Skip to content

Commit 953b017

Browse files
Merge pull request #815 from decentraland/fix/fix-slack-rating-notification-for-worlds
refactor: enhance isWorld type guard to include non-aggregate WorldAttributes detection
2 parents 8c44252 + 8db7d77 commit 953b017

File tree

3 files changed

+149
-1
lines changed

3 files changed

+149
-1
lines changed
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { SceneContentRating } from "decentraland-gatsby/dist/utils/api/Catalyst.types"
2+
3+
import { isPlace, isWorld } from "./entityTypes"
4+
import { AggregatePlaceAttributes } from "../Place/types"
5+
import { AggregateWorldAttributes, WorldAttributes } from "../World/types"
6+
7+
const baseWorldAttributes: WorldAttributes = {
8+
id: "testworld.dcl.eth",
9+
world_name: "testworld.dcl.eth",
10+
title: "Test World",
11+
description: null,
12+
image: null,
13+
owner: null,
14+
content_rating: SceneContentRating.TEEN,
15+
categories: [],
16+
likes: 0,
17+
dislikes: 0,
18+
favorites: 0,
19+
like_rate: 0.5,
20+
like_score: 0,
21+
disabled: false,
22+
disabled_at: null,
23+
created_at: new Date(),
24+
updated_at: new Date(),
25+
show_in_places: true,
26+
single_player: false,
27+
skybox_time: null,
28+
is_private: false,
29+
highlighted: false,
30+
highlighted_image: null,
31+
ranking: null,
32+
}
33+
34+
const aggregateWorldAttributes: AggregateWorldAttributes = {
35+
...baseWorldAttributes,
36+
user_like: false,
37+
user_dislike: false,
38+
user_favorite: false,
39+
user_visits: 0,
40+
world: true,
41+
contact_name: null,
42+
base_position: "0,0",
43+
deployed_at: null,
44+
}
45+
46+
const aggregatePlaceAttributes: AggregatePlaceAttributes = {
47+
id: "place-uuid",
48+
world_name: null,
49+
title: "Genesis Plaza",
50+
description: null,
51+
image: null,
52+
owner: null,
53+
content_rating: SceneContentRating.TEEN,
54+
categories: [],
55+
likes: 0,
56+
dislikes: 0,
57+
favorites: 0,
58+
like_rate: 0.5,
59+
like_score: 0,
60+
disabled: false,
61+
disabled_at: null,
62+
created_at: new Date(),
63+
updated_at: new Date(),
64+
base_position: "0,0",
65+
positions: ["0,0"],
66+
contact_name: null,
67+
contact_email: null,
68+
highlighted: false,
69+
highlighted_image: null,
70+
world: false,
71+
world_id: null,
72+
deployed_at: new Date(),
73+
creator_address: null,
74+
sdk: null,
75+
ranking: null,
76+
textsearch: null,
77+
user_like: false,
78+
user_dislike: false,
79+
user_favorite: false,
80+
user_visits: 0,
81+
}
82+
83+
describe("isWorld", () => {
84+
describe("with a non-aggregate WorldAttributes (e.g. from WorldModel.findByWorldName)", () => {
85+
it("returns true", () => {
86+
expect(isWorld(baseWorldAttributes)).toBe(true)
87+
})
88+
})
89+
90+
describe("with an aggregate AggregateWorldAttributes", () => {
91+
it("returns true", () => {
92+
expect(isWorld(aggregateWorldAttributes)).toBe(true)
93+
})
94+
})
95+
96+
describe("with an aggregate AggregatePlaceAttributes (world: false)", () => {
97+
it("returns false", () => {
98+
expect(isWorld(aggregatePlaceAttributes)).toBe(false)
99+
})
100+
})
101+
102+
describe("with an aggregate AggregatePlaceAttributes that is a world scene (world: true)", () => {
103+
it("returns true via the aggregate world flag", () => {
104+
const worldScenePlace: AggregatePlaceAttributes = {
105+
...aggregatePlaceAttributes,
106+
world: true,
107+
world_name: "myworld.dcl.eth",
108+
}
109+
expect(isWorld(worldScenePlace)).toBe(true)
110+
})
111+
})
112+
})
113+
114+
describe("isPlace", () => {
115+
describe("with an aggregate AggregatePlaceAttributes", () => {
116+
it("returns true", () => {
117+
expect(isPlace(aggregatePlaceAttributes)).toBe(true)
118+
})
119+
})
120+
121+
describe("with an aggregate AggregateWorldAttributes", () => {
122+
it("returns false", () => {
123+
expect(isPlace(aggregateWorldAttributes)).toBe(false)
124+
})
125+
})
126+
127+
describe("with a non-aggregate WorldAttributes", () => {
128+
it("returns false", () => {
129+
expect(isPlace(baseWorldAttributes)).toBe(false)
130+
})
131+
})
132+
})

src/entities/shared/entityTypes.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,16 @@ export type AnyEntityAttributes =
3434
/**
3535
* Type guard to check if an entity is a world.
3636
* Works for aggregate, non-aggregate, and base entity types.
37+
* For aggregate entities, checks the `world` boolean field.
38+
* For non-aggregate WorldAttributes (e.g. from WorldModel queries), detects via
39+
* `show_in_places`, which is unique to WorldAttributes and absent from PlaceAttributes.
3740
*/
3841
export function isWorld(
3942
entity: AnyEntityAttributes | AggregateBaseEntityAttributes
4043
): entity is WorldAttributes | AggregateWorldAttributes {
41-
return "world" in entity && entity.world === true
44+
return (
45+
("world" in entity && entity.world === true) || "show_in_places" in entity
46+
)
4247
}
4348

4449
/**

test/integration/handleWorldSettingsChanged.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import supertest from "supertest"
22

33
import { handleWorldSettingsChanged } from "../../src/entities/CheckScenes/task/handleWorldSettingsChanged"
4+
import * as SlackUtils from "../../src/entities/Slack/utils"
45
import {
56
createWorldSettingsChangedEvent,
67
createWorldSettingsDowngradeRatingEvent,
@@ -157,6 +158,16 @@ describe("handleWorldSettingsChanged integration", () => {
157158

158159
expect(response.body.data.content_rating).toBe("T")
159160
})
161+
162+
it("should call notifyDowngradeRating with the world entity (world_name defined, not undefined base_position)", () => {
163+
expect(SlackUtils.notifyDowngradeRating).toHaveBeenCalledWith(
164+
expect.objectContaining({
165+
world_name: "existingworld.dcl.eth",
166+
show_in_places: expect.anything(),
167+
}),
168+
expect.any(String)
169+
)
170+
})
160171
})
161172
})
162173

0 commit comments

Comments
 (0)