@swedevtools/livedoc-vitest 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.
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/dist/RuleContext-BZhuy-zS.d.cts +206 -0
- package/dist/RuleContext-BZhuy-zS.d.ts +206 -0
- package/dist/globals.cjs +2 -0
- package/dist/globals.d.cts +104 -0
- package/dist/globals.d.ts +104 -0
- package/dist/globals.js +1 -0
- package/dist/index-Blmp569T.d.cts +687 -0
- package/dist/index-CysiWbtk.d.ts +687 -0
- package/dist/index.cjs +10024 -0
- package/dist/index.d.cts +291 -0
- package/dist/index.d.ts +291 -0
- package/dist/index.js +9933 -0
- package/dist/playwright/index.cjs +103 -0
- package/dist/playwright/index.d.cts +129 -0
- package/dist/playwright/index.d.ts +129 -0
- package/dist/playwright/index.js +99 -0
- package/dist/reporter/index.cjs +8676 -0
- package/dist/reporter/index.d.cts +7 -0
- package/dist/reporter/index.d.ts +7 -0
- package/dist/reporter/index.js +8635 -0
- package/dist/setup.cjs +14 -0
- package/dist/setup.d.cts +2 -0
- package/dist/setup.d.ts +2 -0
- package/dist/setup.js +12 -0
- package/package.json +135 -0
- package/tools/livedoc-setup.mjs +164 -0
- package/tools/skills/SKILL.md +244 -0
- package/tools/skills/VALIDATION.md +29 -0
- package/tools/skills/examples/routing.md +60 -0
- package/tools/skills/resources/bdd-features.md +231 -0
- package/tools/skills/resources/playwright.md +148 -0
- package/tools/skills/resources/reporter-config.md +163 -0
- package/tools/skills/resources/specifications.md +159 -0
package/dist/setup.cjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var livedocVitest = require('@swedevtools/livedoc-vitest');
|
|
4
|
+
|
|
5
|
+
// _src/app/setup.ts
|
|
6
|
+
globalThis.feature = livedocVitest.feature;
|
|
7
|
+
globalThis.scenario = livedocVitest.scenario;
|
|
8
|
+
globalThis.scenarioOutline = livedocVitest.scenarioOutline;
|
|
9
|
+
globalThis.background = livedocVitest.background;
|
|
10
|
+
globalThis.given = livedocVitest.given;
|
|
11
|
+
globalThis.when = livedocVitest.when;
|
|
12
|
+
globalThis.then = livedocVitest.Then;
|
|
13
|
+
globalThis.and = livedocVitest.and;
|
|
14
|
+
globalThis.but = livedocVitest.but;
|
package/dist/setup.d.cts
ADDED
package/dist/setup.d.ts
ADDED
package/dist/setup.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { feature, scenario, scenarioOutline, background, given, when, Then, and, but } from '@swedevtools/livedoc-vitest';
|
|
2
|
+
|
|
3
|
+
// _src/app/setup.ts
|
|
4
|
+
globalThis.feature = feature;
|
|
5
|
+
globalThis.scenario = scenario;
|
|
6
|
+
globalThis.scenarioOutline = scenarioOutline;
|
|
7
|
+
globalThis.background = background;
|
|
8
|
+
globalThis.given = given;
|
|
9
|
+
globalThis.when = when;
|
|
10
|
+
globalThis.then = Then;
|
|
11
|
+
globalThis.and = and;
|
|
12
|
+
globalThis.but = but;
|
package/package.json
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@swedevtools/livedoc-vitest",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"author": "Garry McGlennon",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "BDD extensions for Vitest that support LiveDoc reporting with Gherkin syntax and MSpec-style specifications.",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/dotnetprofessional/LiveDoc.git",
|
|
10
|
+
"directory": "packages/vitest"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/dotnetprofessional/LiveDoc/tree/master/packages/vitest#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/dotnetprofessional/LiveDoc/issues"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"bin": {
|
|
21
|
+
"livedoc-vitest-setup": "./tools/livedoc-setup.mjs"
|
|
22
|
+
},
|
|
23
|
+
"main": "./dist/index.cjs",
|
|
24
|
+
"module": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"require": "./dist/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./reporter": {
|
|
33
|
+
"types": "./dist/reporter/index.d.ts",
|
|
34
|
+
"import": "./dist/reporter/index.js",
|
|
35
|
+
"require": "./dist/reporter/index.cjs"
|
|
36
|
+
},
|
|
37
|
+
"./setup": {
|
|
38
|
+
"types": "./dist/setup.d.ts",
|
|
39
|
+
"import": "./dist/setup.js",
|
|
40
|
+
"require": "./dist/setup.cjs"
|
|
41
|
+
},
|
|
42
|
+
"./globals": {
|
|
43
|
+
"types": "./dist/globals.d.ts",
|
|
44
|
+
"import": "./dist/globals.js",
|
|
45
|
+
"require": "./dist/globals.cjs"
|
|
46
|
+
},
|
|
47
|
+
"./playwright": {
|
|
48
|
+
"types": "./dist/playwright/index.d.ts",
|
|
49
|
+
"import": "./dist/playwright/index.js",
|
|
50
|
+
"require": "./dist/playwright/index.cjs"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist",
|
|
55
|
+
"tools",
|
|
56
|
+
"README.md",
|
|
57
|
+
"LICENSE"
|
|
58
|
+
],
|
|
59
|
+
"keywords": [
|
|
60
|
+
"livedoc",
|
|
61
|
+
"vitest",
|
|
62
|
+
"bdd",
|
|
63
|
+
"gherkin",
|
|
64
|
+
"cucumber",
|
|
65
|
+
"mspec",
|
|
66
|
+
"specification",
|
|
67
|
+
"javascript",
|
|
68
|
+
"typescript",
|
|
69
|
+
"testing",
|
|
70
|
+
"tests"
|
|
71
|
+
],
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=18.0.0"
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@types/chai": "^5.2.3",
|
|
77
|
+
"@types/fs-extra": "^11.0.4",
|
|
78
|
+
"@types/node": "^20.19.27",
|
|
79
|
+
"@types/wordwrap": "^1.0.3",
|
|
80
|
+
"@vitest/runner": "^4.0.16",
|
|
81
|
+
"@vitest/ui": "^4.0.16",
|
|
82
|
+
"chai": "^6.2.1",
|
|
83
|
+
"playwright": "^1.59.1",
|
|
84
|
+
"rimraf": "^5.0.10",
|
|
85
|
+
"strip-ansi": "^7.1.2",
|
|
86
|
+
"tsup": "^8.5.1",
|
|
87
|
+
"typescript": "^5.9.3",
|
|
88
|
+
"vitest": "^4.0.16",
|
|
89
|
+
"@swedevtools/livedoc-schema": "1.2.0",
|
|
90
|
+
"@swedevtools/livedoc-server": "^1.2.1"
|
|
91
|
+
},
|
|
92
|
+
"peerDependencies": {
|
|
93
|
+
"@swedevtools/livedoc-server": ">=1.0.0",
|
|
94
|
+
"playwright": ">=1.50.0",
|
|
95
|
+
"vitest": ">=1.0.0"
|
|
96
|
+
},
|
|
97
|
+
"peerDependenciesMeta": {
|
|
98
|
+
"@swedevtools/livedoc-server": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"playwright": {
|
|
102
|
+
"optional": true
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"dependencies": {
|
|
106
|
+
"@types/diff": "^7.0.2",
|
|
107
|
+
"chalk": "^5.6.2",
|
|
108
|
+
"cli-table3": "^0.6.5",
|
|
109
|
+
"diff": "^5.2.0",
|
|
110
|
+
"fs-extra": "^11.3.3",
|
|
111
|
+
"wordwrap": "^1.0.0"
|
|
112
|
+
},
|
|
113
|
+
"scripts": {
|
|
114
|
+
"test": "vitest run --config livedoc.vitest.ts",
|
|
115
|
+
"test:watch": "vitest --config livedoc.vitest.ts",
|
|
116
|
+
"test:ui": "vitest --ui --config livedoc.vitest.ts",
|
|
117
|
+
"test:summary": "vitest run --config vitest.config.summary.ts",
|
|
118
|
+
"test:list": "vitest run --config vitest.config.list.ts",
|
|
119
|
+
"test:spec": "vitest run --config livedoc.vitest.ts",
|
|
120
|
+
"test:silent": "vitest run --config vitest.config.silent.ts",
|
|
121
|
+
"test:file": "vitest run --config vitest.config.file.ts",
|
|
122
|
+
"test:json": "vitest run --config vitest.config.json.ts",
|
|
123
|
+
"test:viewer": "vitest run --config vitest.config.viewer.ts",
|
|
124
|
+
"test:publish": "vitest run --config vitest.config.publish.ts",
|
|
125
|
+
"test:coverage": "vitest run --coverage --config livedoc.vitest.ts",
|
|
126
|
+
"clean": "rimraf dist \"*.tgz\" -g",
|
|
127
|
+
"compile": "tsup",
|
|
128
|
+
"build": "npm run compile",
|
|
129
|
+
"watch": "tsup --watch",
|
|
130
|
+
"pack:local": "pnpm pack",
|
|
131
|
+
"publish:dry": "npm publish --dry-run",
|
|
132
|
+
"publish:beta": "npm publish --tag beta",
|
|
133
|
+
"publish:release": "npm publish"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// LiveDoc AI Skill Installer — install AI coding skills for your team.
|
|
3
|
+
// Usage:
|
|
4
|
+
// npx @swedevtools/livedoc-vitest setup # Interactive menu
|
|
5
|
+
// npx @swedevtools/livedoc-vitest setup --tool copilot # Non-interactive
|
|
6
|
+
// npx livedoc-vitest-setup --tool all # Direct bin entry
|
|
7
|
+
|
|
8
|
+
import { existsSync, mkdirSync, cpSync, readdirSync, statSync, copyFileSync } from 'node:fs';
|
|
9
|
+
import { join, dirname, resolve, relative } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { createInterface } from 'node:readline';
|
|
12
|
+
import { execSync } from 'node:child_process';
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
|
|
17
|
+
// ── Paths ──────────────────────────────────────────────────
|
|
18
|
+
const skillsSource = join(__dirname, 'skills');
|
|
19
|
+
|
|
20
|
+
if (!existsSync(join(skillsSource, 'SKILL.md'))) {
|
|
21
|
+
console.error(' Error: Could not find skill files at', skillsSource);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ── Git root discovery ─────────────────────────────────────
|
|
26
|
+
function findGitRoot() {
|
|
27
|
+
try {
|
|
28
|
+
return execSync('git rev-parse --show-toplevel', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
29
|
+
} catch {
|
|
30
|
+
return process.cwd();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const gitRoot = findGitRoot();
|
|
35
|
+
|
|
36
|
+
// ── Tool definitions (same mapping as xUnit SDK) ──────────
|
|
37
|
+
const tools = [
|
|
38
|
+
{ key: 'copilot', name: 'GitHub Copilot', dest: '.github/skills/livedoc-vitest' },
|
|
39
|
+
{ key: 'claude', name: 'Claude Code', dest: '.claude/skills/livedoc-vitest' },
|
|
40
|
+
{ key: 'roo', name: 'Roo Code', dest: '.roo/skills/livedoc-vitest' },
|
|
41
|
+
{ key: 'cursor', name: 'Cursor', dest: '.cursor/rules/livedoc-vitest' },
|
|
42
|
+
{ key: 'windsurf', name: 'Windsurf', dest: '.windsurf/rules/livedoc-vitest' },
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
// ── Recursive directory copy ──────────────────────────────
|
|
46
|
+
function copyRecursive(src, dest) {
|
|
47
|
+
const entries = readdirSync(src, { withFileTypes: true });
|
|
48
|
+
mkdirSync(dest, { recursive: true });
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const srcPath = join(src, entry.name);
|
|
51
|
+
const destPath = join(dest, entry.name);
|
|
52
|
+
if (entry.isDirectory()) {
|
|
53
|
+
copyRecursive(srcPath, destPath);
|
|
54
|
+
} else {
|
|
55
|
+
copyFileSync(srcPath, destPath);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ── Install skills for selected tools ─────────────────────
|
|
61
|
+
function installSkills(selected) {
|
|
62
|
+
console.log('');
|
|
63
|
+
for (const tool of selected) {
|
|
64
|
+
const dest = join(gitRoot, tool.dest);
|
|
65
|
+
copyRecursive(skillsSource, dest);
|
|
66
|
+
console.log(` \x1b[32m[ok]\x1b[0m ${tool.name} → ${dest}`);
|
|
67
|
+
}
|
|
68
|
+
console.log('');
|
|
69
|
+
console.log(' \x1b[36mDone! Commit the generated files to share with your team.\x1b[0m');
|
|
70
|
+
console.log('');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ── Parse CLI args ────────────────────────────────────────
|
|
74
|
+
function parseArgs() {
|
|
75
|
+
const args = process.argv.slice(2);
|
|
76
|
+
// Strip leading "setup" command if present (npx @swedevtools/livedoc-vitest setup --tool X)
|
|
77
|
+
if (args[0] === 'setup') args.shift();
|
|
78
|
+
|
|
79
|
+
let toolArg = null;
|
|
80
|
+
for (let i = 0; i < args.length; i++) {
|
|
81
|
+
if (args[i] === '--tool' && args[i + 1]) {
|
|
82
|
+
toolArg = args[i + 1].toLowerCase();
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
// Also support --tool=value
|
|
86
|
+
if (args[i].startsWith('--tool=')) {
|
|
87
|
+
toolArg = args[i].slice('--tool='.length).toLowerCase();
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return toolArg;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── Non-interactive mode ──────────────────────────────────
|
|
95
|
+
function resolveNonInteractive(toolArg) {
|
|
96
|
+
if (toolArg === 'all') return tools;
|
|
97
|
+
|
|
98
|
+
const match = tools.find((t) => t.key === toolArg);
|
|
99
|
+
if (!match) {
|
|
100
|
+
console.error(` Unknown tool: ${toolArg}. Use: copilot, claude, roo, cursor, windsurf, all`);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
return [match];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Interactive menu ──────────────────────────────────────
|
|
107
|
+
function showInteractiveMenu() {
|
|
108
|
+
return new Promise((resolve) => {
|
|
109
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
110
|
+
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log(' \x1b[36mLiveDoc AI Skill Installer\x1b[0m');
|
|
113
|
+
console.log('');
|
|
114
|
+
console.log(' Select AI tool(s) to install skills for:');
|
|
115
|
+
console.log('');
|
|
116
|
+
tools.forEach((t, i) => {
|
|
117
|
+
console.log(` ${i + 1}. ${t.name}`);
|
|
118
|
+
});
|
|
119
|
+
console.log(' A. All of the above');
|
|
120
|
+
console.log('');
|
|
121
|
+
|
|
122
|
+
rl.question(' Choice [A]: ', (answer) => {
|
|
123
|
+
rl.close();
|
|
124
|
+
const choice = (answer || 'A').trim();
|
|
125
|
+
|
|
126
|
+
if (choice.toLowerCase() === 'a') {
|
|
127
|
+
resolve(tools);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const idx = parseInt(choice, 10);
|
|
132
|
+
if (idx >= 1 && idx <= tools.length) {
|
|
133
|
+
resolve([tools[idx - 1]]);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
console.error(` Invalid choice: ${choice}`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ── Main ──────────────────────────────────────────────────
|
|
144
|
+
async function main() {
|
|
145
|
+
const toolArg = parseArgs();
|
|
146
|
+
|
|
147
|
+
let selected;
|
|
148
|
+
if (toolArg) {
|
|
149
|
+
selected = resolveNonInteractive(toolArg);
|
|
150
|
+
} else if (!process.stdin.isTTY) {
|
|
151
|
+
// Non-interactive context without --tool: default to all
|
|
152
|
+
console.log(' Non-interactive context detected. Installing for all tools.');
|
|
153
|
+
selected = tools;
|
|
154
|
+
} else {
|
|
155
|
+
selected = await showInteractiveMenu();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
installSkills(selected);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
main().catch((err) => {
|
|
162
|
+
console.error(err);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
});
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: livedoc-vitest
|
|
3
|
+
description: Expert guidance for writing and modifying BDD/Gherkin and MSpec-style tests using the @swedevtools/livedoc-vitest framework. Generates self-documenting TypeScript specs with correct API usage, value extraction, and living documentation patterns.
|
|
4
|
+
sdk_version: 0.2.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# LiveDoc Vitest Test Author
|
|
8
|
+
|
|
9
|
+
> **Progressive disclosure**: This file is the routing hub. Read the appropriate sub-resource for full API details.
|
|
10
|
+
|
|
11
|
+
## Version Check
|
|
12
|
+
|
|
13
|
+
This skill targets **@swedevtools/livedoc-vitest v0.2.0**. Before writing tests, verify the installed version matches:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm ls @swedevtools/livedoc-vitest # or: pnpm ls @swedevtools/livedoc-vitest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
If the installed version differs from `0.2.0`, tell the developer: *"Your LiveDoc skill files target v0.2.0 but you have vX.Y.Z installed. Run `npx livedoc-vitest-setup` to update the skill files, or check the changelog for breaking changes."*
|
|
20
|
+
|
|
21
|
+
## Use this skill when
|
|
22
|
+
- Creating or modifying `.Spec.ts` test files using `@swedevtools/livedoc-vitest`
|
|
23
|
+
- Writing BDD `feature`/`scenario` tests → **read `resources/bdd-features.md`**
|
|
24
|
+
- Writing MSpec `specification`/`rule` tests → **read `resources/specifications.md`**
|
|
25
|
+
- Writing browser-based Playwright tests → **read `resources/playwright.md`**
|
|
26
|
+
- Configuring reporters or static HTML export → **read `resources/reporter-config.md`**
|
|
27
|
+
- Debugging or fixing any LiveDoc Vitest test failures
|
|
28
|
+
|
|
29
|
+
## Do not use this skill when
|
|
30
|
+
- Writing C#/.NET xUnit tests (use `livedoc-xunit` skill instead)
|
|
31
|
+
- Working on non-test TypeScript code (application logic, UI components, build scripts)
|
|
32
|
+
- Writing plain Vitest tests without LiveDoc BDD/Specification patterns
|
|
33
|
+
- Working on the viewer, VS Code extension, or server packages (unless writing their specs)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Two Test Patterns
|
|
38
|
+
|
|
39
|
+
### 1. BDD Features (`resources/bdd-features.md`)
|
|
40
|
+
|
|
41
|
+
**Use when**: Testing user journeys, business flows, acceptance criteria. Audience is business + technical. Tests read as Given/When/Then narratives.
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { feature, scenario, given, when, Then as then } from "@swedevtools/livedoc-vitest";
|
|
45
|
+
|
|
46
|
+
feature("Shipping Costs", () => {
|
|
47
|
+
scenario("Free shipping for Australian orders over $100", () => {
|
|
48
|
+
let cart: ShoppingCart;
|
|
49
|
+
|
|
50
|
+
given("the customer is from 'Australia'", (ctx) => {
|
|
51
|
+
cart = new ShoppingCart({ country: ctx.step.values[0] });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
when("the order totals '100.00' dollars", (ctx) => {
|
|
55
|
+
cart.total = ctx.step.values[0];
|
|
56
|
+
cart.calculate();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
then("shipping type is 'Free'", (ctx) => {
|
|
60
|
+
expect(cart.shippingType).toBe(ctx.step.values[0]);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Key concepts**: `feature`, `scenario`, `scenarioOutline`, `background`, `given`/`when`/`then`/`and`/`but`, `ctx.step.values`, `ctx.step.params`, `ctx.example`, data tables, doc strings.
|
|
67
|
+
|
|
68
|
+
→ **Read `resources/bdd-features.md`** for complete keyword reference, background patterns, scenarioOutline with Examples, value extraction API, data tables, doc strings, attachment API, and validation checklist.
|
|
69
|
+
|
|
70
|
+
### 2. Specifications (`resources/specifications.md`)
|
|
71
|
+
|
|
72
|
+
**Use when**: Testing APIs, utilities, algorithms, data-driven edge cases. Developer-only audience. Direct assertions in rules — no Given/When/Then ceremony.
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { specification, rule, ruleOutline } from "@swedevtools/livedoc-vitest";
|
|
76
|
+
|
|
77
|
+
specification("Calculator Operations", () => {
|
|
78
|
+
rule("Adding '5' and '3' returns '8'", (ctx) => {
|
|
79
|
+
const [a, b, expected] = ctx.rule.values;
|
|
80
|
+
expect(a + b).toBe(expected);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
ruleOutline(`Discount calculations
|
|
84
|
+
Examples:
|
|
85
|
+
| price | discount | expected |
|
|
86
|
+
| 100 | 10 | 90 |
|
|
87
|
+
| 200 | 25 | 150 |
|
|
88
|
+
`, (ctx) => {
|
|
89
|
+
const result = ctx.example.price - (ctx.example.price * ctx.example.discount / 100);
|
|
90
|
+
expect(result).toBe(ctx.example.expected);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Key concepts**: `specification`, `rule`, `ruleOutline`, `ctx.rule.values`, `ctx.rule.params`, `ctx.example`, data-driven testing.
|
|
96
|
+
|
|
97
|
+
→ **Read `resources/specifications.md`** for complete keyword reference, value extraction API, ruleOutline with Examples, async rules, and validation checklist.
|
|
98
|
+
|
|
99
|
+
### 3. Playwright Integration (`resources/playwright.md`)
|
|
100
|
+
|
|
101
|
+
**Use when**: Browser-based testing — UI validation, screenshot capture, end-to-end web testing.
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { useBrowser, screenshot } from "@swedevtools/livedoc-vitest/playwright";
|
|
105
|
+
|
|
106
|
+
const { page } = useBrowser();
|
|
107
|
+
|
|
108
|
+
// Inside a scenario step:
|
|
109
|
+
when("navigating to the homepage", async (ctx) => {
|
|
110
|
+
await page().goto("http://localhost:3000");
|
|
111
|
+
await screenshot(page(), ctx);
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
→ **Read `resources/playwright.md`** for `useBrowser` options, `screenshot` API, lifecycle management, and troubleshooting.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Shared Concepts
|
|
120
|
+
|
|
121
|
+
### Folder Structure = Report Hierarchy
|
|
122
|
+
|
|
123
|
+
The **file path** of each `.Spec.ts` file determines the visual tree in the LiveDoc Viewer:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
_src/test/
|
|
127
|
+
├── Checkout/ → "Checkout" node in viewer
|
|
128
|
+
│ └── Cart.Spec.ts
|
|
129
|
+
├── Shipping/ → "Shipping" node
|
|
130
|
+
│ └── Costs.Spec.ts
|
|
131
|
+
└── Auth/ → "Auth" node
|
|
132
|
+
└── Login.Spec.ts
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Import Pattern
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// BDD pattern
|
|
139
|
+
import { feature, scenario, scenarioOutline, background, given, when, Then as then, and, but } from "@swedevtools/livedoc-vitest";
|
|
140
|
+
|
|
141
|
+
// Specification pattern
|
|
142
|
+
import { specification, rule, ruleOutline } from "@swedevtools/livedoc-vitest";
|
|
143
|
+
|
|
144
|
+
// Playwright (optional)
|
|
145
|
+
import { useBrowser, screenshot } from "@swedevtools/livedoc-vitest/playwright";
|
|
146
|
+
|
|
147
|
+
// Or use globals mode — requires BOTH settings in vitest.config.ts:
|
|
148
|
+
// globals: true
|
|
149
|
+
// setupFiles: ['@swedevtools/livedoc-vitest/setup']
|
|
150
|
+
// Note: globals mode only registers BDD keywords (feature, scenario, given, when, then, etc.)
|
|
151
|
+
// Specification keywords (specification, rule, ruleOutline) must still be imported explicitly.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**CRITICAL**: Import `Then` (uppercase) and alias as `then` (lowercase). ESM thenable detection requires the uppercase export name.
|
|
155
|
+
|
|
156
|
+
### CRITICAL: Self-Documenting Tests
|
|
157
|
+
|
|
158
|
+
**Embed all inputs and expected outputs in step/rule titles.** Extract them using context APIs. Never hardcode values that appear in titles.
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// ✅ Values in title AND extracted from context
|
|
162
|
+
given("a user with balance '500' dollars", (ctx) => {
|
|
163
|
+
account.balance = ctx.step.values[0]; // 500
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// ✅ Named parameters for clarity
|
|
167
|
+
given("a user with <balance:500> dollars", (ctx) => {
|
|
168
|
+
account.balance = ctx.step.params.balance; // 500
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// ❌ BAD: Value drift — title says 500, code uses 200
|
|
172
|
+
given("a user with balance '500' dollars", (ctx) => {
|
|
173
|
+
account.balance = 200;
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Value Extraction Quick Reference
|
|
178
|
+
|
|
179
|
+
| Syntax in Title | Step Access | Rule Access |
|
|
180
|
+
| --- | --- | --- |
|
|
181
|
+
| `'value'` (quoted) | `ctx.step.values[0]` | `ctx.rule.values[0]` |
|
|
182
|
+
| `<name:value>` (named) | `ctx.step.params.name` | `ctx.rule.params.name` |
|
|
183
|
+
| `<Placeholder>` (outline) | `ctx.example.Placeholder` | `ctx.example.Placeholder` |
|
|
184
|
+
|
|
185
|
+
### Descriptions and Tags
|
|
186
|
+
|
|
187
|
+
Lines after the first line in titles provide descriptions and tags:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
feature(`Shopping Cart
|
|
191
|
+
@checkout @critical
|
|
192
|
+
Business rules for the shopping cart checkout flow.
|
|
193
|
+
`, () => { ... });
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
- **First line** = title
|
|
197
|
+
- **Lines starting with `@`** = tags (used for filtering)
|
|
198
|
+
- **Remaining lines** = description (appears in reports)
|
|
199
|
+
|
|
200
|
+
### Async Rules
|
|
201
|
+
|
|
202
|
+
- **Only step callbacks, `rule`, and `ruleOutline` support `async`**
|
|
203
|
+
- `feature`, `scenario`, `scenarioOutline`, `specification`, `background` must be **synchronous**
|
|
204
|
+
|
|
205
|
+
### Modifiers
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
feature.only("...", fn); feature.skip("...", fn);
|
|
209
|
+
scenario.only("...", fn); scenario.skip("...", fn);
|
|
210
|
+
rule.only("...", fn); rule.skip("...", fn);
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Build and Test
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
pnpm --filter @swedevtools/livedoc-vitest test # Run all specs
|
|
217
|
+
pnpm --filter @swedevtools/livedoc-vitest test MyFeature.Spec.ts
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Routing Examples
|
|
223
|
+
|
|
224
|
+
### Positive (USE this skill)
|
|
225
|
+
- "Create a BDD test for shipping costs" → Read `resources/bdd-features.md`, write feature/scenario
|
|
226
|
+
- "Add data-driven tests for tax" → Read `resources/bdd-features.md`, use scenarioOutline
|
|
227
|
+
- "Write spec tests for email validator" → Read `resources/specifications.md`, write specification/rule
|
|
228
|
+
- "Write a Playwright test for the login page" → Read `resources/playwright.md`, use useBrowser
|
|
229
|
+
- "Configure LiveDoc reporter output" → Read `resources/reporter-config.md`
|
|
230
|
+
- "Generate static HTML test report" → Read `resources/reporter-config.md`
|
|
231
|
+
|
|
232
|
+
### Negative (DO NOT use this skill)
|
|
233
|
+
- "Create a C# test for shipping" → Use `livedoc-xunit` skill
|
|
234
|
+
- "Build a React component" → Use `frontend-design` skill
|
|
235
|
+
- "Write a plain vitest test" → No LiveDoc skill needed
|
|
236
|
+
- "Install AI skills for the team" → Run `npx livedoc-vitest-setup`
|
|
237
|
+
|
|
238
|
+
## Failure Handling
|
|
239
|
+
- Tests fail to compile → check imports, especially `Then as then` alias
|
|
240
|
+
- Values are `undefined` → verify single quotes `'value'` not backticks or double quotes
|
|
241
|
+
- `ctx.example` undefined → ensure inside `scenarioOutline`/`ruleOutline`, not plain `scenario`/`rule`
|
|
242
|
+
- Async hangs → ensure `async` only on step/rule callbacks, not on `feature`/`scenario`
|
|
243
|
+
- Playwright `page()` throws → `useBrowser()` must be at module scope; `page()` called inside steps
|
|
244
|
+
- Reporter issues → Read `resources/reporter-config.md`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Validation Report — livedoc-vitest
|
|
2
|
+
|
|
3
|
+
## Result: PASS
|
|
4
|
+
|
|
5
|
+
## Checks
|
|
6
|
+
|
|
7
|
+
| Check | Status |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Frontmatter `name` present | ✅ |
|
|
10
|
+
| Frontmatter `description` present | ✅ |
|
|
11
|
+
| Description ≤ 100 words | ✅ (30 words) |
|
|
12
|
+
| Body ≤ 500 lines | ✅ (321 lines) |
|
|
13
|
+
| `## Use this skill when` | ✅ |
|
|
14
|
+
| `## Do not use this skill when` | ✅ |
|
|
15
|
+
| `## Inputs` | ✅ |
|
|
16
|
+
| `## Outputs` | ✅ |
|
|
17
|
+
| `## Workflow` | ✅ |
|
|
18
|
+
| `## Validation` | ✅ |
|
|
19
|
+
| `## Examples` | ✅ |
|
|
20
|
+
| `### Positive routing examples` | ✅ |
|
|
21
|
+
| `### Negative routing examples` | ✅ |
|
|
22
|
+
| `## Failure handling` | ✅ |
|
|
23
|
+
| Routing examples file (`examples/routing.md`) | ✅ |
|
|
24
|
+
|
|
25
|
+
## Assumptions
|
|
26
|
+
- Tests are written in TypeScript and use Vitest as the test runner
|
|
27
|
+
- The `@swedevtools/livedoc-vitest` package is available in the monorepo via `workspace:*`
|
|
28
|
+
- Globals mode may or may not be enabled; skill covers both import and globals patterns
|
|
29
|
+
- The existing `.github/instructions/livedoc-vitest.instructions.md` remains the file-pattern instruction; this skill provides broader AI-agent guidance
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# LiveDoc Vitest Skill — Routing Examples
|
|
2
|
+
|
|
3
|
+
## Positive routing (USE this skill)
|
|
4
|
+
|
|
5
|
+
### Example 1: Create a new BDD feature spec
|
|
6
|
+
> "Create a test for the shopping cart checkout flow"
|
|
7
|
+
|
|
8
|
+
→ This involves writing a `.Spec.ts` file using `feature`, `scenario`, `given`/`when`/`then` from `@swedevtools/livedoc-vitest`.
|
|
9
|
+
|
|
10
|
+
### Example 2: Add a scenario outline with examples
|
|
11
|
+
> "Add data-driven tests for email validation"
|
|
12
|
+
|
|
13
|
+
→ This involves using `scenarioOutline` or `ruleOutline` with an Examples table and `ctx.example`.
|
|
14
|
+
|
|
15
|
+
### Example 3: Fix value extraction in a step
|
|
16
|
+
> "The step says '500' but the test uses 200 — fix the value drift"
|
|
17
|
+
|
|
18
|
+
→ This involves replacing hardcoded values with `ctx.step.values[0]` or `ctx.step.params`.
|
|
19
|
+
|
|
20
|
+
### Example 4: Convert a plain vitest test to LiveDoc specification pattern
|
|
21
|
+
> "Rewrite these unit tests as a LiveDoc specification with rules"
|
|
22
|
+
|
|
23
|
+
→ This involves using `specification` and `rule`/`ruleOutline` from `@swedevtools/livedoc-vitest`.
|
|
24
|
+
|
|
25
|
+
### Example 5: Modify an existing spec file
|
|
26
|
+
> "Add a new scenario to UserAuth.Spec.ts for password reset"
|
|
27
|
+
|
|
28
|
+
→ This involves editing an existing `.Spec.ts` file using the correct LiveDoc patterns.
|
|
29
|
+
|
|
30
|
+
### Example 6: Write a browser test with Playwright
|
|
31
|
+
> "Write a Playwright test that checks the viewer homepage loads correctly"
|
|
32
|
+
|
|
33
|
+
→ This involves using `useBrowser` and `screenshot` from `@swedevtools/livedoc-vitest/playwright` in a `.Spec.ts` file with BDD patterns.
|
|
34
|
+
|
|
35
|
+
## Negative routing (DO NOT use this skill)
|
|
36
|
+
|
|
37
|
+
### Example 1: Writing a C# xUnit test
|
|
38
|
+
> "Create a test for the shipping calculator in C#"
|
|
39
|
+
|
|
40
|
+
→ Use the `livedoc-xunit` skill instead. This skill is TypeScript-only.
|
|
41
|
+
|
|
42
|
+
### Example 2: Building UI components
|
|
43
|
+
> "Create a React component for the test results viewer"
|
|
44
|
+
|
|
45
|
+
→ This is UI work, not test authoring. Use the `frontend-design` skill instead.
|
|
46
|
+
|
|
47
|
+
### Example 3: Plain vitest without LiveDoc
|
|
48
|
+
> "Write a vitest test for this utility function using describe/it"
|
|
49
|
+
|
|
50
|
+
→ This skill is for LiveDoc BDD/Specification patterns. Plain vitest tests don't need it.
|
|
51
|
+
|
|
52
|
+
### Example 4: Fixing build or config issues
|
|
53
|
+
> "The vitest config won't load, fix it"
|
|
54
|
+
|
|
55
|
+
→ This is build infrastructure, not test authoring. Handle directly without this skill.
|
|
56
|
+
|
|
57
|
+
### Example 5: Installing AI skills or generating static reports
|
|
58
|
+
> "Install the LiveDoc AI skill for my team" or "Generate a static HTML report"
|
|
59
|
+
|
|
60
|
+
→ These are setup/ops tasks. Run `npx livedoc-vitest-setup` for skills or `npx livedoc-viewer export -i results.json` for reports. Not test authoring.
|