Skip to content

Commit d9b2818

Browse files
Merge pull request #140 from opencomponents/add-tests
add more tests
2 parents 410c933 + ca1219e commit d9b2818

File tree

7 files changed

+1299
-14
lines changed

7 files changed

+1299
-14
lines changed

.github/workflows/node.js.yml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,27 @@ name: Node.js CI
55

66
on:
77
push:
8-
branches: [ master ]
8+
branches: [master]
99
pull_request:
10-
branches: [ master ]
10+
branches: [master]
1111

1212
jobs:
1313
build:
14-
1514
runs-on: ubuntu-latest
1615

1716
strategy:
1817
matrix:
19-
node-version: [20.x, 20.x, 22.x]
18+
node-version: [20.x, 22.x, 24.x]
2019
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
2120

2221
steps:
23-
- uses: actions/checkout@v4
24-
- name: Use Node.js ${{ matrix.node-version }}
25-
uses: actions/setup-node@v4
26-
with:
27-
node-version: ${{ matrix.node-version }}
28-
cache: 'npm'
29-
- run: npm ci
30-
- run: npx playwright install --with-deps
31-
- run: npm run build --if-present
32-
- run: npm test
22+
- uses: actions/checkout@v4
23+
- name: Use Node.js ${{ matrix.node-version }}
24+
uses: actions/setup-node@v4
25+
with:
26+
node-version: ${{ matrix.node-version }}
27+
cache: 'npm'
28+
- run: npm ci
29+
- run: npx playwright install --with-deps
30+
- run: npm run build --if-present
31+
- run: npm test

tests/edgeCases.spec.js

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
import { expect, test } from "@playwright/test";
2+
3+
test.beforeEach(async ({ page }) => {
4+
await page.goto("/");
5+
});
6+
7+
test.describe("oc-client : edge cases", () => {
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+
});
20+
});
21+
22+
test("should handle build with special characters in parameters", async ({
23+
page,
24+
}) => {
25+
const result = await page.evaluate(() => {
26+
const options = {
27+
baseUrl: "https://example.com",
28+
name: "test-component",
29+
version: "1.0.0",
30+
parameters: {
31+
message: "Hello & Welcome!",
32+
query: "search=test+value",
33+
encoded: "already%20encoded",
34+
symbols: "!@#$%^&*()",
35+
},
36+
};
37+
38+
return {
39+
html: oc.build(options),
40+
};
41+
});
42+
43+
expect(result.html).toContain("oc-component");
44+
expect(result.html).toContain("href=");
45+
expect(result.html).toContain("Hello%20%26%20Welcome!");
46+
expect(result.html).toContain("search%3Dtest%2Bvalue");
47+
});
48+
49+
test("should handle build with empty parameters", async ({ page }) => {
50+
const result = await page.evaluate(() => {
51+
const options = {
52+
baseUrl: "https://example.com",
53+
name: "test-component",
54+
version: "1.0.0",
55+
parameters: {},
56+
};
57+
58+
return {
59+
html: oc.build(options),
60+
};
61+
});
62+
63+
expect(result.html).toContain("oc-component");
64+
expect(result.html).toContain("test-component/1.0.0/");
65+
expect(result.html).not.toContain("?");
66+
});
67+
68+
test("should handle build without version", async ({ page }) => {
69+
const result = await page.evaluate(() => {
70+
const options = {
71+
baseUrl: "https://example.com",
72+
name: "test-component",
73+
};
74+
75+
return {
76+
html: oc.build(options),
77+
};
78+
});
79+
80+
expect(result.html).toContain("oc-component");
81+
expect(result.html).toContain("test-component/");
82+
expect(result.html).toContain('href="https://example.com/test-component/"');
83+
});
84+
85+
test("should handle build with baseUrl having trailing slash", async ({
86+
page,
87+
}) => {
88+
const result = await page.evaluate(() => {
89+
const options1 = {
90+
baseUrl: "https://example.com/",
91+
name: "test-component",
92+
version: "1.0.0",
93+
};
94+
95+
const options2 = {
96+
baseUrl: "https://example.com",
97+
name: "test-component",
98+
version: "1.0.0",
99+
};
100+
101+
return {
102+
html1: oc.build(options1),
103+
html2: oc.build(options2),
104+
};
105+
});
106+
107+
expect(result.html1).toContain("https://example.com/test-component/1.0.0/");
108+
expect(result.html2).toContain("https://example.com/test-component/1.0.0/");
109+
expect(result.html1).toBe(result.html2);
110+
});
111+
112+
test("should handle renderNestedComponent with jQuery-like object", async ({
113+
page,
114+
}) => {
115+
const result = await page.evaluate(() => {
116+
return new Promise((resolve) => {
117+
const element = document.createElement("oc-component");
118+
element.setAttribute("href", "https://example.com/component");
119+
element.setAttribute("id", "test-component");
120+
document.body.appendChild(element);
121+
122+
const jqueryLikeObject = [element];
123+
jqueryLikeObject[0] = element;
124+
125+
let callbackCalled = false;
126+
127+
oc.renderNestedComponent(jqueryLikeObject, () => {
128+
callbackCalled = true;
129+
});
130+
131+
setTimeout(() => {
132+
resolve({
133+
callbackCalled,
134+
elementHasDataRendering: element.hasAttribute("data-rendering"),
135+
elementDataRendering: element.getAttribute("data-rendering"),
136+
});
137+
}, 100);
138+
});
139+
});
140+
141+
expect(result.elementHasDataRendering).toBe(true);
142+
expect(result.elementDataRendering).toBe("true");
143+
});
144+
145+
test("should handle renderNestedComponent with already rendered component", async ({
146+
page,
147+
}) => {
148+
const result = await page.evaluate(() => {
149+
return new Promise((resolve) => {
150+
const element = document.createElement("oc-component");
151+
element.setAttribute("href", "https://example.com/component");
152+
element.setAttribute("id", "test-component");
153+
element.setAttribute("data-rendered", "true");
154+
document.body.appendChild(element);
155+
156+
let callbackCalled = false;
157+
const startTime = Date.now();
158+
159+
oc.renderNestedComponent(element, () => {
160+
callbackCalled = true;
161+
const endTime = Date.now();
162+
resolve({
163+
callbackCalled,
164+
timeTaken: endTime - startTime,
165+
wasDelayed: endTime - startTime >= 400,
166+
});
167+
});
168+
});
169+
});
170+
171+
expect(result.callbackCalled).toBe(true);
172+
expect(result.wasDelayed).toBe(true);
173+
});
174+
175+
test("should handle renderNestedComponent with currently rendering component", async ({
176+
page,
177+
}) => {
178+
const result = await page.evaluate(() => {
179+
return new Promise((resolve) => {
180+
const element = document.createElement("oc-component");
181+
element.setAttribute("href", "https://example.com/component");
182+
element.setAttribute("id", "test-component");
183+
element.setAttribute("data-rendering", "true");
184+
document.body.appendChild(element);
185+
186+
let callbackCalled = false;
187+
const startTime = Date.now();
188+
189+
oc.renderNestedComponent(element, () => {
190+
callbackCalled = true;
191+
const endTime = Date.now();
192+
resolve({
193+
callbackCalled,
194+
timeTaken: endTime - startTime,
195+
wasDelayed: endTime - startTime >= 400,
196+
});
197+
});
198+
});
199+
});
200+
201+
expect(result.callbackCalled).toBe(true);
202+
expect(result.wasDelayed).toBe(true);
203+
});
204+
205+
test("should handle load with jQuery-like placeholder", async ({ page }) => {
206+
const result = await page.evaluate(() => {
207+
return new Promise((resolve) => {
208+
const placeholder = document.createElement("div");
209+
placeholder.id = "test-placeholder";
210+
document.body.appendChild(placeholder);
211+
212+
const jqueryLikePlaceholder = [placeholder];
213+
jqueryLikePlaceholder[0] = placeholder;
214+
215+
oc.load(
216+
jqueryLikePlaceholder,
217+
"https://example.com/component",
218+
(component) => {
219+
resolve({
220+
callbackCalled: true,
221+
componentExists: !!component,
222+
placeholderHasOcComponent:
223+
placeholder.querySelector("oc-component") !== null,
224+
placeholderInnerHTML: placeholder.innerHTML,
225+
});
226+
},
227+
);
228+
});
229+
});
230+
231+
expect(result.callbackCalled).toBe(true);
232+
expect(result.placeholderHasOcComponent).toBe(true);
233+
expect(result.placeholderInnerHTML).toContain("oc-component");
234+
expect(result.placeholderInnerHTML).toContain(
235+
'href="https://example.com/component"',
236+
);
237+
});
238+
239+
test("should handle getAction with missing component", async ({ page }) => {
240+
const result = await page.evaluate(() => {
241+
return new Promise((resolve) => {
242+
oc.getAction({ component: "non-existent-component" })
243+
.then((props) => {
244+
resolve({
245+
success: true,
246+
props: props,
247+
});
248+
})
249+
.catch((error) => {
250+
resolve({
251+
success: false,
252+
error: error.message || error,
253+
});
254+
});
255+
});
256+
});
257+
258+
expect(result.success).toBe(false);
259+
expect(result.error).toBeDefined();
260+
});
261+
262+
test("should handle multiple rapid renderUnloadedComponents calls", async ({
263+
page,
264+
}) => {
265+
const result = await page.evaluate(() => {
266+
return new Promise((resolve) => {
267+
const component1 = document.createElement("oc-component");
268+
component1.setAttribute("href", "https://example.com/component1");
269+
component1.setAttribute("id", "component1");
270+
document.body.appendChild(component1);
271+
272+
const component2 = document.createElement("oc-component");
273+
component2.setAttribute("href", "https://example.com/component2");
274+
component2.setAttribute("id", "component2");
275+
document.body.appendChild(component2);
276+
277+
let renderCallCount = 0;
278+
const originalRenderNestedComponent = oc.renderNestedComponent;
279+
280+
oc.renderNestedComponent = (component, callback) => {
281+
renderCallCount++;
282+
component.setAttribute("data-rendered", "true");
283+
callback();
284+
};
285+
286+
oc.renderUnloadedComponents();
287+
288+
setTimeout(() => {
289+
oc.renderNestedComponent = originalRenderNestedComponent;
290+
resolve({
291+
renderCallCount,
292+
component1HasDataRendered: component1.hasAttribute("data-rendered"),
293+
component2HasDataRendered: component2.hasAttribute("data-rendered"),
294+
});
295+
}, 100);
296+
});
297+
});
298+
299+
expect(result.renderCallCount).toBeGreaterThan(0);
300+
expect(result.component1HasDataRendered).toBe(true);
301+
expect(result.component2HasDataRendered).toBe(true);
302+
});
303+
});

0 commit comments

Comments
 (0)