Skip to content

Commit 6fdde79

Browse files
sapnilbiswaszealot-zew
authored andcommitted
test: add unit tests for GlobalTag
1 parent 84e8052 commit 6fdde79

1 file changed

Lines changed: 213 additions & 33 deletions

File tree

planet/js/__tests__/GlobalTag.test.js

Lines changed: 213 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -62,64 +62,244 @@ function makePlanet(tagName = "music", isDisplay = "1") {
6262
};
6363
}
6464

65-
// ---------------------------------------------------------------------------
66-
// Regression: toTitleCase must be reachable when GlobalTag.render() runs
67-
// ---------------------------------------------------------------------------
65+
describe("GlobalTag", () => {
66+
let tag;
67+
let mockPlanet;
6868

69-
describe("GlobalTag – regression: toTitleCase dependency after utils modularization", () => {
7069
beforeEach(() => {
7170
addChipContainer("primarychips");
7271
addChipContainer("morechips");
73-
global._ = str => str; // identity stub for translation helper
72+
global._ = str => str;
73+
74+
mockPlanet = {
75+
GlobalPlanet: {
76+
selectSpecialTag: jest.fn(),
77+
refreshTagList: jest.fn()
78+
},
79+
TagsManifest: {
80+
1: { TagName: "Music", IsDisplayTag: "1" },
81+
2: { TagName: "Art", IsDisplayTag: "0" },
82+
3: { TagName: "Math", IsDisplayTag: "1" }
83+
}
84+
};
85+
86+
tag = new GlobalTag(mockPlanet);
7487
});
7588

7689
afterEach(() => {
7790
document.body.innerHTML = "";
7891
delete global._;
92+
jest.restoreAllMocks();
7993
});
8094

81-
it("toTitleCase is defined on global after loading utils-logic", () => {
82-
expect(typeof global.toTitleCase).toBe("function");
83-
});
95+
describe("regression tests for toTitleCase", () => {
96+
it("toTitleCase is defined on global after loading utils-logic", () => {
97+
expect(typeof global.toTitleCase).toBe("function");
98+
});
99+
100+
it("toTitleCase capitalises the first letter of a string", () => {
101+
expect(global.toTitleCase("hello")).toBe("Hello");
102+
});
103+
104+
it("toTitleCase returns undefined for non-string input", () => {
105+
expect(global.toTitleCase(123)).toBeUndefined();
106+
});
107+
108+
it("toTitleCase returns empty string for empty input", () => {
109+
expect(global.toTitleCase("")).toBe("");
110+
});
111+
112+
it("GlobalTag.render() does not throw ReferenceError for toTitleCase", () => {
113+
const tag2 = new GlobalTag(makePlanet("music"));
114+
expect(() => tag2.init({ id: 1 })).not.toThrow();
115+
});
116+
117+
it("GlobalTag.render() sets textContent via toTitleCase", () => {
118+
const tag2 = new GlobalTag(makePlanet("art"));
119+
tag2.init({ id: 1 });
120+
expect(tag2.tagElement.textContent).toBe("Art");
121+
});
84122

85-
it("toTitleCase capitalises the first letter of a string", () => {
86-
expect(global.toTitleCase("hello")).toBe("Hello");
123+
it("display tag is appended to #primarychips", () => {
124+
const tag2 = new GlobalTag(makePlanet("game", "1"));
125+
tag2.init({ id: 1 });
126+
expect(document.getElementById("primarychips").children.length).toBeGreaterThan(0);
127+
});
128+
129+
it("non-display tag is appended to #morechips", () => {
130+
const tag2 = new GlobalTag(makePlanet("sensors", "0"));
131+
tag2.init({ id: 1 });
132+
expect(document.getElementById("morechips").children.length).toBeGreaterThan(0);
133+
});
134+
135+
it("special tag render() also does not throw", () => {
136+
const tag2 = new GlobalTag(makePlanet());
137+
expect(() => tag2.init({ name: "All Projects", func: jest.fn() })).not.toThrow();
138+
});
87139
});
88140

89-
it("toTitleCase returns undefined for non-string input", () => {
90-
expect(global.toTitleCase(123)).toBeUndefined();
141+
describe("constructor", () => {
142+
it("should initialize with default values", () => {
143+
expect(tag.Planet).toBe(mockPlanet);
144+
expect(tag.id).toBeNull();
145+
expect(tag.name).toBeNull();
146+
expect(tag.func).toBeNull();
147+
expect(tag.IsDisplayTag).toBeNull();
148+
expect(tag.specialTag).toBeNull();
149+
expect(tag.tagElement).toBeNull();
150+
expect(tag.selected).toBe(false);
151+
expect(tag.selectedClass).toBeNull();
152+
});
153+
154+
it("should reference globalPlanet from Planet", () => {
155+
expect(tag.globalPlanet).toBe(mockPlanet.GlobalPlanet);
156+
});
91157
});
92158

93-
it("toTitleCase returns empty string for empty input", () => {
94-
expect(global.toTitleCase("")).toBe("");
159+
describe("init with regular tag (has id)", () => {
160+
it("should initialize as a non-special tag", () => {
161+
tag.init({ id: "1" });
162+
expect(tag.specialTag).toBe(false);
163+
expect(tag.id).toBe("1");
164+
expect(tag.name).toBe("Music");
165+
expect(tag.func).toBeNull();
166+
expect(tag.selectedClass).toBe("selected");
167+
});
168+
169+
it("should set IsDisplayTag based on TagsManifest", () => {
170+
tag.init({ id: "1" });
171+
expect(tag.IsDisplayTag).toBe(true);
172+
173+
const tag2 = new GlobalTag(mockPlanet);
174+
tag2.init({ id: "2" });
175+
expect(tag2.IsDisplayTag).toBe(false);
176+
});
177+
178+
it("should render into primarychips for display tags", () => {
179+
tag.init({ id: "1" });
180+
const chips = document.getElementById("primarychips");
181+
expect(chips.children.length).toBe(1);
182+
});
183+
184+
it("should render into morechips for non-display tags", () => {
185+
tag.init({ id: "2" });
186+
const chips = document.getElementById("morechips");
187+
expect(chips.children.length).toBe(1);
188+
});
95189
});
96190

97-
it("GlobalTag.render() does not throw ReferenceError for toTitleCase", () => {
98-
const tag = new GlobalTag(makePlanet("music"));
99-
expect(() => tag.init({ id: 1 })).not.toThrow();
191+
describe("init with special tag (no id)", () => {
192+
it("should initialize as a special tag", () => {
193+
const mockFunc = jest.fn();
194+
tag.init({ name: "All Projects", func: mockFunc });
195+
196+
expect(tag.specialTag).toBe(true);
197+
expect(tag.IsDisplayTag).toBe(true);
198+
expect(tag.id).toBeNull();
199+
expect(tag.name).toBe("All Projects");
200+
expect(tag.func).toBe(mockFunc);
201+
expect(tag.selectedClass).toBe("selected-special");
202+
});
203+
204+
it("should render special tags into primarychips", () => {
205+
tag.init({ name: "My Projects", func: jest.fn() });
206+
const chips = document.getElementById("primarychips");
207+
expect(chips.children.length).toBe(1);
208+
});
100209
});
101210

102-
it("GlobalTag.render() sets textContent via toTitleCase", () => {
103-
const tag = new GlobalTag(makePlanet("art"));
104-
tag.init({ id: 1 });
105-
// _ is identity stub, toTitleCase("art") === "Art"
106-
expect(tag.tagElement.textContent).toBe("Art");
211+
describe("render", () => {
212+
it("should create a div element with chipselect and cursor classes", () => {
213+
tag.init({ id: "1" });
214+
expect(tag.tagElement.classList.contains("chipselect")).toBe(true);
215+
expect(tag.tagElement.classList.contains("cursor")).toBe(true);
216+
});
217+
218+
it("should set text content from translated and title-cased name", () => {
219+
const spy = jest.spyOn(global, "toTitleCase");
220+
tag.init({ id: "1" });
221+
expect(spy).toHaveBeenCalled();
222+
expect(tag.tagElement.textContent).toBe("Music");
223+
});
224+
225+
it("should add selectedClass when tag is selected before rendering", () => {
226+
tag.selected = true;
227+
tag.selectedClass = "selected";
228+
tag.name = "Music";
229+
tag.IsDisplayTag = true;
230+
tag.id = "1";
231+
tag.specialTag = false;
232+
233+
tag.render();
234+
235+
expect(tag.tagElement.classList.contains("selected")).toBe(true);
236+
});
237+
238+
it("should not add selectedClass when tag is not selected", () => {
239+
tag.init({ id: "1" });
240+
expect(tag.tagElement.classList.contains("selected")).toBe(false);
241+
});
107242
});
108243

109-
it("display tag is appended to #primarychips", () => {
110-
const tag = new GlobalTag(makePlanet("game", "1"));
111-
tag.init({ id: 1 });
112-
expect(document.getElementById("primarychips").children.length).toBeGreaterThan(0);
244+
describe("select", () => {
245+
it("should add the selectedClass and set selected to true", () => {
246+
tag.init({ id: "1" });
247+
tag.select();
248+
249+
expect(tag.tagElement.classList.contains("selected")).toBe(true);
250+
expect(tag.selected).toBe(true);
251+
});
113252
});
114253

115-
it("non-display tag is appended to #morechips", () => {
116-
const tag = new GlobalTag(makePlanet("sensors", "0"));
117-
tag.init({ id: 1 });
118-
expect(document.getElementById("morechips").children.length).toBeGreaterThan(0);
254+
describe("unselect", () => {
255+
it("should remove the selectedClass and set selected to false", () => {
256+
tag.init({ id: "1" });
257+
tag.select();
258+
tag.unselect();
259+
260+
expect(tag.tagElement.classList.contains("selected")).toBe(false);
261+
expect(tag.selected).toBe(false);
262+
});
119263
});
120264

121-
it("special tag render() also does not throw", () => {
122-
const tag = new GlobalTag(makePlanet());
123-
expect(() => tag.init({ name: "All Projects", func: jest.fn() })).not.toThrow();
265+
describe("onTagClick", () => {
266+
it("should call selectSpecialTag when clicking an unselected special tag", () => {
267+
tag.init({ name: "All Projects", func: jest.fn() });
268+
tag.selected = false;
269+
270+
tag.onTagClick();
271+
272+
expect(mockPlanet.GlobalPlanet.selectSpecialTag).toHaveBeenCalledWith(tag);
273+
});
274+
275+
it("should select a non-special tag and refresh when unselected", () => {
276+
tag.init({ id: "1" });
277+
tag.selected = false;
278+
279+
tag.onTagClick();
280+
281+
expect(tag.selected).toBe(true);
282+
expect(mockPlanet.GlobalPlanet.refreshTagList).toHaveBeenCalled();
283+
});
284+
285+
it("should unselect a non-special tag and refresh when already selected", () => {
286+
tag.init({ id: "1" });
287+
tag.select();
288+
289+
tag.onTagClick();
290+
291+
expect(tag.selected).toBe(false);
292+
expect(mockPlanet.GlobalPlanet.refreshTagList).toHaveBeenCalled();
293+
});
294+
295+
it("should toggle selected special tag via unselect and refresh", () => {
296+
tag.init({ name: "All Projects", func: jest.fn() });
297+
tag.select();
298+
299+
tag.onTagClick();
300+
301+
expect(tag.selected).toBe(false);
302+
expect(mockPlanet.GlobalPlanet.refreshTagList).toHaveBeenCalled();
303+
});
124304
});
125305
});

0 commit comments

Comments
 (0)