@hapergg/harness-comet-cli 0.1.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 (38) hide show
  1. package/bin/harness-comet.js +7 -0
  2. package/dist/commands/comet.d.ts +8 -0
  3. package/dist/commands/comet.d.ts.map +1 -0
  4. package/dist/commands/comet.js +500 -0
  5. package/dist/commands/comet.js.map +1 -0
  6. package/dist/commands/create.d.ts +16 -0
  7. package/dist/commands/create.d.ts.map +1 -0
  8. package/dist/commands/create.js +69 -0
  9. package/dist/commands/create.js.map +1 -0
  10. package/dist/commands/impact.d.ts +8 -0
  11. package/dist/commands/impact.d.ts.map +1 -0
  12. package/dist/commands/impact.js +108 -0
  13. package/dist/commands/impact.js.map +1 -0
  14. package/dist/commands/init.d.ts +19 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +249 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/dev-bin.d.ts +2 -0
  19. package/dist/dev-bin.d.ts.map +1 -0
  20. package/dist/dev-bin.js +6 -0
  21. package/dist/dev-bin.js.map +1 -0
  22. package/dist/index.d.ts +6 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +393 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/package-info.d.ts +6 -0
  27. package/dist/package-info.d.ts.map +1 -0
  28. package/dist/package-info.js +6 -0
  29. package/dist/package-info.js.map +1 -0
  30. package/dist/templates/incident.d.ts +3 -0
  31. package/dist/templates/incident.d.ts.map +1 -0
  32. package/dist/templates/incident.js +26 -0
  33. package/dist/templates/incident.js.map +1 -0
  34. package/dist/templates/playwright-mode.d.ts +12 -0
  35. package/dist/templates/playwright-mode.d.ts.map +1 -0
  36. package/dist/templates/playwright-mode.js +225 -0
  37. package/dist/templates/playwright-mode.js.map +1 -0
  38. package/package.json +58 -0
@@ -0,0 +1,225 @@
1
+ export function playwrightHarnessCometConfigTemplate(testDir = "tests") {
2
+ return `export default {
3
+ schemaVersion: 1,
4
+ mode: "playwright",
5
+ playwright: {
6
+ configFile: "playwright.config.ts",
7
+ testDir: "${testDir}",
8
+ testMatch: ["**/*.spec.ts"],
9
+ assetRoots: ["${testDir}"],
10
+ resultsFile: "test-results/harness-comet/results.json"
11
+ },
12
+ docs: {
13
+ testingDir: "docs/testing"
14
+ },
15
+ incidents: {
16
+ directory: "${testDir}/incidents",
17
+ requireIssueUrl: false,
18
+ requireReadme: true
19
+ },
20
+ validation: {
21
+ forbidOnly: true,
22
+ longWaitWarningMs: 5000
23
+ }
24
+ };
25
+ `;
26
+ }
27
+ export function playwrightConfigTemplate(testDir = "tests") {
28
+ return `import { defineConfig } from "@playwright/test";
29
+
30
+ export default defineConfig({
31
+ testDir: "${testDir}",
32
+ testMatch: ["**/*.spec.ts"],
33
+ fullyParallel: true,
34
+ forbidOnly: Boolean(process.env.CI),
35
+ retries: process.env.CI ? 2 : 0,
36
+ workers: process.env.CI ? 2 : undefined,
37
+ reporter: [["list"], ["html", { open: "never" }], ["@hapergg/harness-comet-playwright/reporter"]],
38
+ expect: {
39
+ timeout: 10_000
40
+ },
41
+ use: {
42
+ headless: true,
43
+ viewport: { width: 1440, height: 900 },
44
+ actionTimeout: 15_000,
45
+ navigationTimeout: 30_000,
46
+ baseURL: process.env.PLAYWRIGHT_BASE_URL ?? "http://localhost:3000",
47
+ trace: "on-first-retry",
48
+ screenshot: "only-on-failure",
49
+ video: "retain-on-failure"
50
+ },
51
+ projects: [
52
+ {
53
+ name: "chromium",
54
+ use: { browserName: "chromium" }
55
+ }
56
+ ]
57
+ });
58
+ `;
59
+ }
60
+ export function playwrightExampleSpecTemplate() {
61
+ return `import { expect, test } from "@playwright/test";
62
+ import input from "../data/example-input.json" with { type: "json" };
63
+ import expectedPayload from "../data/example-expected-payload.json" with { type: "json" };
64
+ import { attachJson } from "../support/attachments";
65
+ import { mockJson } from "../support/mock-api";
66
+
67
+ test(
68
+ "Example save flow",
69
+ {
70
+ tag: ["@harness", "@annotation-save"]
71
+ },
72
+ async ({ page }, testInfo) => {
73
+ const captured: unknown[] = [];
74
+
75
+ await mockJson(page, "**/api/bootstrap", {
76
+ featureFlags: { annotationSave: true }
77
+ });
78
+
79
+ await page.route("**/api/annotations", async (route) => {
80
+ const request = route.request();
81
+ captured.push(JSON.parse(request.postData() ?? "{}"));
82
+ await route.fulfill({
83
+ status: 200,
84
+ contentType: "application/json",
85
+ body: JSON.stringify({ ok: true, saved: true })
86
+ });
87
+ });
88
+
89
+ await page.setContent(\`
90
+ <main>
91
+ <h1>Annotation Editor</h1>
92
+ <label>
93
+ Label
94
+ <input data-testid="label" />
95
+ </label>
96
+ <label>
97
+ Comment
98
+ <textarea data-testid="comment"></textarea>
99
+ </label>
100
+ <button data-testid="save">Save</button>
101
+ <output data-testid="status"></output>
102
+ </main>
103
+ <script>
104
+ async function bootstrap() {
105
+ const response = await fetch('/api/bootstrap');
106
+ window.__bootstrap = await response.json();
107
+ }
108
+ document.querySelector('[data-testid="save"]').addEventListener('click', async () => {
109
+ const payload = {
110
+ id: "annotation-1",
111
+ label: document.querySelector('[data-testid="label"]').value,
112
+ comment: document.querySelector('[data-testid="comment"]').value
113
+ };
114
+ await fetch('/api/annotations', {
115
+ method: 'POST',
116
+ headers: { 'content-type': 'application/json' },
117
+ body: JSON.stringify(payload)
118
+ });
119
+ document.querySelector('[data-testid="status"]').textContent = 'Saved';
120
+ });
121
+ bootstrap();
122
+ </script>
123
+ \`);
124
+
125
+ await expect
126
+ .poll(() => page.evaluate(() => Boolean(window.__bootstrap?.featureFlags?.annotationSave)))
127
+ .toBe(true);
128
+ await page.getByTestId("label").fill((input as { label: string }).label);
129
+ await page.getByTestId("comment").fill((input as { comment: string }).comment);
130
+ await page.getByTestId("save").click();
131
+
132
+ await expect(page.getByTestId("status")).toHaveText("Saved");
133
+ expect(captured[0]).toEqual(expectedPayload);
134
+ await attachJson(testInfo, "captured-payload", captured[0]);
135
+ }
136
+ );
137
+ `;
138
+ }
139
+ export function playwrightFixturesTemplate() {
140
+ return `export const harnessBaseUrl = process.env.PLAYWRIGHT_BASE_URL ?? "http://localhost:3000";
141
+ `;
142
+ }
143
+ export function playwrightMockApiTemplate() {
144
+ return `import type { Page } from "@playwright/test";
145
+
146
+ export async function mockJson(
147
+ page: Page,
148
+ url: string,
149
+ body: unknown,
150
+ status = 200
151
+ ): Promise<void> {
152
+ await page.route(url, async (route) => {
153
+ await route.fulfill({
154
+ status,
155
+ contentType: "application/json",
156
+ body: JSON.stringify(body)
157
+ });
158
+ });
159
+ }
160
+ `;
161
+ }
162
+ export function playwrightAttachmentsTemplate() {
163
+ return `import type { TestInfo } from "@playwright/test";
164
+
165
+ export async function attachJson(testInfo: TestInfo, name: string, value: unknown): Promise<void> {
166
+ await testInfo.attach(\`\${name}.json\`, {
167
+ body: Buffer.from(JSON.stringify(value, null, 2)),
168
+ contentType: "application/json"
169
+ });
170
+ }
171
+ `;
172
+ }
173
+ export function playwrightIncidentReadmeTemplate() {
174
+ return `# Incident Tests
175
+
176
+ Store incident-focused Playwright assets here. Each incident should have:
177
+
178
+ - an incident metadata file
179
+ - a focused spec
180
+ - input and expected payload fixtures
181
+ - a README describing reproduction and verification notes
182
+ `;
183
+ }
184
+ export function playwrightAuthoringGuideTemplate() {
185
+ return `# Authoring Guide
186
+
187
+ Prefer one business behavior per Playwright test file. Keep the test focused on:
188
+
189
+ - deterministic fixtures
190
+ - request mocking
191
+ - payload capture
192
+ - clear assertions
193
+ - attached JSON evidence
194
+ `;
195
+ }
196
+ export function playwrightIncidentGuideTemplate() {
197
+ return `# Incident Guide
198
+
199
+ Use \`harness-comet create incident <id>\` to scaffold incident assets, then keep the spec and fixture files close to the incident metadata.
200
+ `;
201
+ }
202
+ export function playwrightAcceptanceCriteriaTemplate() {
203
+ return `# Acceptance Criteria
204
+
205
+ Every Playwright Harness change should leave behind:
206
+
207
+ - declared target tests
208
+ - verification evidence
209
+ - results JSON
210
+ - a markdown verify report
211
+ - a receipt that archive-check can validate
212
+ `;
213
+ }
214
+ export function testingReadmeTemplate() {
215
+ return `# Testing
216
+
217
+ This project uses Playwright mode for Harness-Comet.
218
+
219
+ Playwright owns test execution through \`playwright.config.ts\`.
220
+ Harness-Comet owns business scenario metadata, Comet impact decisions, verification evidence, and archive checks.
221
+
222
+ Keep tests focused on business behavior. Add helper files and directories only when the project needs them.
223
+ `;
224
+ }
225
+ //# sourceMappingURL=playwright-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playwright-mode.js","sourceRoot":"","sources":["../../src/templates/playwright-mode.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oCAAoC,CAAC,OAAO,GAAG,OAAO;IACpE,OAAO;;;;;gBAKO,OAAO;;oBAEH,OAAO;;;;;;;kBAOT,OAAO;;;;;;;;;CASxB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAO,GAAG,OAAO;IACxD,OAAO;;;cAGK,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BpB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4ER,CAAC;AACF,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO;CACR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,OAAO;;;;;;;;;;;;;;;;CAgBR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,6BAA6B;IAC3C,OAAO;;;;;;;;CAQR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gCAAgC;IAC9C,OAAO;;;;;;;;CAQR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,gCAAgC;IAC9C,OAAO;;;;;;;;;CASR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,+BAA+B;IAC7C,OAAO;;;CAGR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,oCAAoC;IAClD,OAAO;;;;;;;;;CASR,CAAC;AACF,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;CAQR,CAAC;AACF,CAAC"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@hapergg/harness-comet-cli",
3
+ "version": "0.1.0",
4
+ "description": "Command line interface for initializing, validating, and running Harness Comet projects.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/HarperGG/harness-comet.git",
13
+ "directory": "packages/cli"
14
+ },
15
+ "homepage": "https://github.com/HarperGG/harness-comet#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/HarperGG/harness-comet/issues"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "bin"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public",
25
+ "registry": "https://registry.npmjs.org/"
26
+ },
27
+ "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "bin": {
37
+ "harness-comet": "./bin/harness-comet.js"
38
+ },
39
+ "dependencies": {
40
+ "commander": "^14.0.2",
41
+ "execa": "^9.6.0",
42
+ "picocolors": "^1.1.1",
43
+ "@hapergg/harness-comet-adapter-playwright": "0.1.0",
44
+ "@hapergg/harness-comet-schema": "0.1.0",
45
+ "@hapergg/harness-comet-adapter-memory": "0.1.0",
46
+ "@hapergg/harness-comet-core": "0.1.0",
47
+ "@hapergg/harness-comet-comet-adapter": "0.1.0"
48
+ },
49
+ "devDependencies": {
50
+ "typescript": "^5.9.3",
51
+ "vitest": "^4.0.14"
52
+ },
53
+ "scripts": {
54
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
55
+ "build": "tsc -b && chmod +x bin/harness-comet.js",
56
+ "test": "vitest run"
57
+ }
58
+ }