@microsoft/fast-test-harness 0.1.0 → 0.2.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 (36) hide show
  1. package/README.md +24 -18
  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 +13 -0
  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.map +1 -1
  11. package/dist/esm/build/generate-templates.js +61 -1
  12. package/dist/esm/build/generate-webui-templates.js +8 -25
  13. package/dist/esm/fixtures/ssr-fixture.js +19 -1
  14. package/dist/esm/ssr/render.js +38 -5
  15. package/package.json +26 -15
  16. package/dist/dts/build/dom-shim.test.d.ts +0 -2
  17. package/dist/dts/build/dom-shim.test.d.ts.map +0 -1
  18. package/dist/dts/build/generate-stylesheets.test.d.ts +0 -2
  19. package/dist/dts/build/generate-stylesheets.test.d.ts.map +0 -1
  20. package/dist/dts/build/generate-templates.test.d.ts +0 -2
  21. package/dist/dts/build/generate-templates.test.d.ts.map +0 -1
  22. package/dist/dts/build/generate-webui-templates.test.d.ts +0 -2
  23. package/dist/dts/build/generate-webui-templates.test.d.ts.map +0 -1
  24. package/dist/dts/fixtures/csr-fixture.pw.spec.d.ts +0 -2
  25. package/dist/dts/fixtures/csr-fixture.pw.spec.d.ts.map +0 -1
  26. package/dist/dts/fixtures/ssr-fixture.pw.spec.d.ts +0 -2
  27. package/dist/dts/fixtures/ssr-fixture.pw.spec.d.ts.map +0 -1
  28. package/dist/dts/ssr/render.test.d.ts +0 -2
  29. package/dist/dts/ssr/render.test.d.ts.map +0 -1
  30. package/dist/esm/build/dom-shim.test.js +0 -202
  31. package/dist/esm/build/generate-stylesheets.test.js +0 -74
  32. package/dist/esm/build/generate-templates.test.js +0 -231
  33. package/dist/esm/build/generate-webui-templates.test.js +0 -179
  34. package/dist/esm/fixtures/csr-fixture.pw.spec.js +0 -137
  35. package/dist/esm/fixtures/ssr-fixture.pw.spec.js +0 -189
  36. package/dist/esm/ssr/render.test.js +0 -236
@@ -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
- });
@@ -1,189 +0,0 @@
1
- import { expect, test } from "@microsoft/fast-test-harness";
2
- test.describe("SSR: setTemplate", () => {
3
- test.use({ tagName: "test-widget", ssr: true });
4
- test("should navigate to the SSR fixture page", async ({ fastPage, page }) => {
5
- await fastPage.setTemplate();
6
- const url = new URL(page.url());
7
- expect(url.pathname).toMatch(/^\/ssr-.*\.html$/);
8
- expect(url.pathname).toContain("should_navigate_to_the_ssr_fixture_page");
9
- });
10
- test("should render the element with default options", async ({ fastPage }) => {
11
- await fastPage.setTemplate();
12
- await expect(fastPage.element).toHaveCount(1);
13
- });
14
- test("should render with innerHTML", async ({ fastPage }) => {
15
- await fastPage.setTemplate({ innerHTML: "<span>child</span>" });
16
- await expect(fastPage.element).toHaveCount(1);
17
- await expect(fastPage.element).toContainText("child");
18
- });
19
- test("should render with attributes", async ({ fastPage }) => {
20
- await fastPage.setTemplate({
21
- attributes: { label: "Hello", size: "large" },
22
- });
23
- await expect(fastPage.element).toHaveAttribute("label", "Hello");
24
- await expect(fastPage.element).toHaveAttribute("size", "large");
25
- });
26
- test("should render with boolean attribute", async ({ fastPage }) => {
27
- await fastPage.setTemplate({ attributes: { disabled: true } });
28
- await expect(fastPage.element).toHaveAttribute("disabled");
29
- });
30
- test("should render with a raw HTML string", async ({ fastPage }) => {
31
- await fastPage.setTemplate(`<test-widget label="raw">raw content</test-widget>`);
32
- await expect(fastPage.element).toHaveAttribute("label", "raw");
33
- await expect(fastPage.element).toContainText("raw content");
34
- });
35
- test("should replace the previous template on subsequent calls", async ({ fastPage, }) => {
36
- await fastPage.setTemplate({ attributes: { label: "first" } });
37
- await expect(fastPage.element).toHaveAttribute("label", "first");
38
- await fastPage.setTemplate({ attributes: { label: "second" } });
39
- await expect(fastPage.element).toHaveAttribute("label", "second");
40
- await expect(fastPage.element).toHaveCount(1);
41
- });
42
- });
43
- test.describe("SSR: updateTemplate", () => {
44
- test.use({ tagName: "test-widget", ssr: true });
45
- test("should update attributes on an existing element", async ({ fastPage }) => {
46
- await fastPage.setTemplate({ attributes: { label: "before" } });
47
- await expect(fastPage.element).toHaveAttribute("label", "before");
48
- await fastPage.updateTemplate("test-widget", {
49
- attributes: { label: "after" },
50
- });
51
- await expect(fastPage.element).toHaveAttribute("label", "after");
52
- });
53
- test("should remove an attribute when set to false", async ({ fastPage }) => {
54
- await fastPage.setTemplate({ attributes: { disabled: true } });
55
- await expect(fastPage.element).toHaveAttribute("disabled");
56
- await fastPage.updateTemplate("test-widget", {
57
- attributes: { disabled: false },
58
- });
59
- await expect(fastPage.element).not.toHaveAttribute("disabled");
60
- });
61
- test("should update innerHTML", async ({ fastPage }) => {
62
- await fastPage.setTemplate({ innerHTML: "original" });
63
- await fastPage.updateTemplate("test-widget", {
64
- innerHTML: "updated",
65
- });
66
- await expect(fastPage.element).toContainText("updated");
67
- });
68
- test("should accept a Locator", async ({ fastPage }) => {
69
- await fastPage.setTemplate({ attributes: { label: "loc" } });
70
- await fastPage.updateTemplate(fastPage.element, {
71
- attributes: { label: "via-locator" },
72
- });
73
- await expect(fastPage.element).toHaveAttribute("label", "via-locator");
74
- });
75
- });
76
- test.describe("SSR: applyTokens", () => {
77
- test.use({ tagName: "test-widget", ssr: true });
78
- test("should set CSS custom properties on the body", async ({ fastPage }) => {
79
- await fastPage.setTemplate();
80
- await fastPage.applyTokens({
81
- "color-primary": "#0078d4",
82
- "spacing-m": "8px",
83
- });
84
- const value = await fastPage.page.evaluate(() => document.body.style.getPropertyValue("--color-primary"));
85
- expect(value).toBe("#0078d4");
86
- });
87
- });
88
- test.describe("SSR: waitForCustomElement", () => {
89
- test.use({ tagName: "test-widget", ssr: true });
90
- test("should resolve for a registered element", async ({ fastPage }) => {
91
- await fastPage.setTemplate();
92
- await fastPage.waitForCustomElement("test-widget");
93
- });
94
- });
95
- test.describe("SSR: toHaveCustomState", () => {
96
- test.use({ tagName: "test-widget", ssr: true });
97
- test("should pass when element has the custom state", async ({ fastPage }) => {
98
- await fastPage.setTemplate({ attributes: { disabled: true } });
99
- await expect(fastPage.element).toHaveCustomState("disabled");
100
- });
101
- test("should fail (negated) when element does not have the state", async ({ fastPage, }) => {
102
- await fastPage.setTemplate();
103
- await expect(fastPage.element).not.toHaveCustomState("disabled");
104
- });
105
- });
106
- test.describe("SSR: element locator", () => {
107
- test.use({ tagName: "test-widget", ssr: true });
108
- test("should locate the element by tag name", async ({ fastPage }) => {
109
- await fastPage.setTemplate();
110
- await expect(fastPage.element).toHaveCount(1);
111
- });
112
- });
113
- test.describe("SSR: declarative shadow DOM", () => {
114
- test.use({ tagName: "test-widget", ssr: true });
115
- test("should have a shadow root after SSR render", async ({ fastPage }) => {
116
- await fastPage.setTemplate({ attributes: { label: "DSD" } });
117
- const hasShadow = await fastPage.element.evaluate(el => el.shadowRoot !== null);
118
- expect(hasShadow).toBe(true);
119
- });
120
- });
121
- test.describe("SSR: template placeholder replacement", () => {
122
- test.use({ tagName: "test-widget", ssr: true });
123
- test("should replace the fixture placeholder with rendered component HTML", async ({ fastPage, page, }) => {
124
- await fastPage.setTemplate({ attributes: { label: "test" } });
125
- const bodyHtml = await page.locator("body").innerHTML();
126
- expect(bodyHtml).not.toContain("<!--fixture-->");
127
- expect(bodyHtml).toContain("<test-widget");
128
- });
129
- test("should replace the title placeholder with the test title", async ({ fastPage, page, }) => {
130
- await fastPage.setTemplate();
131
- const title = await page.title();
132
- expect(title).not.toBe("<!--fixturetitle-->");
133
- expect(title.length).toBeGreaterThan(0);
134
- });
135
- test("should replace the templates placeholder with template content", async ({ fastPage, page, }) => {
136
- await fastPage.setTemplate();
137
- const bodyHtml = await page.locator("body").innerHTML();
138
- expect(bodyHtml).not.toContain("<!--templates-->");
139
- });
140
- test("should replace the stylespreload placeholder with preload links", async ({ fastPage, page, }) => {
141
- await fastPage.setTemplate();
142
- const headHtml = await page.locator("head").innerHTML();
143
- expect(headHtml).not.toContain("<!--stylespreload-->");
144
- expect(headHtml).toContain("/test-theme.css");
145
- });
146
- test("should not contain any unreplaced placeholder comments", async ({ fastPage, page, }) => {
147
- await fastPage.setTemplate();
148
- const fullHtml = await page.content();
149
- expect(fullHtml).not.toContain("<!--fixture-->");
150
- expect(fullHtml).not.toContain("<!--fixturetitle-->");
151
- expect(fullHtml).not.toContain("<!--templates-->");
152
- expect(fullHtml).not.toContain("<!--stylespreload-->");
153
- });
154
- });
155
- test.describe("SSR: addStyleTag buffering", () => {
156
- test.use({ tagName: "test-widget", ssr: true });
157
- test("should include buffered styles in the SSR page", async ({ fastPage, page }) => {
158
- await fastPage.addStyleTag({
159
- content: "test-widget { outline: 3px solid blue; }",
160
- });
161
- await fastPage.setTemplate();
162
- const hasStyle = await page.evaluate(() => {
163
- const styles = document.querySelectorAll("style");
164
- return Array.from(styles).some(s => s.textContent?.includes("outline: 3px solid blue"));
165
- });
166
- expect(hasStyle).toBe(true);
167
- });
168
- test("should pass through addStyleTag calls after setTemplate", async ({ fastPage, page, }) => {
169
- await fastPage.setTemplate();
170
- await fastPage.addStyleTag({
171
- content: "test-widget { margin: 99px; }",
172
- });
173
- const hasStyle = await page.evaluate(() => {
174
- const styles = document.querySelectorAll("style");
175
- return Array.from(styles).some(s => s.textContent?.includes("margin: 99px"));
176
- });
177
- expect(hasStyle).toBe(true);
178
- });
179
- });
180
- test.describe("SSR: multiple elements", () => {
181
- test.use({ tagName: "test-widget", ssr: true });
182
- test("should handle templates with multiple instances", async ({ fastPage }) => {
183
- await fastPage.setTemplate(`
184
- <test-widget label="first">one</test-widget>
185
- <test-widget label="second">two</test-widget>
186
- `);
187
- await expect(fastPage.element).toHaveCount(2);
188
- });
189
- });