Skip to content

Commit 0ae062a

Browse files
add more tests
1 parent 4615f8e commit 0ae062a

File tree

7 files changed

+1469
-35
lines changed

7 files changed

+1469
-35
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"files": ["tasks", "dist", "vendor", "src", "index.js", "index.d.ts"],
2222
"scripts": {
2323
"start": "serve -l 5173",
24-
"test": "npm run build && npx playwright test",
24+
"test": "npm run build && npx playwright test --reporter=html",
2525
"build": "node tasks/build.js",
2626
"lint": "npx @biomejs/biome check --write .",
2727
"precommit": "lint-staged",

tests/customElements.spec.js

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test.beforeEach(async ({ page }) => {
4+
await page.goto("/");
5+
});
6+
7+
test.describe("oc-client : custom elements lifecycle", () => {
8+
test.beforeEach(async ({ page }) => {
9+
await page.evaluate(() => {
10+
window.originalConsoleLog = console.log;
11+
console.log = () => {};
12+
});
13+
});
14+
15+
test.afterEach(async ({ page }) => {
16+
await page.evaluate(() => {
17+
console.log = window.originalConsoleLog;
18+
delete window.originalConsoleLog;
19+
oc.events.reset();
20+
});
21+
});
22+
23+
test("should handle connectedCallback with lifecycle enabled", async ({
24+
page,
25+
}) => {
26+
const result = await page.evaluate(() => {
27+
return new Promise((resolve) => {
28+
let renderNestedCalled = false;
29+
const originalRenderNested = oc.renderNestedComponent;
30+
31+
oc.renderNestedComponent = (component, callback) => {
32+
renderNestedCalled = true;
33+
callback();
34+
};
35+
36+
const component = document.createElement("oc-component");
37+
component.setAttribute("href", "https://example.com/component");
38+
39+
document.body.appendChild(component);
40+
41+
setTimeout(() => {
42+
oc.renderNestedComponent = originalRenderNested;
43+
resolve({
44+
renderNestedCalled,
45+
isConnected: component.isConnected,
46+
});
47+
}, 100);
48+
});
49+
});
50+
51+
expect(result.renderNestedCalled).toBe(true);
52+
expect(result.isConnected).toBe(true);
53+
});
54+
55+
test("should handle connectedCallback with lifecycle disabled via attribute", async ({
56+
page,
57+
}) => {
58+
const result = await page.evaluate(() => {
59+
return new Promise((resolve) => {
60+
let renderNestedCalled = false;
61+
const originalRenderNested = oc.renderNestedComponent;
62+
63+
oc.renderNestedComponent = (component, callback) => {
64+
renderNestedCalled = true;
65+
callback();
66+
};
67+
68+
const component = document.createElement("oc-component");
69+
component.setAttribute("href", "https://example.com/component");
70+
component.setAttribute("disable-lifecycle", "true");
71+
72+
document.body.appendChild(component);
73+
74+
setTimeout(() => {
75+
oc.renderNestedComponent = originalRenderNested;
76+
resolve({
77+
renderNestedCalled,
78+
disableLifecycleAttr: component.getAttribute("disable-lifecycle"),
79+
});
80+
}, 100);
81+
});
82+
});
83+
84+
expect(result.renderNestedCalled).toBe(false);
85+
expect(result.disableLifecycleAttr).toBe("true");
86+
});
87+
88+
test("should handle disconnectedCallback and fire unrendered event", async ({
89+
page,
90+
}) => {
91+
const result = await page.evaluate(() => {
92+
return new Promise((resolve) => {
93+
let unrenderedEventFired = false;
94+
let eventData = null;
95+
96+
oc.events.on("oc:unrendered", (e, data) => {
97+
unrenderedEventFired = true;
98+
eventData = data;
99+
});
100+
101+
const component = document.createElement("oc-component");
102+
component.setAttribute("href", "https://example.com/component");
103+
component.setAttribute("id", "test-component-123");
104+
component.setAttribute("data-rendered", "true");
105+
106+
document.body.appendChild(component);
107+
108+
setTimeout(() => {
109+
component.remove();
110+
111+
setTimeout(() => {
112+
resolve({
113+
unrenderedEventFired,
114+
eventElementId: eventData?.id,
115+
eventElement: eventData?.element === component,
116+
});
117+
}, 50);
118+
}, 50);
119+
});
120+
});
121+
122+
expect(result.unrenderedEventFired).toBe(true);
123+
expect(result.eventElementId).toBe("test-component-123");
124+
expect(result.eventElement).toBe(true);
125+
});
126+
127+
test("should call unmount method when component is disconnected", async ({
128+
page,
129+
}) => {
130+
const result = await page.evaluate(() => {
131+
return new Promise((resolve) => {
132+
let unmountCalled = false;
133+
134+
const component = document.createElement("oc-component");
135+
component.setAttribute("href", "https://example.com/component");
136+
component.setAttribute("id", "test-component-456");
137+
component.setAttribute("data-rendered", "true");
138+
139+
component.unmount = () => {
140+
unmountCalled = true;
141+
};
142+
143+
document.body.appendChild(component);
144+
145+
setTimeout(() => {
146+
component.remove();
147+
148+
setTimeout(() => {
149+
resolve({
150+
unmountCalled,
151+
hasDataRendered: component.hasAttribute("data-rendered"),
152+
});
153+
}, 50);
154+
}, 50);
155+
});
156+
});
157+
158+
expect(result.unmountCalled).toBe(true);
159+
expect(result.hasDataRendered).toBe(false);
160+
});
161+
162+
test("should handle disable-lifecycle attribute variations", async ({
163+
page,
164+
}) => {
165+
const result = await page.evaluate(() => {
166+
return new Promise((resolve) => {
167+
let renderCalls = 0;
168+
const originalRenderNested = oc.renderNestedComponent;
169+
170+
oc.renderNestedComponent = (component, callback) => {
171+
renderCalls++;
172+
callback();
173+
};
174+
175+
const component1 = document.createElement("oc-component");
176+
component1.setAttribute("disable-lifecycle", "");
177+
document.body.appendChild(component1);
178+
179+
const component2 = document.createElement("oc-component");
180+
component2.setAttribute("disable-lifecycle", "false");
181+
document.body.appendChild(component2);
182+
183+
setTimeout(() => {
184+
oc.renderNestedComponent = originalRenderNested;
185+
resolve({
186+
renderCalls,
187+
component1DisableAttr: component1.getAttribute("disable-lifecycle"),
188+
component2DisableAttr: component2.getAttribute("disable-lifecycle"),
189+
});
190+
}, 100);
191+
});
192+
});
193+
194+
expect(result.renderCalls).toBe(1);
195+
expect(result.component1DisableAttr).toBe("");
196+
expect(result.component2DisableAttr).toBe("false");
197+
});
198+
199+
test("should not call unmount if component was never rendered", async ({
200+
page,
201+
}) => {
202+
const result = await page.evaluate(() => {
203+
return new Promise((resolve) => {
204+
let unmountCalled = false;
205+
206+
const component = document.createElement("oc-component");
207+
component.setAttribute("href", "https://example.com/component");
208+
component.setAttribute("id", "test-component-789");
209+
210+
component.unmount = () => {
211+
unmountCalled = true;
212+
};
213+
214+
document.body.appendChild(component);
215+
216+
setTimeout(() => {
217+
component.remove();
218+
219+
setTimeout(() => {
220+
resolve({
221+
unmountCalled,
222+
hasDataRendered: component.hasAttribute("data-rendered"),
223+
});
224+
}, 50);
225+
}, 50);
226+
});
227+
});
228+
229+
expect(result.unmountCalled).toBe(false);
230+
expect(result.hasDataRendered).toBe(false);
231+
});
232+
233+
test("should handle multiple connect/disconnect cycles", async ({ page }) => {
234+
const result = await page.evaluate(() => {
235+
return new Promise((resolve) => {
236+
let renderCalls = 0;
237+
let unmountCalls = 0;
238+
const originalRenderNested = oc.renderNestedComponent;
239+
240+
oc.renderNestedComponent = (component, callback) => {
241+
renderCalls++;
242+
component.setAttribute("data-rendered", "true");
243+
callback();
244+
};
245+
246+
const component = document.createElement("oc-component");
247+
component.setAttribute("href", "https://example.com/component");
248+
component.setAttribute("id", "test-component-cycle");
249+
250+
component.unmount = () => {
251+
unmountCalls++;
252+
};
253+
254+
document.body.appendChild(component);
255+
256+
setTimeout(() => {
257+
component.remove();
258+
259+
setTimeout(() => {
260+
document.body.appendChild(component);
261+
262+
setTimeout(() => {
263+
component.remove();
264+
265+
setTimeout(() => {
266+
oc.renderNestedComponent = originalRenderNested;
267+
resolve({
268+
renderCalls,
269+
unmountCalls,
270+
});
271+
}, 50);
272+
}, 50);
273+
}, 50);
274+
}, 50);
275+
});
276+
});
277+
278+
expect(result.renderCalls).toBe(2);
279+
expect(result.unmountCalls).toBe(2);
280+
});
281+
});

tests/edgeCases.spec.js

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -207,40 +207,6 @@ test.describe("oc-client : edge cases", () => {
207207
expect(result.wasDelayed).toBe(true);
208208
});
209209

210-
test("should handle load with jQuery-like placeholder", async ({ page }) => {
211-
const result = await page.evaluate(() => {
212-
return new Promise((resolve) => {
213-
const placeholder = document.createElement("div");
214-
placeholder.id = "test-placeholder";
215-
document.body.appendChild(placeholder);
216-
217-
const jqueryLikePlaceholder = [placeholder];
218-
jqueryLikePlaceholder[0] = placeholder;
219-
220-
oc.load(
221-
jqueryLikePlaceholder,
222-
"https://example.com/component",
223-
(component) => {
224-
resolve({
225-
callbackCalled: true,
226-
componentExists: !!component,
227-
placeholderHasOcComponent:
228-
placeholder.querySelector("oc-component") !== null,
229-
placeholderInnerHTML: placeholder.innerHTML,
230-
});
231-
},
232-
);
233-
});
234-
});
235-
236-
expect(result.callbackCalled).toBe(true);
237-
expect(result.placeholderHasOcComponent).toBe(true);
238-
expect(result.placeholderInnerHTML).toContain("oc-component");
239-
expect(result.placeholderInnerHTML).toContain(
240-
'href="https://example.com/component"',
241-
);
242-
});
243-
244210
test("should handle getAction with missing component", async ({ page }) => {
245211
const result = await page.evaluate(() => {
246212
return new Promise((resolve) => {

0 commit comments

Comments
 (0)