@microsoft/fast-test-harness 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +25 -19
  2. package/dist/dts/build/generate-templates.d.ts +35 -0
  3. package/dist/dts/build/generate-templates.d.ts.map +1 -1
  4. package/dist/dts/build/generate-webui-templates.d.ts +14 -1
  5. package/dist/dts/build/generate-webui-templates.d.ts.map +1 -1
  6. package/dist/dts/fixtures/csr-fixture.d.ts +28 -0
  7. package/dist/dts/fixtures/csr-fixture.d.ts.map +1 -1
  8. package/dist/dts/fixtures/ssr-fixture.d.ts +19 -0
  9. package/dist/dts/fixtures/ssr-fixture.d.ts.map +1 -1
  10. package/dist/dts/ssr/render.d.ts +11 -16
  11. package/dist/dts/ssr/render.d.ts.map +1 -1
  12. package/dist/esm/build/generate-templates.js +62 -2
  13. package/dist/esm/build/generate-webui-templates.js +9 -26
  14. package/dist/esm/fixtures/ssr-fixture.js +19 -1
  15. package/dist/esm/ssr/render.js +48 -104
  16. package/package.json +26 -15
  17. package/dist/dts/build/dom-shim.test.d.ts +0 -2
  18. package/dist/dts/build/dom-shim.test.d.ts.map +0 -1
  19. package/dist/dts/build/generate-stylesheets.test.d.ts +0 -2
  20. package/dist/dts/build/generate-stylesheets.test.d.ts.map +0 -1
  21. package/dist/dts/build/generate-templates.test.d.ts +0 -2
  22. package/dist/dts/build/generate-templates.test.d.ts.map +0 -1
  23. package/dist/dts/build/generate-webui-templates.test.d.ts +0 -2
  24. package/dist/dts/build/generate-webui-templates.test.d.ts.map +0 -1
  25. package/dist/dts/fixtures/csr-fixture.pw.spec.d.ts +0 -2
  26. package/dist/dts/fixtures/csr-fixture.pw.spec.d.ts.map +0 -1
  27. package/dist/dts/fixtures/ssr-fixture.pw.spec.d.ts +0 -2
  28. package/dist/dts/fixtures/ssr-fixture.pw.spec.d.ts.map +0 -1
  29. package/dist/dts/ssr/render.test.d.ts +0 -2
  30. package/dist/dts/ssr/render.test.d.ts.map +0 -1
  31. package/dist/esm/build/dom-shim.test.js +0 -202
  32. package/dist/esm/build/generate-stylesheets.test.js +0 -74
  33. package/dist/esm/build/generate-templates.test.js +0 -231
  34. package/dist/esm/build/generate-webui-templates.test.js +0 -179
  35. package/dist/esm/fixtures/csr-fixture.pw.spec.js +0 -137
  36. package/dist/esm/fixtures/ssr-fixture.pw.spec.js +0 -189
  37. package/dist/esm/ssr/render.test.js +0 -236
@@ -1,231 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import { test } from "node:test";
6
- import { installDomShim } from "@microsoft/fast-test-harness/build/dom-shim.js";
7
- import { convertTemplate, generateFTemplates, } from "@microsoft/fast-test-harness/build/generate-templates.js";
8
- import { generateWebuiTemplates } from "@microsoft/fast-test-harness/build/generate-webui-templates.js";
9
- test.describe("convertTemplate", async () => {
10
- // Install the DOM shim before any tests — convertTemplate needs fast-html
11
- // syntax constants which require a DOM environment, and FAST Element needs
12
- // basic DOM globals to initialize.
13
- installDomShim();
14
- // Dynamic import after the DOM shim is installed so FAST Element can
15
- // access `document`, `CSSStyleSheet`, etc.
16
- const { html, ref, slotted, children } = await import("@microsoft/fast-element");
17
- test("should wrap a static template in f-template tags", () => {
18
- const template = html `<template><div>hello</div></template>`;
19
- const result = convertTemplate(template, "fast-test");
20
- assert.ok(result);
21
- assert.ok(result.includes('<f-template name="fast-test"'));
22
- assert.ok(result.includes("shadowrootmode"));
23
- assert.ok(result.includes("<div>hello</div>"));
24
- assert.ok(result.includes("{{styles}}"));
25
- });
26
- test("should return null-safe for empty factories", () => {
27
- const template = html `<template><span></span></template>`;
28
- const result = convertTemplate(template, "fast-empty");
29
- assert.ok(result);
30
- assert.ok(result.includes("<span></span>"));
31
- });
32
- test("should inject {{styles}} after the opening template tag", () => {
33
- const template = html `<template><p>content</p></template>`;
34
- const result = convertTemplate(template, "fast-styles");
35
- assert.ok(result);
36
- const templateIdx = result.indexOf("<template>");
37
- const stylesIdx = result.indexOf("{{styles}}");
38
- assert.ok(stylesIdx > templateIdx, "{{styles}} should appear after <template>");
39
- });
40
- test("should convert RefDirective factories to f-ref attributes", () => {
41
- const template = html `<template><div ${ref("myRef")}></div></template>`;
42
- const result = convertTemplate(template, "fast-ref");
43
- assert.ok(result);
44
- assert.ok(result.includes('f-ref="{myRef}"'), `got: ${result}`);
45
- });
46
- test("should convert SlottedDirective factories to f-slotted attributes", () => {
47
- const template = html `<template><slot ${slotted("slottedItems")}></slot></template>`;
48
- const result = convertTemplate(template, "fast-slotted");
49
- assert.ok(result);
50
- assert.ok(result.includes("f-slotted="), `got: ${result}`);
51
- assert.ok(result.includes("slottedItems"), `got: ${result}`);
52
- });
53
- test("should convert value bindings to {{expression}}", () => {
54
- const template = html `<template><span>${x => x.label}</span></template>`;
55
- const result = convertTemplate(template, "fast-binding");
56
- assert.ok(result);
57
- assert.ok(result.includes("{{label}}"), `got: ${result}`);
58
- });
59
- test("should convert boolean bindings to ?attr expressions", () => {
60
- const template = html `<template><button ?disabled="${x => x.disabled}"></button></template>`;
61
- const result = convertTemplate(template, "fast-bool");
62
- assert.ok(result);
63
- assert.ok(result.includes('?disabled="{{disabled}}"'), `got: ${result}`);
64
- });
65
- test("should inline static sub-templates", () => {
66
- const template = html `<template><div>${() => "<svg>icon</svg>"}</div></template>`;
67
- const result = convertTemplate(template, "fast-inline");
68
- assert.ok(result);
69
- assert.ok(result.includes("<svg>icon</svg>"), `got: ${result}`);
70
- });
71
- test("should convert ChildrenDirective factories to f-children attributes", () => {
72
- const template = html `<template><div ${children("childItems")}></div></template>`;
73
- const result = convertTemplate(template, "fast-children");
74
- assert.ok(result);
75
- assert.ok(result.includes("f-children="), `got: ${result}`);
76
- assert.ok(result.includes("childItems"), `got: ${result}`);
77
- });
78
- test("should convert event bindings to @event expressions", () => {
79
- const template = html `<template><button @click="${(x, c) => x.handleClick(c.event)}"></button></template>`;
80
- const result = convertTemplate(template, "fast-event");
81
- assert.ok(result);
82
- assert.ok(result.includes("@click="), `got: ${result}`);
83
- assert.ok(result.includes("handleClick"), `got: ${result}`);
84
- });
85
- test("should convert property bindings to :prop expressions", () => {
86
- const template = html `<template><input :value="${x => x.currentValue}" /></template>`;
87
- const result = convertTemplate(template, "fast-prop");
88
- assert.ok(result);
89
- assert.ok(result.includes(":value="), `got: ${result}`);
90
- assert.ok(result.includes("currentValue"), `got: ${result}`);
91
- });
92
- test("should handle multiple factories in a single template", () => {
93
- const template = html `<template><span>${x => x.label}</span><button ?disabled="${x => x.disabled}"></button></template>`;
94
- const result = convertTemplate(template, "fast-multi");
95
- assert.ok(result);
96
- assert.ok(result.includes("{{label}}"), `got: ${result}`);
97
- assert.ok(result.includes('?disabled="{{disabled}}"'), `got: ${result}`);
98
- });
99
- test("should inline a static sub-template ViewTemplate", () => {
100
- const icon = html `<svg>icon</svg>`;
101
- const template = html `<template><div>${() => icon}</div></template>`;
102
- const result = convertTemplate(template, "fast-sub");
103
- assert.ok(result);
104
- assert.ok(result.includes("<svg>icon</svg>"), `got: ${result}`);
105
- });
106
- });
107
- test.describe("generateFTemplates", () => {
108
- let tempDir;
109
- test.beforeEach(async () => {
110
- tempDir = await mkdtemp(join(tmpdir(), "fast-ftemplates-"));
111
- });
112
- test.afterEach(async () => {
113
- await rm(tempDir, { recursive: true, force: true });
114
- });
115
- test("should generate an f-template HTML file from a template module", async () => {
116
- const distDir = join(tempDir, "dist");
117
- await mkdir(distDir, { recursive: true });
118
- await writeFile(join(distDir, "badge.template.js"), `export const template = {
119
- html: "<template><slot></slot></template>",
120
- factories: {}
121
- };`);
122
- await generateFTemplates({ cwd: tempDir, tagPrefix: "mai" });
123
- const html = await readFile(join(distDir, "badge.template.html"), "utf8");
124
- assert.ok(html.includes('<f-template name="mai-badge"'));
125
- assert.ok(html.includes("<slot></slot>"));
126
- assert.ok(html.includes("{{styles}}"));
127
- });
128
- test("should write to outDir when specified", async () => {
129
- const distDir = join(tempDir, "dist");
130
- await mkdir(distDir, { recursive: true });
131
- await writeFile(join(distDir, "card.template.js"), `export const template = {
132
- html: "<template><div>card</div></template>",
133
- factories: {}
134
- };`);
135
- await generateFTemplates({ cwd: tempDir, outDir: "out", tagPrefix: "fast" });
136
- const html = await readFile(join(tempDir, "out", "card.template.html"), "utf8");
137
- assert.ok(html.includes('<f-template name="fast-card"'));
138
- });
139
- test("should skip modules without a template export", async () => {
140
- const distDir = join(tempDir, "dist");
141
- await mkdir(distDir, { recursive: true });
142
- await writeFile(join(distDir, "empty.template.js"), `export const styles = ":host {}";`);
143
- await generateFTemplates({ cwd: tempDir, tagPrefix: "fast" });
144
- try {
145
- await readFile(join(distDir, "empty.template.html"), "utf8");
146
- assert.fail("Should not have created an HTML file");
147
- }
148
- catch (err) {
149
- assert.strictEqual(err.code, "ENOENT");
150
- }
151
- });
152
- test("should apply a format function", async () => {
153
- const distDir = join(tempDir, "dist");
154
- await mkdir(distDir, { recursive: true });
155
- await writeFile(join(distDir, "text.template.js"), `export const template = {
156
- html: "<template><span>text</span></template>",
157
- factories: {}
158
- };`);
159
- await generateFTemplates({
160
- cwd: tempDir,
161
- tagPrefix: "fast",
162
- format: html => `<!-- formatted -->\n${html}`,
163
- });
164
- const html = await readFile(join(distDir, "text.template.html"), "utf8");
165
- assert.ok(html.startsWith("<!-- formatted -->"));
166
- });
167
- });
168
- test.describe("generateWebuiTemplates", () => {
169
- let tempDir;
170
- test.beforeEach(async () => {
171
- tempDir = await mkdtemp(join(tmpdir(), "fast-webui-"));
172
- });
173
- test.afterEach(async () => {
174
- await rm(tempDir, { recursive: true, force: true });
175
- });
176
- test("should generate a webui template without f-template wrapper", async () => {
177
- const distDir = join(tempDir, "dist");
178
- await mkdir(distDir, { recursive: true });
179
- await writeFile(join(distDir, "badge.template.js"), `export const template = {
180
- html: "<template><slot></slot></template>",
181
- factories: {}
182
- };`);
183
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "mai" });
184
- const html = await readFile(join(distDir, "badge.template-webui.html"), "utf8");
185
- assert.ok(html.includes('<template shadowrootmode="open">'));
186
- assert.ok(html.includes("<slot></slot>"));
187
- assert.ok(!html.includes("<f-template"), "should not have f-template wrapper");
188
- assert.ok(!html.includes("{{styles}}"), "should not have styles marker");
189
- });
190
- test("should write to outDir when specified", async () => {
191
- const distDir = join(tempDir, "dist");
192
- await mkdir(distDir, { recursive: true });
193
- await writeFile(join(distDir, "card.template.js"), `export const template = {
194
- html: "<template><div>card</div></template>",
195
- factories: {}
196
- };`);
197
- await generateWebuiTemplates({
198
- cwd: tempDir,
199
- outDir: "out",
200
- tagPrefix: "fast",
201
- });
202
- const html = await readFile(join(tempDir, "out", "card.template-webui.html"), "utf8");
203
- assert.ok(html.includes('<template shadowrootmode="open">'));
204
- });
205
- test("should add shadowrootdelegatesfocus from definition-async", async () => {
206
- const distDir = join(tempDir, "dist");
207
- await mkdir(distDir, { recursive: true });
208
- await writeFile(join(distDir, "input.template.js"), `export const template = {
209
- html: "<template><input /></template>",
210
- factories: {}
211
- };`);
212
- await writeFile(join(distDir, "input.definition-async.js"), `export const definition = {
213
- name: "fast-input",
214
- shadowOptions: { delegatesFocus: true },
215
- };`);
216
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "fast" });
217
- const html = await readFile(join(distDir, "input.template-webui.html"), "utf8");
218
- assert.ok(html.includes("shadowrootdelegatesfocus"), `should include delegatesFocus, got: ${html}`);
219
- });
220
- test("should not add shadowrootdelegatesfocus when absent", async () => {
221
- const distDir = join(tempDir, "dist");
222
- await mkdir(distDir, { recursive: true });
223
- await writeFile(join(distDir, "div.template.js"), `export const template = {
224
- html: "<template><div>hello</div></template>",
225
- factories: {}
226
- };`);
227
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "fast" });
228
- const html = await readFile(join(distDir, "div.template-webui.html"), "utf8");
229
- assert.ok(!html.includes("shadowrootdelegatesfocus"));
230
- });
231
- });
@@ -1,179 +0,0 @@
1
- import assert from "node:assert/strict";
2
- import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import { test } from "node:test";
6
- import { generateWebuiTemplates } from "@microsoft/fast-test-harness/build/generate-webui-templates.js";
7
- test.describe("generateWebuiTemplates", () => {
8
- let tempDir;
9
- test.beforeEach(async () => {
10
- tempDir = await mkdtemp(join(tmpdir(), "fast-webui-templ-"));
11
- });
12
- test.afterEach(async () => {
13
- await rm(tempDir, { recursive: true, force: true });
14
- });
15
- test("should generate a webui template without f-template wrapper", async () => {
16
- const distDir = join(tempDir, "dist");
17
- await mkdir(distDir, { recursive: true });
18
- await writeFile(join(distDir, "badge.template.js"), `export const template = {
19
- html: "<template><slot></slot></template>",
20
- factories: {}
21
- };`);
22
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "mai" });
23
- const html = await readFile(join(distDir, "badge.template-webui.html"), "utf8");
24
- assert.ok(html.includes('<template shadowrootmode="open">'));
25
- assert.ok(html.includes("<slot></slot>"));
26
- assert.ok(!html.includes("<f-template"), "should not have f-template wrapper");
27
- assert.ok(!html.includes("{{styles}}"), "should not have styles marker");
28
- });
29
- test("should write to outDir when specified", async () => {
30
- const distDir = join(tempDir, "dist");
31
- await mkdir(distDir, { recursive: true });
32
- await writeFile(join(distDir, "card.template.js"), `export const template = {
33
- html: "<template><div>card</div></template>",
34
- factories: {}
35
- };`);
36
- await generateWebuiTemplates({
37
- cwd: tempDir,
38
- outDir: "out",
39
- tagPrefix: "fast",
40
- });
41
- const html = await readFile(join(tempDir, "out", "card.template-webui.html"), "utf8");
42
- assert.ok(html.includes('<template shadowrootmode="open">'));
43
- });
44
- test("should skip modules without a template export", async () => {
45
- const distDir = join(tempDir, "dist");
46
- await mkdir(distDir, { recursive: true });
47
- await writeFile(join(distDir, "empty.template.js"), `export const styles = ":host {}";`);
48
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "fast" });
49
- try {
50
- await readFile(join(distDir, "empty.template-webui.html"), "utf8");
51
- assert.fail("Should not have created an HTML file");
52
- }
53
- catch (err) {
54
- assert.strictEqual(err.code, "ENOENT");
55
- }
56
- });
57
- test("should apply a format function", async () => {
58
- const distDir = join(tempDir, "dist");
59
- await mkdir(distDir, { recursive: true });
60
- await writeFile(join(distDir, "text.template.js"), `export const template = {
61
- html: "<template><span>text</span></template>",
62
- factories: {}
63
- };`);
64
- await generateWebuiTemplates({
65
- cwd: tempDir,
66
- tagPrefix: "fast",
67
- format: html => `<!-- webui-formatted -->\n${html}`,
68
- });
69
- const html = await readFile(join(distDir, "text.template-webui.html"), "utf8");
70
- assert.ok(html.startsWith("<!-- webui-formatted -->"));
71
- });
72
- test("should add shadowrootdelegatesfocus from definition-async", async () => {
73
- const distDir = join(tempDir, "dist");
74
- await mkdir(distDir, { recursive: true });
75
- await writeFile(join(distDir, "input.template.js"), `export const template = {
76
- html: "<template><input /></template>",
77
- factories: {}
78
- };`);
79
- await writeFile(join(distDir, "input.definition-async.js"), `export const definition = {
80
- name: "fast-input",
81
- shadowOptions: { delegatesFocus: true },
82
- };`);
83
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "fast" });
84
- const html = await readFile(join(distDir, "input.template-webui.html"), "utf8");
85
- assert.ok(html.includes("shadowrootdelegatesfocus"), `should include delegatesFocus, got: ${html}`);
86
- });
87
- test("should not add shadowrootdelegatesfocus when absent", async () => {
88
- const distDir = join(tempDir, "dist");
89
- await mkdir(distDir, { recursive: true });
90
- await writeFile(join(distDir, "div.template.js"), `export const template = {
91
- html: "<template><div>hello</div></template>",
92
- factories: {}
93
- };`);
94
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "fast" });
95
- const html = await readFile(join(distDir, "div.template-webui.html"), "utf8");
96
- assert.ok(!html.includes("shadowrootdelegatesfocus"));
97
- });
98
- test("should strip the {{styles}} marker from output", async () => {
99
- const distDir = join(tempDir, "dist");
100
- await mkdir(distDir, { recursive: true });
101
- // The template contains nested content that would produce a styles marker
102
- // during f-template generation (convertTemplate injects it).
103
- await writeFile(join(distDir, "label.template.js"), `export const template = {
104
- html: "<template><label>Name</label></template>",
105
- factories: {}
106
- };`);
107
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "mai" });
108
- const html = await readFile(join(distDir, "label.template-webui.html"), "utf8");
109
- assert.ok(!html.includes("{{styles}}"), `should not contain styles marker: ${html}`);
110
- assert.ok(!html.includes("{%styles%}"), `should not contain alt styles marker: ${html}`);
111
- });
112
- test("should handle modules with a default export", async () => {
113
- const distDir = join(tempDir, "dist");
114
- await mkdir(distDir, { recursive: true });
115
- await writeFile(join(distDir, "icon.template.js"), `const template = {
116
- html: "<template><svg></svg></template>",
117
- factories: {}
118
- };
119
- export default template;`);
120
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "fast" });
121
- const html = await readFile(join(distDir, "icon.template-webui.html"), "utf8");
122
- assert.ok(html.includes('<template shadowrootmode="open">'));
123
- assert.ok(html.includes("<svg></svg>"));
124
- });
125
- test("should handle multiple template modules in one pass", async () => {
126
- const distDir = join(tempDir, "dist");
127
- await mkdir(distDir, { recursive: true });
128
- await writeFile(join(distDir, "button.template.js"), `export const template = {
129
- html: "<template><button><slot></slot></button></template>",
130
- factories: {}
131
- };`);
132
- await writeFile(join(distDir, "badge.template.js"), `export const template = {
133
- html: "<template><span><slot></slot></span></template>",
134
- factories: {}
135
- };`);
136
- await generateWebuiTemplates({ cwd: tempDir, tagPrefix: "mai" });
137
- const buttonHtml = await readFile(join(distDir, "button.template-webui.html"), "utf8");
138
- const badgeHtml = await readFile(join(distDir, "badge.template-webui.html"), "utf8");
139
- assert.ok(buttonHtml.includes("<button>"));
140
- assert.ok(badgeHtml.includes("<span>"));
141
- });
142
- test("should gracefully handle a format function that throws", async () => {
143
- const distDir = join(tempDir, "dist");
144
- await mkdir(distDir, { recursive: true });
145
- await writeFile(join(distDir, "broken.template.js"), `export const template = {
146
- html: "<template><div>ok</div></template>",
147
- factories: {}
148
- };`);
149
- // Should not throw — just warn and skip formatting.
150
- await generateWebuiTemplates({
151
- cwd: tempDir,
152
- tagPrefix: "fast",
153
- format: () => {
154
- throw new Error("format boom");
155
- },
156
- });
157
- const html = await readFile(join(distDir, "broken.template-webui.html"), "utf8");
158
- // The file should still be written (unformatted).
159
- assert.ok(html.includes("<div>ok</div>"));
160
- });
161
- test("should use a custom glob pattern", async () => {
162
- const distDir = join(tempDir, "dist");
163
- const sub = join(distDir, "components");
164
- await mkdir(sub, { recursive: true });
165
- // Use the standard .template.js suffix so basename extraction works
166
- await writeFile(join(sub, "alert.template.js"), `export const template = {
167
- html: "<template><div role='alert'></div></template>",
168
- factories: {}
169
- };`);
170
- await generateWebuiTemplates({
171
- cwd: tempDir,
172
- tagPrefix: "fast",
173
- pattern: "components/*.template.js",
174
- });
175
- const html = await readFile(join(sub, "alert.template-webui.html"), "utf8");
176
- assert.ok(html.includes("role="), `got: ${html}`);
177
- assert.ok(html.includes("alert"), `got: ${html}`);
178
- });
179
- });
@@ -1,137 +0,0 @@
1
- import { expect, test } from "@microsoft/fast-test-harness";
2
- test.describe("CSR: setTemplate", () => {
3
- test.use({ tagName: "test-widget" });
4
- test("should render the element with default options", async ({ fastPage }) => {
5
- await fastPage.setTemplate();
6
- await expect(fastPage.element).toHaveCount(1);
7
- });
8
- test("should render with innerHTML", async ({ fastPage }) => {
9
- await fastPage.setTemplate({ innerHTML: "<span>child</span>" });
10
- await expect(fastPage.element).toHaveCount(1);
11
- await expect(fastPage.element).toContainText("child");
12
- });
13
- test("should render with attributes", async ({ fastPage }) => {
14
- await fastPage.setTemplate({
15
- attributes: { label: "Hello", size: "large" },
16
- });
17
- await expect(fastPage.element).toHaveAttribute("label", "Hello");
18
- await expect(fastPage.element).toHaveAttribute("size", "large");
19
- });
20
- test("should render with boolean attribute", async ({ fastPage }) => {
21
- await fastPage.setTemplate({ attributes: { disabled: true } });
22
- await expect(fastPage.element).toHaveAttribute("disabled");
23
- });
24
- test("should render with a raw HTML string", async ({ fastPage }) => {
25
- await fastPage.setTemplate(`<test-widget label="raw">raw content</test-widget>`);
26
- await expect(fastPage.element).toHaveAttribute("label", "raw");
27
- await expect(fastPage.element).toContainText("raw content");
28
- });
29
- test("should replace the previous template on subsequent calls", async ({ fastPage, }) => {
30
- await fastPage.setTemplate({ attributes: { label: "first" } });
31
- await expect(fastPage.element).toHaveAttribute("label", "first");
32
- await fastPage.setTemplate({ attributes: { label: "second" } });
33
- await expect(fastPage.element).toHaveAttribute("label", "second");
34
- await expect(fastPage.element).toHaveCount(1);
35
- });
36
- });
37
- test.describe("CSR: updateTemplate", () => {
38
- test.use({ tagName: "test-widget" });
39
- test("should update attributes on an existing element", async ({ fastPage }) => {
40
- await fastPage.setTemplate({ attributes: { label: "before" } });
41
- await expect(fastPage.element).toHaveAttribute("label", "before");
42
- await fastPage.updateTemplate("test-widget", {
43
- attributes: { label: "after" },
44
- });
45
- await expect(fastPage.element).toHaveAttribute("label", "after");
46
- });
47
- test("should remove an attribute when set to false", async ({ fastPage }) => {
48
- await fastPage.setTemplate({ attributes: { disabled: true } });
49
- await expect(fastPage.element).toHaveAttribute("disabled");
50
- await fastPage.updateTemplate("test-widget", {
51
- attributes: { disabled: false },
52
- });
53
- await expect(fastPage.element).not.toHaveAttribute("disabled");
54
- });
55
- test("should update innerHTML", async ({ fastPage }) => {
56
- await fastPage.setTemplate({ innerHTML: "original" });
57
- await fastPage.updateTemplate("test-widget", {
58
- innerHTML: "updated",
59
- });
60
- await expect(fastPage.element).toContainText("updated");
61
- });
62
- test("should accept a Locator", async ({ fastPage }) => {
63
- await fastPage.setTemplate({ attributes: { label: "loc" } });
64
- await fastPage.updateTemplate(fastPage.element, {
65
- attributes: { label: "via-locator" },
66
- });
67
- await expect(fastPage.element).toHaveAttribute("label", "via-locator");
68
- });
69
- });
70
- test.describe("CSR: applyTokens", () => {
71
- test.use({ tagName: "test-widget" });
72
- test("should set CSS custom properties on the body", async ({ fastPage }) => {
73
- await fastPage.setTemplate();
74
- await fastPage.applyTokens({
75
- "color-primary": "#0078d4",
76
- "spacing-m": "8px",
77
- });
78
- const value = await fastPage.page.evaluate(() => document.body.style.getPropertyValue("--color-primary"));
79
- expect(value).toBe("#0078d4");
80
- });
81
- });
82
- test.describe("CSR: waitForCustomElement", () => {
83
- test.use({ tagName: "test-widget" });
84
- test("should resolve for a registered element", async ({ fastPage }) => {
85
- await fastPage.setTemplate();
86
- await fastPage.waitForCustomElement("test-widget");
87
- });
88
- });
89
- test.describe("CSR: toHaveCustomState", () => {
90
- test.use({ tagName: "test-widget" });
91
- test("should pass when element has the custom state", async ({ fastPage }) => {
92
- await fastPage.setTemplate({ attributes: { disabled: true } });
93
- await expect(fastPage.element).toHaveCustomState("disabled");
94
- });
95
- test("should fail (negated) when element does not have the state", async ({ fastPage, }) => {
96
- await fastPage.setTemplate();
97
- await expect(fastPage.element).not.toHaveCustomState("disabled");
98
- });
99
- });
100
- test.describe("CSR: element locator", () => {
101
- test.use({ tagName: "test-widget" });
102
- test("should locate the element by tag name", async ({ fastPage }) => {
103
- await fastPage.setTemplate();
104
- await expect(fastPage.element).toHaveCount(1);
105
- });
106
- });
107
- test.describe("CSR: addStyleTag", () => {
108
- test.use({ tagName: "test-widget" });
109
- test("should add a style tag with content", async ({ fastPage }) => {
110
- await fastPage.setTemplate();
111
- await fastPage.addStyleTag({
112
- content: "test-widget { border: 1px solid red; }",
113
- });
114
- const hasBorder = await fastPage.page.evaluate(() => {
115
- const styles = document.querySelectorAll("style");
116
- return Array.from(styles).some(s => s.textContent?.includes("border: 1px solid red"));
117
- });
118
- expect(hasBorder).toBe(true);
119
- });
120
- });
121
- test.describe("CSR: multiple elements", () => {
122
- test.use({ tagName: "test-widget" });
123
- test("should handle templates with multiple instances", async ({ fastPage }) => {
124
- await fastPage.setTemplate(`
125
- <test-widget label="first">one</test-widget>
126
- <test-widget label="second">two</test-widget>
127
- `);
128
- await expect(fastPage.element).toHaveCount(2);
129
- });
130
- });
131
- test.describe("CSR: waitFor", () => {
132
- test.use({ tagName: "test-widget", waitFor: ["test-widget"] });
133
- test("should wait for additional elements specified in waitFor", async ({ fastPage, }) => {
134
- await fastPage.setTemplate();
135
- await expect(fastPage.element).toHaveCount(1);
136
- });
137
- });