Skip to content

Commit db9ad08

Browse files
committed
Add components tests
1 parent 3039db1 commit db9ad08

File tree

3 files changed

+202
-1
lines changed

3 files changed

+202
-1
lines changed

renderers/lit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"service": true
6565
},
6666
"test": {
67-
"command": "node --test --enable-source-maps --test-reporter spec dist/src/0.8/*.test.js dist/src/v0_9/tests/*.test.js",
67+
"command": "node --test --enable-source-maps --test-reporter spec dist/src/0.8/*.test.js dist/src/v0_9/tests/*.test.js dist/src/v0_9/tests/**/*.test.js",
6868
"dependencies": [
6969
"build"
7070
]
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { setupTestDom, teardownTestDom, asyncUpdate } from "../dom-setup.js";
18+
import assert from "node:assert";
19+
import { describe, it, beforeEach, after, before } from "node:test";
20+
import { ComponentContext, MessageProcessor } from "@a2ui/web_core/v0_9";
21+
22+
describe("CheckBox Component", () => {
23+
let basicCatalog: any;
24+
25+
before(async () => {
26+
setupTestDom();
27+
basicCatalog = (await import("../../catalogs/basic/index.js")).basicCatalog;
28+
// Ensure component is registered
29+
await import("../../catalogs/basic/components/CheckBox.js");
30+
});
31+
32+
after(teardownTestDom);
33+
34+
let processor: MessageProcessor<any>;
35+
let surface: any;
36+
37+
beforeEach(() => {
38+
processor = new MessageProcessor([basicCatalog]);
39+
processor.processMessages([
40+
{
41+
version: "v0.9",
42+
createSurface: {
43+
surfaceId: "test-surface",
44+
catalogId: basicCatalog.id,
45+
},
46+
},
47+
{
48+
version: "v0.9",
49+
updateComponents: {
50+
surfaceId: "test-surface",
51+
components: [
52+
{
53+
id: "checkbox_invalid",
54+
component: "CheckBox",
55+
label: "Check me",
56+
value: false,
57+
isValid: false,
58+
validationErrors: ["This is required"],
59+
},
60+
],
61+
},
62+
},
63+
]);
64+
surface = processor.model.getSurface("test-surface")!;
65+
});
66+
67+
it("should render validation error in CheckBox", async () => {
68+
const el = document.createElement("a2ui-checkbox") as any;
69+
document.body.appendChild(el);
70+
71+
const context = new ComponentContext(surface, "checkbox_invalid");
72+
await asyncUpdate(el, (e) => {
73+
e.context = context;
74+
});
75+
76+
const errorDiv = el.shadowRoot.querySelector(".error");
77+
assert.ok(errorDiv);
78+
assert.strictEqual(errorDiv.textContent.trim(), "This is required");
79+
80+
document.body.removeChild(el);
81+
});
82+
});
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { setupTestDom, teardownTestDom, asyncUpdate } from "../dom-setup.js";
18+
import assert from "node:assert";
19+
import { describe, it, beforeEach, after, before } from "node:test";
20+
import { ComponentContext, MessageProcessor } from "@a2ui/web_core/v0_9";
21+
22+
describe("ChoicePicker Component", () => {
23+
let basicCatalog: any;
24+
25+
before(async () => {
26+
setupTestDom();
27+
basicCatalog = (await import("../../catalogs/basic/index.js")).basicCatalog;
28+
// Ensure component is registered
29+
await import("../../catalogs/basic/components/ChoicePicker.js");
30+
});
31+
32+
after(teardownTestDom);
33+
34+
let processor: MessageProcessor<any>;
35+
let surface: any;
36+
37+
beforeEach(() => {
38+
processor = new MessageProcessor([basicCatalog]);
39+
processor.processMessages([
40+
{
41+
version: "v0.9",
42+
createSurface: {
43+
surfaceId: "test-surface",
44+
catalogId: basicCatalog.id,
45+
},
46+
},
47+
{
48+
version: "v0.9",
49+
updateComponents: {
50+
surfaceId: "test-surface",
51+
components: [
52+
{
53+
id: "choice_picker_chips",
54+
component: "ChoicePicker",
55+
label: "Pick chips",
56+
options: [
57+
{ label: "Apple", value: "apple" },
58+
{ label: "Banana", value: "banana" },
59+
],
60+
value: [],
61+
displayStyle: "chips",
62+
},
63+
{
64+
id: "choice_picker_filterable",
65+
component: "ChoicePicker",
66+
label: "Filter me",
67+
options: [
68+
{ label: "Apple", value: "apple" },
69+
{ label: "Banana", value: "banana" },
70+
],
71+
value: [],
72+
filterable: true,
73+
},
74+
],
75+
},
76+
},
77+
]);
78+
surface = processor.model.getSurface("test-surface")!;
79+
});
80+
81+
it("should render chips when displayStyle is chips", async () => {
82+
const el = document.createElement("a2ui-choicepicker") as any;
83+
document.body.appendChild(el);
84+
85+
const context = new ComponentContext(surface, "choice_picker_chips");
86+
await asyncUpdate(el, (e) => {
87+
e.context = context;
88+
});
89+
90+
const buttons = el.shadowRoot.querySelectorAll("button.chip");
91+
assert.strictEqual(buttons.length, 2);
92+
assert.strictEqual(buttons[0].textContent.trim(), "Apple");
93+
94+
document.body.removeChild(el);
95+
});
96+
97+
it("should filter options when filterable is true", async () => {
98+
const el = document.createElement("a2ui-choicepicker") as any;
99+
document.body.appendChild(el);
100+
101+
const context = new ComponentContext(surface, "choice_picker_filterable");
102+
await asyncUpdate(el, (e) => {
103+
e.context = context;
104+
});
105+
106+
// Initially 2 options + 1 main label = 3 labels
107+
assert.strictEqual(el.shadowRoot.querySelectorAll("label").length, 3);
108+
109+
// Simulate input by setting state directly
110+
await asyncUpdate(el, (e) => {
111+
e.filter = "app";
112+
});
113+
114+
// Now only Apple should be visible + main label = 2 labels
115+
assert.strictEqual(el.shadowRoot.querySelectorAll("label").length, 2);
116+
117+
document.body.removeChild(el);
118+
});
119+
});

0 commit comments

Comments
 (0)