Skip to content

Commit b225a71

Browse files
feat(VB-277):unit test cases addd
1 parent e991dd1 commit b225a71

3 files changed

Lines changed: 313 additions & 20 deletions

File tree

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
import { clearVisibilityStyles, restoreVisibilityStyles } from "../clearStyles";
2+
3+
describe("clearStyles", () => {
4+
let element: HTMLDivElement;
5+
6+
beforeEach(() => {
7+
element = document.createElement("div");
8+
document.body.appendChild(element);
9+
});
10+
11+
afterEach(() => {
12+
document.body.removeChild(element);
13+
});
14+
15+
describe("clearVisibilityStyles", () => {
16+
it("should hide element and disable transitions/animations", () => {
17+
// Set initial styles
18+
element.style.visibility = "visible";
19+
element.style.transition = "all 0.3s ease";
20+
element.style.animation = "fadeIn 1s";
21+
22+
clearVisibilityStyles(element);
23+
24+
expect(element.style.visibility).toBe("hidden");
25+
expect(element.style.transition).toBe("none");
26+
expect(element.style.animation).toBe("none");
27+
});
28+
29+
it("should handle element with no initial styles", () => {
30+
clearVisibilityStyles(element);
31+
32+
expect(element.style.visibility).toBe("hidden");
33+
expect(element.style.transition).toBe("none");
34+
expect(element.style.animation).toBe("none");
35+
});
36+
37+
it("should store original style values", () => {
38+
// Set initial styles
39+
element.style.visibility = "visible";
40+
element.style.transition = "opacity 0.5s";
41+
element.style.animation = "slideIn 2s";
42+
43+
clearVisibilityStyles(element);
44+
45+
// Verify styles are cleared
46+
expect(element.style.visibility).toBe("hidden");
47+
expect(element.style.transition).toBe("none");
48+
expect(element.style.animation).toBe("none");
49+
50+
// Verify we can restore (this indirectly tests that values were stored)
51+
restoreVisibilityStyles(element);
52+
expect(element.style.visibility).toBe("visible");
53+
expect(element.style.transition).toBe("opacity 0.5s");
54+
expect(element.style.animation).toBe("slideIn 2s");
55+
});
56+
57+
it("should handle multiple calls on the same element", () => {
58+
element.style.visibility = "visible";
59+
element.style.transition = "all 0.3s";
60+
61+
// First call
62+
clearVisibilityStyles(element);
63+
expect(element.style.visibility).toBe("hidden");
64+
65+
// Second call should not overwrite stored values
66+
element.style.visibility = "hidden"; // Simulate current state
67+
clearVisibilityStyles(element);
68+
69+
// Restore should still work with original values
70+
restoreVisibilityStyles(element);
71+
expect(element.style.visibility).toBe("visible");
72+
expect(element.style.transition).toBe("all 0.3s");
73+
});
74+
75+
it("should handle empty string style values", () => {
76+
element.style.visibility = "";
77+
element.style.transition = "";
78+
element.style.animation = "";
79+
80+
clearVisibilityStyles(element);
81+
restoreVisibilityStyles(element);
82+
83+
expect(element.style.visibility).toBe("");
84+
expect(element.style.transition).toBe("");
85+
expect(element.style.animation).toBe("");
86+
});
87+
});
88+
89+
describe("restoreVisibilityStyles", () => {
90+
it("should restore original styles after clearing", () => {
91+
const originalVisibility = "visible";
92+
const originalTransition = "all 0.3s ease-in-out";
93+
const originalAnimation = "bounce 1s infinite";
94+
95+
element.style.visibility = originalVisibility;
96+
element.style.transition = originalTransition;
97+
element.style.animation = originalAnimation;
98+
99+
clearVisibilityStyles(element);
100+
restoreVisibilityStyles(element);
101+
102+
expect(element.style.visibility).toBe(originalVisibility);
103+
expect(element.style.transition).toBe(originalTransition);
104+
expect(element.style.animation).toBe(originalAnimation);
105+
});
106+
107+
it("should handle restore without prior clear (no stored values)", () => {
108+
element.style.visibility = "visible";
109+
element.style.transition = "all 0.3s";
110+
111+
// Call restore without clearing first
112+
restoreVisibilityStyles(element);
113+
114+
// Should not modify styles when no stored values exist
115+
expect(element.style.visibility).toBe("visible");
116+
expect(element.style.transition).toBe("all 0.3s");
117+
});
118+
119+
it("should remove stored values after restoration", () => {
120+
element.style.visibility = "visible";
121+
clearVisibilityStyles(element);
122+
restoreVisibilityStyles(element);
123+
124+
// Second restore call should not affect styles
125+
element.style.visibility = "hidden";
126+
restoreVisibilityStyles(element);
127+
expect(element.style.visibility).toBe("hidden"); // Should remain unchanged
128+
});
129+
130+
it("should restore empty string values correctly", () => {
131+
// Start with empty styles (which is the default)
132+
clearVisibilityStyles(element);
133+
restoreVisibilityStyles(element);
134+
135+
expect(element.style.visibility).toBe("");
136+
expect(element.style.transition).toBe("");
137+
expect(element.style.animation).toBe("");
138+
});
139+
140+
it("should handle partial style restoration", () => {
141+
element.style.visibility = "visible";
142+
element.style.transition = "opacity 0.5s";
143+
// animation is not set (empty)
144+
145+
clearVisibilityStyles(element);
146+
restoreVisibilityStyles(element);
147+
148+
expect(element.style.visibility).toBe("visible");
149+
expect(element.style.transition).toBe("opacity 0.5s");
150+
expect(element.style.animation).toBe("");
151+
});
152+
});
153+
154+
describe("WeakMap storage behavior", () => {
155+
it("should handle multiple elements independently", () => {
156+
const element1 = document.createElement("div");
157+
const element2 = document.createElement("div");
158+
document.body.appendChild(element1);
159+
document.body.appendChild(element2);
160+
161+
element1.style.visibility = "visible";
162+
element1.style.transition = "all 0.3s";
163+
element2.style.visibility = "hidden";
164+
element2.style.animation = "fadeIn 1s";
165+
166+
clearVisibilityStyles(element1);
167+
clearVisibilityStyles(element2);
168+
169+
restoreVisibilityStyles(element1);
170+
restoreVisibilityStyles(element2);
171+
172+
expect(element1.style.visibility).toBe("visible");
173+
expect(element1.style.transition).toBe("all 0.3s");
174+
expect(element1.style.animation).toBe(""); // Was not set originally
175+
176+
expect(element2.style.visibility).toBe("hidden");
177+
expect(element2.style.transition).toBe(""); // Was not set originally
178+
expect(element2.style.animation).toBe("fadeIn 1s");
179+
180+
document.body.removeChild(element1);
181+
document.body.removeChild(element2);
182+
});
183+
184+
it("should not leak memory after element removal", () => {
185+
const tempElement = document.createElement("div");
186+
tempElement.style.visibility = "visible";
187+
188+
clearVisibilityStyles(tempElement);
189+
190+
// Element is not in DOM and has no references
191+
// WeakMap should allow garbage collection
192+
// This test mainly documents the expected behavior
193+
expect(tempElement.style.visibility).toBe("hidden");
194+
});
195+
});
196+
197+
describe("CSS property handling edge cases", () => {
198+
it("should handle complex transition values", () => {
199+
element.style.transition =
200+
"opacity 0.3s ease-in-out, transform 0.5s linear";
201+
202+
clearVisibilityStyles(element);
203+
expect(element.style.transition).toBe("none");
204+
205+
restoreVisibilityStyles(element);
206+
expect(element.style.transition).toBe(
207+
"opacity 0.3s ease-in-out, transform 0.5s linear"
208+
);
209+
});
210+
211+
it("should handle complex animation values", () => {
212+
element.style.animation =
213+
"slideIn 0.5s ease-out, fadeIn 1s linear infinite";
214+
215+
clearVisibilityStyles(element);
216+
expect(element.style.animation).toBe("none");
217+
218+
restoreVisibilityStyles(element);
219+
expect(element.style.animation).toBe(
220+
"slideIn 0.5s ease-out, fadeIn 1s linear infinite"
221+
);
222+
});
223+
224+
it("should handle inherit and initial values", () => {
225+
element.style.visibility = "inherit";
226+
element.style.transition = "initial";
227+
element.style.animation = "inherit";
228+
229+
clearVisibilityStyles(element);
230+
restoreVisibilityStyles(element);
231+
232+
expect(element.style.visibility).toBe("inherit");
233+
expect(element.style.transition).toBe("initial");
234+
expect(element.style.animation).toBe("inherit");
235+
});
236+
});
237+
});

src/visualBuilder/utils/__test__/enableInlineEditing.test.ts

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { handleFieldInput, handleFieldKeyDown } from "../handleFieldMouseDown";
1212
import { pasteAsPlainText } from "../pasteAsPlainText";
1313
import { FieldDataType } from "../types/index.types";
1414
import { updateFocussedState as updateFocussedStateActual } from "../updateFocussedState";
15+
import { clearVisibilityStyles } from "../clearStyles";
1516

1617
const isEllipsisActive = vi.mocked(isEllipsisActiveActual);
1718
const generatePseudoEditableElement = vi.mocked(
@@ -67,6 +68,11 @@ vi.mock("../pasteAsPlainText", () => ({
6768
pasteAsPlainText: vi.fn(),
6869
}));
6970

71+
vi.mock("../clearStyles", () => ({
72+
clearVisibilityStyles: vi.fn(),
73+
restoreVisibilityStyles: vi.fn(),
74+
}));
75+
7076
describe("enableInlineEditing", () => {
7177
let editableElement: HTMLDivElement;
7278
let mockedEditableElement: MockedObject<HTMLDivElement>;
@@ -165,7 +171,7 @@ describe("enableInlineEditing", () => {
165171
});
166172

167173
expect(generatePseudoEditableElement).toHaveBeenCalled();
168-
expect(editableElement.style.visibility).toBe("hidden");
174+
expect(clearVisibilityStyles).toHaveBeenCalledWith(editableElement);
169175
expect(resizeObserver.observe).toHaveBeenCalled();
170176
});
171177

@@ -184,7 +190,7 @@ describe("enableInlineEditing", () => {
184190
});
185191

186192
expect(generatePseudoEditableElement).toHaveBeenCalled();
187-
expect(editableElement.style.visibility).toBe("hidden");
193+
expect(clearVisibilityStyles).toHaveBeenCalledWith(editableElement);
188194
});
189195

190196
it("should set field type attribute on pseudo element", () => {
@@ -294,9 +300,9 @@ describe("enableInlineEditing", () => {
294300
});
295301

296302
expect(generatePseudoEditableElement).toHaveBeenCalled();
297-
expect(editableElement.style.visibility).toBe("hidden");
303+
expect(clearVisibilityStyles).toHaveBeenCalledWith(editableElement);
298304
expect(resizeObserver.observe).toHaveBeenCalled();
299-
305+
300306
document.body.removeChild(editableElement);
301307
});
302308

@@ -312,7 +318,9 @@ describe("enableInlineEditing", () => {
312318
},
313319
});
314320

315-
expect(editableElement.getAttribute("data-cs-last-edited")).toBe("true");
321+
expect(editableElement.getAttribute("data-cs-last-edited")).toBe(
322+
"true"
323+
);
316324
});
317325

318326
it("should create pseudo element when field is last edited even with same content", () => {
@@ -333,8 +341,8 @@ describe("enableInlineEditing", () => {
333341
});
334342

335343
expect(generatePseudoEditableElement).toHaveBeenCalled();
336-
expect(editableElement.style.visibility).toBe("hidden");
337-
344+
expect(clearVisibilityStyles).toHaveBeenCalledWith(editableElement);
345+
338346
document.body.removeChild(editableElement);
339347
});
340348

@@ -358,8 +366,10 @@ describe("enableInlineEditing", () => {
358366
});
359367

360368
expect(generatePseudoEditableElement).not.toHaveBeenCalled();
361-
expect(editableElement.style.visibility).toBe("");
362-
expect(editableElement.getAttribute("data-cs-last-edited")).toBe("true");
369+
expect(clearVisibilityStyles).not.toHaveBeenCalled();
370+
expect(editableElement.getAttribute("data-cs-last-edited")).toBe(
371+
"true"
372+
);
363373

364374
document.body.removeChild(otherElement);
365375
});
@@ -380,13 +390,56 @@ describe("enableInlineEditing", () => {
380390
});
381391

382392
expect(generatePseudoEditableElement).toHaveBeenCalled();
383-
expect(editableElement.style.visibility).toBe("hidden");
384-
385-
const pseudoElement = visualBuilderContainer.querySelector(".visual-builder__pseudo-editable-element");
393+
expect(clearVisibilityStyles).toHaveBeenCalledWith(editableElement);
394+
395+
const pseudoElement = visualBuilderContainer.querySelector(
396+
".visual-builder__pseudo-editable-element"
397+
);
386398
expect(pseudoElement).toBeTruthy();
387399
expect(pseudoElement?.getAttribute("data-cslp")).toBeNull();
388-
expect(editableElement.getAttribute("data-cs-last-edited")).toBe("true");
389-
400+
expect(editableElement.getAttribute("data-cs-last-edited")).toBe(
401+
"true"
402+
);
403+
390404
document.body.removeChild(editableElement);
391405
});
406+
407+
it("should call clearVisibilityStyles to immediately hide element when creating pseudo element", () => {
408+
// Test that clearVisibilityStyles is called specifically for hiding transitions/animations
409+
enableInlineEditing({
410+
expectedFieldData: "Different content",
411+
editableElement,
412+
fieldType: FieldDataType.SINGLELINE,
413+
elements: {
414+
visualBuilderContainer,
415+
resizeObserver,
416+
lastEditedField: null,
417+
},
418+
});
419+
420+
// Verify clearVisibilityStyles was called with the correct element
421+
expect(clearVisibilityStyles).toHaveBeenCalledTimes(1);
422+
expect(clearVisibilityStyles).toHaveBeenCalledWith(editableElement);
423+
424+
// Verify it was called before other operations
425+
expect(generatePseudoEditableElement).toHaveBeenCalled();
426+
expect(resizeObserver.observe).toHaveBeenCalled();
427+
});
428+
429+
it("should not call clearVisibilityStyles when pseudo element is not needed", () => {
430+
// When content matches and no ellipsis, no pseudo element should be created
431+
enableInlineEditing({
432+
expectedFieldData: "Test content",
433+
editableElement,
434+
fieldType: FieldDataType.SINGLELINE,
435+
elements: {
436+
visualBuilderContainer,
437+
resizeObserver,
438+
lastEditedField: null,
439+
},
440+
});
441+
442+
expect(clearVisibilityStyles).not.toHaveBeenCalled();
443+
expect(generatePseudoEditableElement).not.toHaveBeenCalled();
444+
});
392445
});

0 commit comments

Comments
 (0)