Skip to content

Commit 8ad84fa

Browse files
author
DavidQ
committed
Add Playwright validation for tool template runtime header and theme usage - PR_26126_066-tool-template-runtime-validation
1 parent 9ba59c1 commit 8ad84fa

12 files changed

Lines changed: 325 additions & 56 deletions

File tree

docs/dev/reports/playwright_v8_coverage_report.txt

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Playwright V8 Coverage Report
22

3-
PR: PR_26126_059-playwright-coverage-multi-tool-verification
3+
PR: generated by current workspace-v2 Playwright run.
44
Coverage source: Playwright/Chromium built-in V8 coverage.
55
Coverage scope: all repo-relative browser JavaScript collected by Playwright/Chromium V8 coverage.
66
Dependencies: no new npm packages.
@@ -13,11 +13,15 @@ Note: coverage entries are aggregated across every page/tool where coverageRepor
1313
Exercised tool entry points detected:
1414
(84%) Preview Generator V2 - exercised 19 runtime JS files
1515
(49%) Palette Manager - exercised 12 runtime JS files
16+
(89%) First-Class Tool Starter Template - exercised 10 runtime JS files
1617
(0%) Workspace V2 - not exercised by this Playwright run
1718
(0%) Workspace Manager - not exercised by this Playwright run
1819

1920
Changed runtime JS files covered:
20-
(100%) none changed - no changed runtime JS files
21+
(67%) tools/templates/first-class-tool-starter/js/ToolStarterApp.js - executed lines 69/69; executed functions 8/12
22+
(92%) tools/templates/first-class-tool-starter/js/controls/ToolStarterShellControl.js - executed lines 111/111; executed functions 11/12
23+
(100%) tools/templates/first-class-tool-starter/js/bootstrap.js - executed lines 42/42; executed functions 4/4
24+
(100%) tools/templates/first-class-tool-starter/js/controls/AccordionSection.js - executed lines 27/27; executed functions 5/5
2125

2226
Files with executed line/function counts where available:
2327
(2%) src/engine/input/ActionInputService.js - executed lines 397/397; executed functions 1/51
@@ -96,6 +100,7 @@ Files with executed line/function counts where available:
96100
(65%) tools/palette-manager-v2/controls/SourcePaletteBrowserControl.js - executed lines 121/121; executed functions 15/23
97101
(67%) src/shared/number/numberUtils.js - executed lines 14/14; executed functions 2/3
98102
(67%) tools/preview-generator-v2/PreviewGeneratorV2ShellControl.js - executed lines 117/117; executed functions 8/12
103+
(67%) tools/templates/first-class-tool-starter/js/ToolStarterApp.js - executed lines 69/69; executed functions 8/12
99104
(71%) tools/palette-manager-v2/controls/PaletteValidationErrorControl.js - executed lines 30/30; executed functions 5/7
100105
(73%) src/engine/theme/mount-shared-header.js - executed lines 143/143; executed functions 8/11
101106
(75%) src/engine/core/FixedTicker.js - executed lines 36/36; executed functions 3/4
@@ -106,7 +111,10 @@ Files with executed line/function counts where available:
106111
(80%) src/engine/theme/accordionV2/accordionV2.js - executed lines 26/26; executed functions 4/5
107112
(81%) tools/preview-generator-v2/PreviewGeneratorV2App.js - executed lines 539/539; executed functions 47/58
108113
(82%) samples/shared/sampleDetailPageEnhancement.js - executed lines 471/471; executed functions 41/50
114+
(86%) tools/templates/first-class-tool-starter/js/controls/StatusLogControl.js - executed lines 21/21; executed functions 6/7
109115
(87%) tools/common/PaletteSortService.js - executed lines 103/103; executed functions 13/15
116+
(88%) tools/templates/first-class-tool-starter/js/controls/SourceInputControl.js - executed lines 33/33; executed functions 7/8
117+
(92%) tools/templates/first-class-tool-starter/js/controls/ToolStarterShellControl.js - executed lines 111/111; executed functions 11/12
110118
(100%) samples/phase-01/0102/main.js - executed lines 23/23; executed functions 1/1
111119
(100%) samples/shared/numberUtils.js - executed lines 7/7; executed functions 1/1
112120
(100%) src/engine/audio/index.js - executed lines 15/15; executed functions 1/1
@@ -141,9 +149,21 @@ Files with executed line/function counts where available:
141149
(100%) tools/preview-generator-v2/PreviewGeneratorV2Logger.js - executed lines 19/19; executed functions 5/5
142150
(100%) tools/preview-generator-v2/PreviewGeneratorV2RepoAccess.js - executed lines 21/21; executed functions 5/5
143151
(100%) tools/preview-generator-v2/PreviewGeneratorV2Ui.js - executed lines 48/48; executed functions 9/9
152+
(100%) tools/templates/first-class-tool-starter/js/bootstrap.js - executed lines 42/42; executed functions 4/4
153+
(100%) tools/templates/first-class-tool-starter/js/controls/AccordionSection.js - executed lines 27/27; executed functions 5/5
154+
(100%) tools/templates/first-class-tool-starter/js/controls/ActionNavControl.js - executed lines 16/16; executed functions 4/4
155+
(100%) tools/templates/first-class-tool-starter/js/controls/InspectorControl.js - executed lines 8/8; executed functions 3/3
156+
(100%) tools/templates/first-class-tool-starter/js/controls/PreviewPanelControl.js - executed lines 23/23; executed functions 5/5
157+
(100%) tools/templates/first-class-tool-starter/js/services/ToolStateSerializer.js - executed lines 13/13; executed functions 3/3
144158

145159
Uncovered or low-coverage changed JS files:
146-
(100%) none changed - no changed runtime JS files
160+
(100%) none - no low-coverage changed runtime JS files
147161

148162
Changed JS files considered:
149163
(0%) tests/helpers/playwrightV8CoverageReporter.mjs - changed JS file not collected as browser runtime coverage
164+
(0%) tests/playwright/PreviewGeneratorV2Baseline.spec.mjs - changed JS file not collected as browser runtime coverage
165+
(0%) tools/templates/first-class-tool-starter/tests/playwright/FirstClassToolStarter.spec.mjs - changed JS file not collected as browser runtime coverage
166+
(67%) tools/templates/first-class-tool-starter/js/ToolStarterApp.js - changed JS file with browser V8 coverage
167+
(92%) tools/templates/first-class-tool-starter/js/controls/ToolStarterShellControl.js - changed JS file with browser V8 coverage
168+
(100%) tools/templates/first-class-tool-starter/js/bootstrap.js - changed JS file with browser V8 coverage
169+
(100%) tools/templates/first-class-tool-starter/js/controls/AccordionSection.js - changed JS file with browser V8 coverage
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# PR_26126_066 Tool Template Runtime Validation
2+
3+
Scope:
4+
- Updated the first-class tool starter under tools/templates.
5+
- Updated workspace-v2 Playwright coverage/reporting so the starter is launched in the normal test lane.
6+
- Updated V8 coverage reporting to include the first-class tool starter template entry point.
7+
- No live tools outside tests/coverage plumbing were modified.
8+
9+
Template runtime hardening:
10+
- Header markup now follows the Preview Generator V2 / Palette Manager-style shell pattern with body.tools-platform-tool-page, collapsible header/details, #shared-theme-header, and a tool-local header host.
11+
- Template now consumes src/engine/theme/main.css, src/engine/ui/hubCommon.css, src/engine/theme/accordionV2/accordionV2.css, and src/engine/theme/mount-shared-header.js.
12+
- Added ToolStarterShellControl to own Hide Header and Details behavior, summary state, fullscreen state classes, and summary metadata.
13+
- AccordionSection now uses data-accordion-v2-open, data-accordion-v2-bound, and data-accordion-v2-icon-state behavior consistent with current tool accordions.
14+
- Source input state now refreshes visible validation text when required input is cleared.
15+
16+
Playwright and coverage updates:
17+
- Workspace-v2 Playwright now launches tools/templates/first-class-tool-starter/index.html.
18+
- Workspace-v2 Playwright validates template launch, header/theme links, no tools/shared script/link dependencies, Hide Header and Details behavior, accordion interactions, Run enabled/disabled state, status/log clear behavior, and missing input validation.
19+
- Playwright V8 coverage report now includes First-Class Tool Starter Template in the exercised tool entry points.
20+
- Coverage helper excludes test specs under /tests/ from changed runtime JS classification.
21+
22+
Validation:
23+
- Playwright impacted: Yes
24+
- npm run test:workspace-v2 -> 5 passed.
25+
- Template-local Playwright validation: npx playwright test --config tools/templates/first-class-tool-starter/playwright.config.mjs --reporter=list -> 6 passed.
26+
- node --check passed for all changed starter JS/MJS files and updated Playwright/helper files.
27+
- git diff --check passed for scoped changed files.
28+
- Verified template HTML has no inline script blocks, style blocks, or inline event handlers.
29+
- Verified no actual tools/shared imports, script references, CSS references, or runtime dependencies were added.
30+
- Verified no tracked roadmap, samples, start_of_day, games, tools/shared, package, or package-lock files changed.
31+
32+
Coverage evidence:
33+
- docs/dev/reports/playwright_v8_coverage_report.txt lists First-Class Tool Starter Template as exercised.
34+
- Changed runtime JS coverage includes ToolStarterApp, ToolStarterShellControl, bootstrap, and AccordionSection.
35+
36+
Manual test notes:
37+
- Open tools/templates/first-class-tool-starter/index.html through a local HTTP server.
38+
- Confirm shared header renders, Hide Header and Details toggles the header, accordions collapse/expand, Run enables only after source input, Run writes status/output, Clear empties the status log, and clearing the source input restores the required-input message.

tests/helpers/playwrightV8CoverageReporter.mjs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,11 @@ export class PlaywrightV8CoverageReporter {
3838
async writeReport() {
3939
const coverageByPath = this.buildCoverageByPath();
4040
const changedJsFiles = this.getChangedJsFiles();
41-
const changedRuntimeJsFiles = changedJsFiles.filter((filePath) => (
42-
filePath.startsWith("src/")
43-
|| filePath.startsWith("tools/")
44-
|| filePath.startsWith("common/")
45-
));
41+
const changedRuntimeJsFiles = changedJsFiles.filter((filePath) => this.isRuntimeJsFile(filePath));
4642
const reportLines = [
4743
"Playwright V8 Coverage Report",
4844
"",
49-
"PR: PR_26126_059-playwright-coverage-multi-tool-verification",
45+
"PR: generated by current workspace-v2 Playwright run.",
5046
"Coverage source: Playwright/Chromium built-in V8 coverage.",
5147
"Coverage scope: all repo-relative browser JavaScript collected by Playwright/Chromium V8 coverage.",
5248
"Dependencies: no new npm packages.",
@@ -229,6 +225,15 @@ export class PlaywrightV8CoverageReporter {
229225
.sort((left, right) => left.localeCompare(right));
230226
}
231227

228+
isRuntimeJsFile(filePath) {
229+
if (filePath.includes("/tests/")) {
230+
return false;
231+
}
232+
return filePath.startsWith("src/")
233+
|| filePath.startsWith("tools/")
234+
|| filePath.startsWith("common/");
235+
}
236+
232237
pathFromStatusLine(line) {
233238
const rawPath = line.slice(3).trim();
234239
if (!rawPath) {
@@ -275,6 +280,7 @@ export class PlaywrightV8CoverageReporter {
275280
const toolEntryPoints = [
276281
{ name: "Preview Generator V2", prefix: "tools/preview-generator-v2/" },
277282
{ name: "Palette Manager", prefix: "tools/palette-manager-v2/" },
283+
{ name: "First-Class Tool Starter Template", prefix: "tools/templates/first-class-tool-starter/" },
278284
{ name: "Workspace V2", prefix: "tools/workspace-v2/" },
279285
{ name: "Workspace Manager", prefix: "tools/workspace-manager/" }
280286
];

tests/playwright/PreviewGeneratorV2Baseline.spec.mjs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ async function openPaletteManager(page) {
120120
return server;
121121
}
122122

123+
async function openToolTemplate(page) {
124+
const server = await startRepoServer();
125+
await coverageReporter.start(page);
126+
await page.goto(`${server.baseUrl}/tools/templates/first-class-tool-starter/index.html`, { waitUntil: "networkidle" });
127+
return server;
128+
}
129+
123130
async function expectAccordionToggles(page, contentId) {
124131
const header = page.locator(`.accordion-v2__header[aria-controls="${contentId}"]`);
125132
const content = page.locator(`#${contentId}`);
@@ -443,4 +450,55 @@ test.describe("Preview Generator V2 baseline", () => {
443450
await server.close();
444451
}
445452
});
453+
454+
test("launches first-class tool starter template with runtime-valid controls", async ({ page }) => {
455+
const server = await openToolTemplate(page);
456+
const pageErrors = [];
457+
458+
page.on("pageerror", (error) => {
459+
pageErrors.push(error.message);
460+
});
461+
462+
try {
463+
await expect(page.locator("body.tools-platform-tool-page[data-tool-id='first-class-tool-starter']")).toBeVisible();
464+
await expect(page.locator('link[href="../../../src/engine/theme/main.css"]')).toHaveCount(1);
465+
await expect(page.locator('link[href="../../../src/engine/theme/accordionV2/accordionV2.css"]')).toHaveCount(1);
466+
await expect(page.locator("#shared-theme-header")).toBeAttached();
467+
await expect(page.locator("[data-tool-starter-header]")).toContainText("First-Class Tool Starter");
468+
await expect(page.locator("[data-tool-starter-summary]")).toHaveAttribute("data-tools-platform-summary-active", "1");
469+
470+
const sharedReferences = await page.evaluate(() => [
471+
...document.querySelectorAll("script[src],link[href]")
472+
].map((element) => element.getAttribute("src") || element.getAttribute("href"))
473+
.filter((value) => value && value.includes("tools/shared")));
474+
expect(sharedReferences).toEqual([]);
475+
476+
const summary = page.locator("[data-tool-starter-summary]");
477+
const details = page.locator(".is-collapsible");
478+
await expect(summary).toContainText("Hide Header and Details");
479+
await summary.click();
480+
await expect(details).not.toHaveAttribute("open", "");
481+
await expect(summary).toHaveAttribute("data-tools-platform-summary-state", "collapsed");
482+
483+
await expectAccordionToggles(page, "sourceInputContent");
484+
485+
const runButton = page.locator("#runToolButton");
486+
await expect(runButton).toBeDisabled();
487+
await page.locator("#sourceInput").fill("starter value");
488+
await expect(runButton).toBeEnabled();
489+
await runButton.click();
490+
await expect(page.locator("#statusLog")).toHaveValue(/Processed source value/);
491+
await page.locator("#clearStatusButton").click();
492+
await expect(page.locator("#statusLog")).toHaveValue("");
493+
494+
await page.locator("#sourceInput").fill("");
495+
await expect(runButton).toBeDisabled();
496+
await expect(page.locator("#sourceValidationMessage")).toContainText("Input is required");
497+
498+
expect(pageErrors).toEqual([]);
499+
} finally {
500+
await coverageReporter.stop(page);
501+
await server.close();
502+
}
503+
});
446504
});

tools/templates/first-class-tool-starter/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ tools/<tool-id>/
2525
PreviewPanelControl.js
2626
SourceInputControl.js
2727
StatusLogControl.js
28+
ToolStarterShellControl.js
2829
services/
2930
ToolStateSerializer.js
3031
tests/
@@ -62,6 +63,8 @@ The contracts define:
6263
- One class per file.
6364
- One control or section per class.
6465
- Header markup follows the Palette Manager V2 pattern: `body.tools-platform-tool-page`, collapsible header/details, `#shared-theme-header`, and a tool-local header host.
66+
- Header styling consumes `src/engine/theme/main.css`, `src/engine/ui/hubCommon.css`, and `src/engine/theme/accordionV2/accordionV2.css`.
67+
- `ToolStarterShellControl` owns Hide Header and Details behavior, summary state, and fullscreen state classes.
6568
- App/root class coordinates only and must not own DOM logic or business logic.
6669
- Controls own their DOM and their events.
6770
- Controls communicate through injected callbacks or the app coordinator.

tools/templates/first-class-tool-starter/index.html

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,37 @@
1-
<!doctype html>
1+
<!doctype html>
22
<html lang="en">
33
<head>
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1">
66
<title>First-Class Tool Starter</title>
7+
<link rel="stylesheet" href="../../../src/engine/theme/main.css">
8+
<link rel="stylesheet" href="../../../src/engine/ui/hubCommon.css">
9+
<link rel="stylesheet" href="../../../src/engine/theme/accordionV2/accordionV2.css">
710
<link rel="stylesheet" href="./styles/toolStarter.css">
811
<script type="module" src="./js/bootstrap.js"></script>
912
</head>
10-
<body class="tools-platform-tool-page hub-page-tools" data-tool-id="first-class-tool-starter">
13+
<body class="tools-platform-tool-page tools-platform-surface hub-page-tools" data-tool-id="first-class-tool-starter">
1114
<details class="is-collapsible" open>
1215
<summary class="is-collapsible__summary" data-tool-starter-summary>Hide Header and Details</summary>
1316
<div class="is-collapsible__content">
1417
<div id="shared-theme-header"></div>
1518
<div class="tool-starter__header" data-tool-starter-header>
16-
<div>
17-
<h1>First-Class Tool Starter</h1>
18-
<p>Replace this shell with the new tool name and purpose.</p>
19-
</div>
20-
<p class="tool-starter__header-meta">Self-contained starter</p>
19+
<section class="tools-platform-frame tool-starter__local-shell-frame">
20+
<div class="tools-platform-frame__accordion-content">
21+
<div class="tools-platform-frame__accordion-summary">
22+
<div class="tools-platform-frame__summary-copy">
23+
<h1 class="tools-platform-frame__title" data-tool-id="first-class-tool-starter">First-Class Tool Starter</h1>
24+
<h2 class="tools-platform-frame__eyebrow">First-Class Tools Surface</h2>
25+
</div>
26+
<div class="tools-platform-frame__summary-meta">
27+
<div class="tools-platform-frame__meta">Self-contained starter with no tools/shared dependency.</div>
28+
</div>
29+
</div>
30+
<div class="tools-platform-frame__topline">
31+
<p class="tools-platform-frame__description">Replace this shell with the new tool name and purpose.</p>
32+
</div>
33+
</div>
34+
</section>
2135
</div>
2236
</div>
2337
</details>
@@ -30,7 +44,7 @@ <h1>First-Class Tool Starter</h1>
3044

3145
<main class="tool-starter app-shell" data-tool-id="first-class-tool-starter">
3246
<aside class="tool-starter__panel tool-starter__panel--left" aria-label="Tool inputs">
33-
<section class="accordion-v2 tool-starter__accordion is-open" data-accordion-open="true">
47+
<section class="accordion-v2 tool-starter__accordion is-open" data-accordion-v2-open="true">
3448
<button class="accordion-v2__header" type="button" aria-expanded="true" aria-controls="sourceInputContent">
3549
<span>Input Source</span>
3650
<span class="accordion-v2__icon" aria-hidden="true">+</span>
@@ -44,7 +58,7 @@ <h1>First-Class Tool Starter</h1>
4458
</div>
4559
</section>
4660

47-
<section class="accordion-v2 tool-starter__accordion is-open" data-accordion-open="true">
61+
<section class="accordion-v2 tool-starter__accordion is-open" data-accordion-v2-open="true">
4862
<button class="accordion-v2__header" type="button" aria-expanded="true" aria-controls="statusLogContent">
4963
<span>Status</span>
5064
<span class="accordion-v2__icon" aria-hidden="true">+</span>
@@ -57,7 +71,7 @@ <h1>First-Class Tool Starter</h1>
5771
</aside>
5872

5973
<section class="tool-starter__panel tool-starter__panel--center" aria-label="Tool preview">
60-
<section class="accordion-v2 tool-starter__accordion tool-starter__accordion--fill is-open" data-accordion-open="true">
74+
<section class="accordion-v2 tool-starter__accordion tool-starter__accordion--fill is-open" data-accordion-v2-open="true">
6175
<button class="accordion-v2__header" type="button" aria-expanded="true" aria-controls="previewPanelContent">
6276
<span>Preview</span>
6377
<span class="accordion-v2__icon" aria-hidden="true">+</span>
@@ -71,7 +85,7 @@ <h1>First-Class Tool Starter</h1>
7185
</section>
7286

7387
<aside class="tool-starter__panel tool-starter__panel--right" aria-label="Tool output">
74-
<section class="accordion-v2 tool-starter__accordion is-open" data-accordion-open="true">
88+
<section class="accordion-v2 tool-starter__accordion is-open" data-accordion-v2-open="true">
7589
<button class="accordion-v2__header" type="button" aria-expanded="true" aria-controls="inspectorContent">
7690
<span>Output Summary</span>
7791
<span class="accordion-v2__icon" aria-hidden="true">+</span>
@@ -82,5 +96,6 @@ <h1>First-Class Tool Starter</h1>
8296
</section>
8397
</aside>
8498
</main>
99+
<script type="module" src="../../../src/engine/theme/mount-shared-header.js"></script>
85100
</body>
86101
</html>

0 commit comments

Comments
 (0)