@sun-asterisk/sungen 3.1.0 → 3.1.2-beta.93
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/dist/cli/commands/challenge.d.ts.map +1 -1
- package/dist/cli/commands/challenge.js +9 -2
- package/dist/cli/commands/challenge.js.map +1 -1
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +3 -2
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +8 -0
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/exporters/csv-exporter.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.js +92 -76
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/spec-parser.d.ts.map +1 -1
- package/dist/exporters/spec-parser.js +6 -1
- package/dist/exporters/spec-parser.js.map +1 -1
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +1 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/scenario.hbs +19 -1
- package/dist/generators/test-generator/code-generator.d.ts +16 -1
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +133 -49
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/patterns/database-patterns.d.ts +2 -1
- package/dist/generators/test-generator/patterns/database-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/database-patterns.js +2 -1
- package/dist/generators/test-generator/patterns/database-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/expect-patterns.d.ts +3 -0
- package/dist/generators/test-generator/patterns/expect-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/expect-patterns.js +54 -0
- package/dist/generators/test-generator/patterns/expect-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +2 -0
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts +6 -0
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +8 -0
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/generators/test-generator/template-engine.d.ts +3 -0
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
- package/dist/generators/test-generator/template-engine.js.map +1 -1
- package/dist/generators/test-generator/utils/runtime-data-transformer.d.ts +1 -1
- package/dist/generators/test-generator/utils/runtime-data-transformer.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/runtime-data-transformer.js +5 -5
- package/dist/generators/test-generator/utils/runtime-data-transformer.js.map +1 -1
- package/dist/harness/challenge.d.ts +1 -0
- package/dist/harness/challenge.d.ts.map +1 -1
- package/dist/harness/challenge.js +49 -2
- package/dist/harness/challenge.js.map +1 -1
- package/dist/harness/data-driven-lint.d.ts +7 -0
- package/dist/harness/data-driven-lint.d.ts.map +1 -0
- package/dist/harness/data-driven-lint.js +153 -0
- package/dist/harness/data-driven-lint.js.map +1 -0
- package/dist/harness/parse.d.ts +2 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +16 -0
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/query-catalog.d.ts +48 -0
- package/dist/harness/query-catalog.d.ts.map +1 -0
- package/dist/harness/query-catalog.js +0 -0
- package/dist/harness/query-catalog.js.map +1 -0
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +7 -4
- package/dist/harness/script-check.js.map +1 -1
- package/dist/orchestrator/templates/ai-instructions/claude-agent-challenge.md +3 -2
- package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +40 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +19 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +1 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-test-design-techniques.md +6 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +40 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +19 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +1 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-test-design-techniques.md +6 -0
- package/dist/orchestrator/templates/specs-db.d.ts +8 -0
- package/dist/orchestrator/templates/specs-db.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-db.js +22 -0
- package/dist/orchestrator/templates/specs-db.js.map +1 -1
- package/dist/orchestrator/templates/specs-db.ts +22 -0
- package/dist/orchestrator/templates/specs-test-data.ts +76 -15
- package/package.json +2 -2
- package/src/cli/commands/challenge.ts +6 -2
- package/src/cli/commands/delivery.ts +3 -2
- package/src/cli/commands/generate.ts +8 -0
- package/src/exporters/csv-exporter.ts +22 -6
- package/src/exporters/spec-parser.ts +6 -1
- package/src/generators/test-generator/adapters/adapter-interface.ts +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/scenario.hbs +19 -1
- package/src/generators/test-generator/code-generator.ts +128 -50
- package/src/generators/test-generator/patterns/database-patterns.ts +2 -1
- package/src/generators/test-generator/patterns/expect-patterns.ts +49 -0
- package/src/generators/test-generator/patterns/index.ts +2 -0
- package/src/generators/test-generator/step-mapper.ts +9 -0
- package/src/generators/test-generator/template-engine.ts +3 -0
- package/src/generators/test-generator/utils/runtime-data-transformer.ts +5 -5
- package/src/harness/challenge.ts +47 -2
- package/src/harness/data-driven-lint.ts +119 -0
- package/src/harness/parse.ts +12 -0
- package/src/harness/query-catalog.ts +0 -0
- package/src/harness/script-check.ts +8 -5
- package/src/orchestrator/templates/ai-instructions/claude-agent-challenge.md +3 -2
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +40 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +19 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +1 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-test-design-techniques.md +6 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +40 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +19 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +1 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-test-design-techniques.md +6 -0
- package/src/orchestrator/templates/specs-db.ts +22 -0
- package/src/orchestrator/templates/specs-test-data.ts +76 -15
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-catalog.js","sourceRoot":"","sources":["../../src/harness/query-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-check.d.ts","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,CAgBtF;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC;;;cAEpD,MAAM;cAAQ,MAAM;;EAqBhD;AA0CD,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"script-check.d.ts","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,CAgBtF;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC;;;cAEpD,MAAM;cAAQ,MAAM;;EAqBhD;AA0CD,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkGzH"}
|
|
@@ -175,10 +175,13 @@ async function runScriptCheck(screenDir, screenName, flowMode) {
|
|
|
175
175
|
findings.push('No generated spec found under specs/generated/ — run `sungen generate` / `/sungen:run-test` first.');
|
|
176
176
|
}
|
|
177
177
|
// A. Structural 1:1
|
|
178
|
+
// A @cases scenario emits ONE source test() inside a per-row loop, titled
|
|
179
|
+
// `<name> — ${__row.__label}` — match that literal title, not the bare name.
|
|
180
|
+
const expectedTitle = (s) => (s.casesDataset ? `${s.name} — ${'${'}__row.__label}` : s.name);
|
|
178
181
|
const specTitleSet = new Set(specTitles);
|
|
179
|
-
const
|
|
180
|
-
const missingInSpec = automated.filter((s) => !specTitleSet.has(s
|
|
181
|
-
const extraInSpec = specTitles.filter((t) => !
|
|
182
|
+
const expectedSet = new Set(automated.map(expectedTitle));
|
|
183
|
+
const missingInSpec = automated.filter((s) => !specTitleSet.has(expectedTitle(s))).map((s) => s.name);
|
|
184
|
+
const extraInSpec = specTitles.filter((t) => !expectedSet.has(t));
|
|
182
185
|
const countMatch = committedSpec ? automated.length === specTitles.length : false;
|
|
183
186
|
if (committedSpec && !countMatch) {
|
|
184
187
|
findings.push(`Count mismatch: ${automated.length} automated scenarios vs ${specTitles.length} test() blocks.`);
|
|
@@ -223,7 +226,7 @@ async function runScriptCheck(screenDir, screenName, flowMode) {
|
|
|
223
226
|
}
|
|
224
227
|
// C. Anti-bypass / faithfulness
|
|
225
228
|
const { assertionlessTests, hollowSteps } = committedSpec
|
|
226
|
-
? analyzeFaithfulness(specSrc,
|
|
229
|
+
? analyzeFaithfulness(specSrc, expectedSet)
|
|
227
230
|
: { assertionlessTests: [], hollowSteps: [] };
|
|
228
231
|
for (const t of assertionlessTests) {
|
|
229
232
|
findings.push(`BYPASS: test "${t}" has 0 assertions (action-only — proves nothing). The testcase is not really automated.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-check.js","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,8CAgBC;AASD,kDAuBC;AA0CD,
|
|
1
|
+
{"version":3,"file":"script-check.js","sourceRoot":"","sources":["../../src/harness/script-check.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,8CAgBC;AASD,kDAuBC;AA0CD,wCAkGC;AAnOD;;;;;;;;;;;;;GAaG;AACH,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AACzB,mCAAsD;AAqBtD,yEAAyE;AACzE,SAAgB,iBAAiB,CAAC,OAAe;IAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,MAAM,GAAwC,EAAE,CAAC;IACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACpF,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,KAAK,GAAG,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;QAC/B,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBAAC,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;oBAAC,KAAK,EAAE,CAAC;oBAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,CAAC;qBAAM,IAAI,EAAE,KAAK,GAAG;oBAAE,KAAK,EAAE,CAAC;YAAC,CAAC;YACzG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,OAAO,IAAI,KAAK,IAAI,CAAC;gBAAE,MAAM;QACnC,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,SAAS,GAAG,6CAA6C,CAAC;AAEhE;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,OAAe,EAAE,eAA4B;IAC/E,MAAM,kBAAkB,GAAa,EAAE,CAAC;IACxC,MAAM,WAAW,GAAqC,EAAE,CAAC;IACzD,KAAK,MAAM,GAAG,IAAI,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS,CAAC,6BAA6B;QAC5E,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACtB,2EAA2E;QAC3E,mFAAmF;QACnF,mDAAmD;QACnD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnG,kFAAkF;QAClF,iFAAiF;QACjF,iFAAiF;QACjF,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3F,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YAClE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,OAAO;gBAAE,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;IACD,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,CAAC;AAC7C,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe;IACxC,sEAAsE;IACtE,mEAAmE;IACnE,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,EAAE,GAAG,0DAA0D,CAAC;IACtE,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG;SACP,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;SACjC,IAAI,CAAC,IAAI,CAAC;SACV,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC;SAC1B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,IAAY,EAAE,QAAiB;IAC5D,qDAAqD;IACrD,2DAA2D;IAC3D,6EAA6E;IAC7E,4EAA4E;IAC5E,6CAA6C;IAC7C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;QACzB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO;QAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,IAAI,CAAC,CAAC,CAAC,CAAC;iBACxB,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC/E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,kDAAkD;IAC3F,IAAI,CAAC,MAAM,CAAC,CAAC;IACb,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACzB,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,SAAiB,EAAE,UAAkB,EAAE,QAAiB;IAC3F,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,UAAU,UAAU,CAAC,CAAC;IAC9E,MAAM,SAAS,GAAG,IAAA,qBAAa,EAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAEjD,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAErG,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,UAAU,GAAa,EAAE,CAAC;IAC9B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAClD,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,oGAAoG,CAAC,CAAC;IACtH,CAAC;IAED,oBAAoB;IACpB,0EAA0E;IAC1E,6EAA6E;IAC7E,MAAM,aAAa,GAAG,CAAC,CAAe,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3G,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtG,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAClF,IAAI,aAAa,IAAI,CAAC,UAAU,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,SAAS,CAAC,MAAM,2BAA2B,UAAU,CAAC,MAAM,iBAAiB,CAAC,CAAC;IAClH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,aAAa;QAAE,QAAQ,CAAC,IAAI,CAAC,8BAA8B,CAAC,kDAAkD,CAAC,CAAC;IAChI,KAAK,MAAM,CAAC,IAAI,WAAW;QAAE,QAAQ,CAAC,IAAI,CAAC,wBAAwB,CAAC,gDAAgD,CAAC,CAAC;IAEtH,yCAAyC;IACzC,IAAI,KAAK,GAA+B,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,6CAA6C,CAAC,CAAC;YACjF,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;YAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACnF,MAAM,GAAG,GAAG,IAAI,aAAa,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpG,MAAM,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;YAC5D,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YAClD,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;gBAC7B,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;gBACrD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACZ,KAAK,GAAG,OAAO,CAAC;oBAChB,gCAAgC;oBAChC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;oBAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;wBACrD,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;4BACpB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;4BAC7I,KAAK,EAAE,CAAC;wBACV,CAAC;oBACH,CAAC;oBACD,QAAQ,CAAC,IAAI,CAAC,+KAA+K,CAAC,CAAC;gBACjM,CAAC;YACH,CAAC;YACD,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,4CAA4C,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,MAAM,EAAE,kBAAkB,EAAE,WAAW,EAAE,GAAG,aAAa;QACvD,CAAC,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC;QAC3C,CAAC,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,kBAAkB,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,0FAA0F,CAAC,CAAC;IAC9H,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,IAAI,iEAAiE,CAAC,CAAC;IAC1H,CAAC;IACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAEvE,MAAM,EAAE,GAAG,CAAC,CAAC,aAAa,IAAI,UAAU,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC;IAErI,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,aAAa;QACvB,kBAAkB,EAAE,SAAS,CAAC,MAAM;QACpC,eAAe,EAAE,MAAM,CAAC,MAAM;QAC9B,cAAc,EAAE,UAAU,CAAC,MAAM;QACjC,UAAU;QACV,aAAa;QACb,WAAW;QACX,KAAK;QACL,UAAU;QACV,kBAAkB;QAClB,WAAW;QACX,MAAM;QACN,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;QAC1B,QAAQ;KACT,CAAC;AACJ,CAAC"}
|
|
@@ -15,11 +15,12 @@ Run `sungen challenge --screen <name>` (Bash) and read its report (`.sungen/repo
|
|
|
15
15
|
- `.sungen/reports/<name>-audit.json` — what the gate already measured.
|
|
16
16
|
- Blind-spot patterns — run `sungen blindspot list --prompt` (Bash) and check the suite against each known pattern.
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Four critics
|
|
19
19
|
|
|
20
20
|
1. **Coverage critic** — viewpoints that are missing or covered only shallowly; areas over-covered with low value (e.g. many subscription edge cases while cart correctness is thin). Recommend rebalancing, not just adding.
|
|
21
21
|
2. **Business-Depth critic** — scenarios whose **title claims more than the steps prove** (a set/collection asserted by one element; "correct X" asserted by mere visibility). For each, give the exact deep step to add. Confirm or dismiss the deterministic flags from `sungen challenge`.
|
|
22
|
-
3. **
|
|
22
|
+
3. **Data-driven critic** — surface `@cases`-worthy gaps, *spec-independent*: (a) **confirm the deterministic collapse suggestions** (`sungen challenge` flags ≥2 scenarios with the same step skeleton → propose the one `@cases:<dataset>` with the rows + a `case` label each); (b) for any action reaching a backend/logic (login, search, create, an API/error path), propose the **corner/error matrix** as `@cases` rows — *invalid · empty · boundary · injection · duplicate · not-found · unauthorized · malformed · rate-limit* — picking the family that fits the screen. These are the cases a spec/viewpoint usually under-specifies.
|
|
23
|
+
4. **Novelty critic** — 3–5 **non-obvious, valuable** scenarios outside the existing pattern, via risk lenses (double-submit, partial-load, boundary/unusual data, concurrency/back-button, historical incidents). Each must map to a risk or viewpoint and explain why it isn't a duplicate.
|
|
23
24
|
|
|
24
25
|
## Guardrails (hard)
|
|
25
26
|
- **Read-only.** Never edit the feature or any file. You return findings; the QA/orchestrator decides.
|
|
@@ -102,6 +102,22 @@ User see [Table] table match data:
|
|
|
102
102
|
|
|
103
103
|
Row scope: `see [Ref] row in [Table] table with {{v}}` enters scope. Subsequent `see [Col] column with {{v}}` checks cell in that row. Use `table match data:` for multi-row verification.
|
|
104
104
|
|
|
105
|
+
### Database verification (optional Data Driver)
|
|
106
|
+
|
|
107
|
+
Read-only DB-state checks. **Prefer named queries** — SQL lives in `qa/screens/<screen>/database/queries.yaml` (reviewed once, parameterized). Invoke with the `@query:<name>` annotation; it binds the result rows to `{{name}}`, then assert with `expect`:
|
|
108
|
+
|
|
109
|
+
```gherkin
|
|
110
|
+
@query:active_user # precondition: run query, bind {{active_user}}
|
|
111
|
+
@query:orders(buyer={{email}}) # …with explicit param override
|
|
112
|
+
Scenario: ...
|
|
113
|
+
Then expect {{active_user.count}} is at least {{one}} # ≥1 row
|
|
114
|
+
And expect {{active_user.first.status}} is "active" # first row's column
|
|
115
|
+
And expect {{orders.count}} is {{expected}} # exact count
|
|
116
|
+
And User see [Total] text is {{orders.first.total}} # UI ↔ DB
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Path access on a bound result: `{{q.count}}`/`{{q.length}}`, `{{q.first.col}}`, `{{q.last.col}}`, `{{q[2].col}}`, `{{q.col}}` (= first row's col). `expect A is B` also supports `is at least` / `is at most` / `is not`. Tier-2 declarative (trivial inline, no catalog): `User see [<table>] row where [<col>] is {{v}} [has [<col2>] = "x"]`, `… no row where …`, `… count is {{n}}`. Full grammar + catalog/datasource/secret rules → **Advanced → Database** doc. Only emit DB steps when the project has a `database/` catalog / `datasources.yaml`.
|
|
120
|
+
|
|
105
121
|
### States
|
|
106
122
|
|
|
107
123
|
`hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty` `loading` `selected` `sorted ascending` `sorted descending`
|
|
@@ -195,6 +211,30 @@ Options: `nth` `exact` `scope` `match` `variant` `frame` `contenteditable` `colu
|
|
|
195
211
|
| `@afterEach` | Hook: runs after each test → `test.afterEach()` (custom cleanup) |
|
|
196
212
|
| `@afterAll` | Hook: runs once after all tests → `test.afterAll()` |
|
|
197
213
|
| `@flow` | Mark feature as E2E flow (cross-screen testing) |
|
|
214
|
+
| `@cases:dataset` | Data-driven: run the scenario once per row of the `dataset` LIST in test-data → one `test()` per row |
|
|
215
|
+
| `@query:name` | Database: run the named query from `database/queries.yaml` (precondition) and bind its rows to `{{name}}`; assert with `expect {{name.count}} …` + path access. Override params `@query:name(p={{v}})`. Repeatable. (Optional Data Driver — see Database verification above) |
|
|
216
|
+
|
|
217
|
+
### Data-driven scenarios (`@cases`)
|
|
218
|
+
|
|
219
|
+
For one test case × many inputs (email/format/boundary validation, decision tables), tag the
|
|
220
|
+
scenario `@cases:<dataset>` and reference each row's columns as `{{col}}`. Put the rows as a LIST
|
|
221
|
+
in test-data — NOT inline; data stays runtime + env-overlayable.
|
|
222
|
+
|
|
223
|
+
```gherkin
|
|
224
|
+
@high @cases:email_validation
|
|
225
|
+
Scenario: VP-VAL-001 The email field rejects invalid formats
|
|
226
|
+
When User fill [Email] field with {{email}}
|
|
227
|
+
Then User see [Login Error] message with {{expected_error}}
|
|
228
|
+
```
|
|
229
|
+
```yaml
|
|
230
|
+
# test-data/<screen>.yaml
|
|
231
|
+
email_validation:
|
|
232
|
+
- { case: "no @", email: "plainaddress", expected_error: "Invalid email" }
|
|
233
|
+
- { case: "valid", email: "ok@x.com", expected_error: "" }
|
|
234
|
+
```
|
|
235
|
+
An optional `case`/`name`/`label` column labels each run. Each row → its own pass/fail. Prefer
|
|
236
|
+
`@cases` over duplicating a scenario per value. (Gherkin `Scenario Outline`/`Examples` is NOT
|
|
237
|
+
supported — use `@cases`.)
|
|
198
238
|
|
|
199
239
|
### Pass-through tags (filter at runtime via Playwright --grep)
|
|
200
240
|
|
|
@@ -54,6 +54,25 @@ user-invocable: false
|
|
|
54
54
|
OR condition: generate 1 scenario per branch where that branch alone triggers the outcome.
|
|
55
55
|
→ Happy-path only = missing the most common multi-condition implementation bug.
|
|
56
56
|
|
|
57
|
+
- **Many inputs, same steps → ONE data-driven scenario (`@cases`), not N copies:**
|
|
58
|
+
When a rule needs lots of inputs with the *same* step shape (email/format validation,
|
|
59
|
+
BVA boundary triples, EP classes, decision-table rows), tag one scenario `@cases:<dataset>`,
|
|
60
|
+
reference each row's columns as `{{col}}`, and put the rows as a LIST in test-data:
|
|
61
|
+
```gherkin
|
|
62
|
+
@high @cases:email_validation
|
|
63
|
+
Scenario: VP-VAL-001 The email field rejects invalid formats
|
|
64
|
+
When User fill [Email] field with {{email}}
|
|
65
|
+
Then User see [Error] message with {{expected_error}}
|
|
66
|
+
```
|
|
67
|
+
```yaml
|
|
68
|
+
email_validation:
|
|
69
|
+
- { case: "no @", email: "plainaddress", expected_error: "Invalid email" }
|
|
70
|
+
- { case: "valid", email: "ok@x.com", expected_error: "" }
|
|
71
|
+
```
|
|
72
|
+
→ one `test()` per row, each labelled by `case`. Adding inputs = editing test-data (no recompile),
|
|
73
|
+
and env overlays apply. Prefer this over duplicating a scenario per value. (Gherkin
|
|
74
|
+
`Scenario Outline`/`Examples` is NOT supported — use `@cases`.)
|
|
75
|
+
|
|
57
76
|
---
|
|
58
77
|
|
|
59
78
|
## Tier System
|
|
@@ -120,6 +120,7 @@ Build a mapping table: for each applicable group, does the feature have a matchi
|
|
|
120
120
|
- **EP**: keep only **one representative** per invalid class; same-class duplicates → flag as redundant.
|
|
121
121
|
- **BVA**: spec defines min/max → cover `min-1`, `min`, `max`, `max+1` (Maxlength, counts…).
|
|
122
122
|
- Error messages must match the spec **word-for-word**, not generic.
|
|
123
|
+
- **Data-driven (`@cases`)**: a `@cases:<dataset>` scenario legitimately covers many inputs in ONE scenario (one row per EP class / boundary / rule). Do **not** flag it as "too few negative cases" or as duplication — instead review the **dataset rows**: are all EP classes / boundary triples present, each labelled, expected values exact? N near-identical scenarios that differ only by input value → flag and recommend collapsing to `@cases`.
|
|
123
124
|
|
|
124
125
|
---
|
|
125
126
|
|
|
@@ -17,6 +17,12 @@ Apply selectively — not every screen needs all four techniques. Use the techni
|
|
|
17
17
|
|
|
18
18
|
**Rule:** These techniques determine **how many** and **which** scenarios to generate. `sungen-viewpoint` determines **which viewpoints** to cover.
|
|
19
19
|
|
|
20
|
+
**Implementing the data table → `@cases` (data-driven):** when EP classes / BVA boundary triples /
|
|
21
|
+
decision-table rows share the *same step shape* and differ only by input/expected values, encode
|
|
22
|
+
them as ONE `@cases:<dataset>` scenario (each class/boundary/rule = one row in the test-data list,
|
|
23
|
+
labelled by a `case` column) instead of N near-duplicate scenarios. The technique still decides the
|
|
24
|
+
rows; `@cases` is how you write them compactly. See `sungen-gherkin-syntax` → Data-driven.
|
|
25
|
+
|
|
20
26
|
---
|
|
21
27
|
|
|
22
28
|
## 1. Equivalence Partitioning (EP)
|
|
@@ -102,6 +102,22 @@ User see [Table] table match data:
|
|
|
102
102
|
|
|
103
103
|
Row scope: `see [Ref] row in [Table] table with {{v}}` enters scope. Subsequent `see [Col] column with {{v}}` checks cell in that row. Use `table match data:` for multi-row verification.
|
|
104
104
|
|
|
105
|
+
### Database verification (optional Data Driver)
|
|
106
|
+
|
|
107
|
+
Read-only DB-state checks. **Prefer named queries** — SQL lives in `qa/screens/<screen>/database/queries.yaml` (reviewed once, parameterized). Invoke with the `@query:<name>` annotation; it binds the result rows to `{{name}}`, then assert with `expect`:
|
|
108
|
+
|
|
109
|
+
```gherkin
|
|
110
|
+
@query:active_user # precondition: run query, bind {{active_user}}
|
|
111
|
+
@query:orders(buyer={{email}}) # …with explicit param override
|
|
112
|
+
Scenario: ...
|
|
113
|
+
Then expect {{active_user.count}} is at least {{one}} # ≥1 row
|
|
114
|
+
And expect {{active_user.first.status}} is "active" # first row's column
|
|
115
|
+
And expect {{orders.count}} is {{expected}} # exact count
|
|
116
|
+
And User see [Total] text is {{orders.first.total}} # UI ↔ DB
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Path access on a bound result: `{{q.count}}`/`{{q.length}}`, `{{q.first.col}}`, `{{q.last.col}}`, `{{q[2].col}}`, `{{q.col}}` (= first row's col). `expect A is B` also supports `is at least` / `is at most` / `is not`. Tier-2 declarative (trivial inline, no catalog): `User see [<table>] row where [<col>] is {{v}} [has [<col2>] = "x"]`, `… no row where …`, `… count is {{n}}`. Full grammar + catalog/datasource/secret rules → **Advanced → Database** doc. Only emit DB steps when the project has a `database/` catalog / `datasources.yaml`.
|
|
120
|
+
|
|
105
121
|
### States
|
|
106
122
|
|
|
107
123
|
`hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty` `loading` `selected` `sorted ascending` `sorted descending`
|
|
@@ -195,6 +211,30 @@ Options: `nth` `exact` `scope` `match` `variant` `frame` `contenteditable` `colu
|
|
|
195
211
|
| `@afterEach` | Hook: runs after each test → `test.afterEach()` (custom cleanup) |
|
|
196
212
|
| `@afterAll` | Hook: runs once after all tests → `test.afterAll()` |
|
|
197
213
|
| `@flow` | Mark feature as E2E flow (cross-screen testing) |
|
|
214
|
+
| `@cases:dataset` | Data-driven: run the scenario once per row of the `dataset` LIST in test-data → one `test()` per row |
|
|
215
|
+
| `@query:name` | Database: run the named query from `database/queries.yaml` (precondition) and bind its rows to `{{name}}`; assert with `expect {{name.count}} …` + path access. Override params `@query:name(p={{v}})`. Repeatable. (Optional Data Driver — see Database verification above) |
|
|
216
|
+
|
|
217
|
+
### Data-driven scenarios (`@cases`)
|
|
218
|
+
|
|
219
|
+
For one test case × many inputs (email/format/boundary validation, decision tables), tag the
|
|
220
|
+
scenario `@cases:<dataset>` and reference each row's columns as `{{col}}`. Put the rows as a LIST
|
|
221
|
+
in test-data — NOT inline; data stays runtime + env-overlayable.
|
|
222
|
+
|
|
223
|
+
```gherkin
|
|
224
|
+
@high @cases:email_validation
|
|
225
|
+
Scenario: VP-VAL-001 The email field rejects invalid formats
|
|
226
|
+
When User fill [Email] field with {{email}}
|
|
227
|
+
Then User see [Login Error] message with {{expected_error}}
|
|
228
|
+
```
|
|
229
|
+
```yaml
|
|
230
|
+
# test-data/<screen>.yaml
|
|
231
|
+
email_validation:
|
|
232
|
+
- { case: "no @", email: "plainaddress", expected_error: "Invalid email" }
|
|
233
|
+
- { case: "valid", email: "ok@x.com", expected_error: "" }
|
|
234
|
+
```
|
|
235
|
+
An optional `case`/`name`/`label` column labels each run. Each row → its own pass/fail. Prefer
|
|
236
|
+
`@cases` over duplicating a scenario per value. (Gherkin `Scenario Outline`/`Examples` is NOT
|
|
237
|
+
supported — use `@cases`.)
|
|
198
238
|
|
|
199
239
|
### Pass-through tags (filter at runtime via Playwright --grep)
|
|
200
240
|
|
|
@@ -54,6 +54,25 @@ user-invocable: false
|
|
|
54
54
|
OR condition: generate 1 scenario per branch where that branch alone triggers the outcome.
|
|
55
55
|
→ Happy-path only = missing the most common multi-condition implementation bug.
|
|
56
56
|
|
|
57
|
+
- **Many inputs, same steps → ONE data-driven scenario (`@cases`), not N copies:**
|
|
58
|
+
When a rule needs lots of inputs with the *same* step shape (email/format validation,
|
|
59
|
+
BVA boundary triples, EP classes, decision-table rows), tag one scenario `@cases:<dataset>`,
|
|
60
|
+
reference each row's columns as `{{col}}`, and put the rows as a LIST in test-data:
|
|
61
|
+
```gherkin
|
|
62
|
+
@high @cases:email_validation
|
|
63
|
+
Scenario: VP-VAL-001 The email field rejects invalid formats
|
|
64
|
+
When User fill [Email] field with {{email}}
|
|
65
|
+
Then User see [Error] message with {{expected_error}}
|
|
66
|
+
```
|
|
67
|
+
```yaml
|
|
68
|
+
email_validation:
|
|
69
|
+
- { case: "no @", email: "plainaddress", expected_error: "Invalid email" }
|
|
70
|
+
- { case: "valid", email: "ok@x.com", expected_error: "" }
|
|
71
|
+
```
|
|
72
|
+
→ one `test()` per row, each labelled by `case`. Adding inputs = editing test-data (no recompile),
|
|
73
|
+
and env overlays apply. Prefer this over duplicating a scenario per value. (Gherkin
|
|
74
|
+
`Scenario Outline`/`Examples` is NOT supported — use `@cases`.)
|
|
75
|
+
|
|
57
76
|
---
|
|
58
77
|
|
|
59
78
|
## Tier System
|
|
@@ -120,6 +120,7 @@ Build a mapping table: for each applicable group, does the feature have a matchi
|
|
|
120
120
|
- **EP**: keep only **one representative** per invalid class; same-class duplicates → flag as redundant.
|
|
121
121
|
- **BVA**: spec defines min/max → cover `min-1`, `min`, `max`, `max+1` (Maxlength, counts…).
|
|
122
122
|
- Error messages must match the spec **word-for-word**, not generic.
|
|
123
|
+
- **Data-driven (`@cases`)**: a `@cases:<dataset>` scenario legitimately covers many inputs in ONE scenario (one row per EP class / boundary / rule). Do **not** flag it as "too few negative cases" or as duplication — instead review the **dataset rows**: are all EP classes / boundary triples present, each labelled, expected values exact? N near-identical scenarios that differ only by input value → flag and recommend collapsing to `@cases`.
|
|
123
124
|
|
|
124
125
|
---
|
|
125
126
|
|
package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-test-design-techniques.md
CHANGED
|
@@ -17,6 +17,12 @@ Apply selectively — not every screen needs all four techniques. Use the techni
|
|
|
17
17
|
|
|
18
18
|
**Rule:** These techniques determine **how many** and **which** scenarios to generate. `sungen-viewpoint` determines **which viewpoints** to cover.
|
|
19
19
|
|
|
20
|
+
**Implementing the data table → `@cases` (data-driven):** when EP classes / BVA boundary triples /
|
|
21
|
+
decision-table rows share the *same step shape* and differ only by input/expected values, encode
|
|
22
|
+
them as ONE `@cases:<dataset>` scenario (each class/boundary/rule = one row in the test-data list,
|
|
23
|
+
labelled by a `case` column) instead of N near-duplicate scenarios. The technique still decides the
|
|
24
|
+
rows; `@cases` is how you write them compactly. See `sungen-gherkin-syntax` → Data-driven.
|
|
25
|
+
|
|
20
26
|
---
|
|
21
27
|
|
|
22
28
|
## 1. Equivalence Partitioning (EP)
|
|
@@ -12,6 +12,14 @@ declare class DataSource {
|
|
|
12
12
|
assertCount(table: string, filter: Record<string, any>, count: number, datasource?: string): Promise<void>;
|
|
13
13
|
/** Rewrites $1/$2 placeholders to `?` for SQLite. */
|
|
14
14
|
private sqlFor;
|
|
15
|
+
/** Read-only guard (second layer): a named query must be a single SELECT/WITH statement. */
|
|
16
|
+
private assertSelectOnly;
|
|
17
|
+
/**
|
|
18
|
+
* Run a catalog query (read-only) and return its rows. The result is bound to a `{{name}}`
|
|
19
|
+
* variable via `testData.bind(...)`, so the scenario asserts on it with `expect …` steps and
|
|
20
|
+
* path access (`{{name.count}}`, `{{name.first.col}}`, `{{name[2].col}}`).
|
|
21
|
+
*/
|
|
22
|
+
fetchQuery(label: string, sql: string, params: any[], datasource?: string): Promise<any[]>;
|
|
15
23
|
}
|
|
16
24
|
export declare const db: DataSource;
|
|
17
25
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specs-db.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-db.ts"],"names":[],"mappings":"AA+DA,cAAM,UAAU;IACd,OAAO,CAAC,OAAO,CAAiD;IAChE,OAAO,CAAC,OAAO,CAA6B;IAE5C,OAAO,CAAC,GAAG;YAQG,MAAM;IAoBpB,OAAO,CAAC,KAAK;IAOb,wGAAwG;IAClG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/H,0CAA0C;IACpC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjG,gDAAgD;IAC1C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhH,qDAAqD;IACrD,OAAO,CAAC,MAAM;
|
|
1
|
+
{"version":3,"file":"specs-db.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-db.ts"],"names":[],"mappings":"AA+DA,cAAM,UAAU;IACd,OAAO,CAAC,OAAO,CAAiD;IAChE,OAAO,CAAC,OAAO,CAA6B;IAE5C,OAAO,CAAC,GAAG;YAQG,MAAM;IAoBpB,OAAO,CAAC,KAAK;IAOb,wGAAwG;IAClG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/H,0CAA0C;IACpC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjG,gDAAgD;IAC1C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhH,qDAAqD;IACrD,OAAO,CAAC,MAAM;IAKd,4FAA4F;IAC5F,OAAO,CAAC,gBAAgB;IASxB;;;;OAIG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;CAKjG;AAMD,eAAO,MAAM,EAAE,YAAmB,CAAC"}
|
|
@@ -163,6 +163,28 @@ class DataSource {
|
|
|
163
163
|
sqlFor(conf, sql) {
|
|
164
164
|
return conf.engine === 'sqlite' ? sql.replace(/\$\d+/g, '?') : sql;
|
|
165
165
|
}
|
|
166
|
+
// --- Named queries (catalog-backed; SQL is resolved + embedded at compile time) -----------
|
|
167
|
+
/** Read-only guard (second layer): a named query must be a single SELECT/WITH statement. */
|
|
168
|
+
assertSelectOnly(label, sql) {
|
|
169
|
+
const s = sql.trim().replace(/;\s*$/, '');
|
|
170
|
+
if (!/^(SELECT|WITH)\b/i.test(s))
|
|
171
|
+
throw new Error(`Data Driver: ${label} is not a read-only SELECT — refused.`);
|
|
172
|
+
if (s.includes(';'))
|
|
173
|
+
throw new Error(`Data Driver: ${label} contains multiple statements — refused.`);
|
|
174
|
+
if (/\b(INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|TRUNCATE|GRANT|REVOKE|MERGE|REPLACE|CALL|EXEC|EXECUTE|ATTACH|PRAGMA|VACUUM)\b/i.test(s)) {
|
|
175
|
+
throw new Error(`Data Driver: ${label} contains a write/DDL keyword — refused.`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Run a catalog query (read-only) and return its rows. The result is bound to a `{{name}}`
|
|
180
|
+
* variable via `testData.bind(...)`, so the scenario asserts on it with `expect …` steps and
|
|
181
|
+
* path access (`{{name.count}}`, `{{name.first.col}}`, `{{name[2].col}}`).
|
|
182
|
+
*/
|
|
183
|
+
async fetchQuery(label, sql, params, datasource) {
|
|
184
|
+
this.assertSelectOnly(label, sql);
|
|
185
|
+
const { engine, conf } = await this.engine(datasource);
|
|
186
|
+
return engine.query(this.sqlFor(conf, sql), params);
|
|
187
|
+
}
|
|
166
188
|
}
|
|
167
189
|
function desc(filter) {
|
|
168
190
|
return Object.entries(filter).map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(', ');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specs-db.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-db.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oBAAoB;AACpB;;;;;;;;;;;GAWG;AACH,2CAA0C;AAC1C,uCAAyB;AACzB,2CAA6B;AAE7B,MAAM,KAAK,GAAG,0BAA0B,CAAC;AACzC,MAAM,KAAK,GAAG,CAAC,CAAS,EAAU,EAAE;IAClC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC;IACjH,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAUF,SAAS,SAAS;IAChB,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,WAAW,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;QAC1E,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1D,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBACrE,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;oBACzC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,UAAU;IACjB,SAAS,EAAE,CAAC;IACZ,MAAM,IAAI,GAAG;QACX,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,kBAAkB,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,kBAAkB,CAAC;KACnD,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IAC5F,IAAI,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,iCAAiC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACnH,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,GAAG,CAAC,WAAW,CAAC;AACzB,CAAC;AAID,MAAM,UAAU;IAAhB;QACU,YAAO,GAA4C,IAAI,CAAC;QACxD,YAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"specs-db.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -138,6 +138,28 @@ class DataSource {
|
|
|
138
138
|
private sqlFor(conf: DataSourceConfig, sql: string): string {
|
|
139
139
|
return conf.engine === 'sqlite' ? sql.replace(/\$\d+/g, '?') : sql;
|
|
140
140
|
}
|
|
141
|
+
|
|
142
|
+
// --- Named queries (catalog-backed; SQL is resolved + embedded at compile time) -----------
|
|
143
|
+
/** Read-only guard (second layer): a named query must be a single SELECT/WITH statement. */
|
|
144
|
+
private assertSelectOnly(label: string, sql: string): void {
|
|
145
|
+
const s = sql.trim().replace(/;\s*$/, '');
|
|
146
|
+
if (!/^(SELECT|WITH)\b/i.test(s)) throw new Error(`Data Driver: ${label} is not a read-only SELECT — refused.`);
|
|
147
|
+
if (s.includes(';')) throw new Error(`Data Driver: ${label} contains multiple statements — refused.`);
|
|
148
|
+
if (/\b(INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|TRUNCATE|GRANT|REVOKE|MERGE|REPLACE|CALL|EXEC|EXECUTE|ATTACH|PRAGMA|VACUUM)\b/i.test(s)) {
|
|
149
|
+
throw new Error(`Data Driver: ${label} contains a write/DDL keyword — refused.`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Run a catalog query (read-only) and return its rows. The result is bound to a `{{name}}`
|
|
155
|
+
* variable via `testData.bind(...)`, so the scenario asserts on it with `expect …` steps and
|
|
156
|
+
* path access (`{{name.count}}`, `{{name.first.col}}`, `{{name[2].col}}`).
|
|
157
|
+
*/
|
|
158
|
+
async fetchQuery(label: string, sql: string, params: any[], datasource?: string): Promise<any[]> {
|
|
159
|
+
this.assertSelectOnly(label, sql);
|
|
160
|
+
const { engine, conf } = await this.engine(datasource);
|
|
161
|
+
return engine.query(this.sqlFor(conf, sql), params);
|
|
162
|
+
}
|
|
141
163
|
}
|
|
142
164
|
|
|
143
165
|
function desc(filter: Record<string, any>): string {
|
|
@@ -5,6 +5,8 @@ import yaml from 'yaml';
|
|
|
5
5
|
|
|
6
6
|
export class TestDataLoader {
|
|
7
7
|
private data: Record<string, any>;
|
|
8
|
+
// Data-driven (@cases): when set (via withRow), get() prefers this row's columns.
|
|
9
|
+
private row?: Record<string, any>;
|
|
8
10
|
|
|
9
11
|
private constructor(data: Record<string, any>) {
|
|
10
12
|
this.data = data;
|
|
@@ -41,23 +43,56 @@ export class TestDataLoader {
|
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
get(key: string): string {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
let current: any = this.data[key];
|
|
47
|
-
if (current === undefined || current === null) {
|
|
48
|
-
// Fall back to nested navigation for YAML-structured keys (e.g. "cart.qty_two").
|
|
49
|
-
current = this.data;
|
|
50
|
-
for (const part of key.split('.')) {
|
|
51
|
-
if (current == null || typeof current !== 'object') {
|
|
52
|
-
throw new Error(`Test data key not found: ${key} (failed at '${part}')`);
|
|
53
|
-
}
|
|
54
|
-
current = current[part];
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (current === undefined || current === null) {
|
|
46
|
+
const value = this.resolve(key);
|
|
47
|
+
if (value === undefined || value === null) {
|
|
58
48
|
throw new Error(`Test data key not found: ${key}`);
|
|
59
49
|
}
|
|
60
|
-
return String(
|
|
50
|
+
return String(value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Resolve a `{{...}}` reference to its raw value. Supports:
|
|
55
|
+
* - flat keys (incl. captured runtime vars stored under a literal dotted key);
|
|
56
|
+
* - `@cases` row columns (the current row wins);
|
|
57
|
+
* - structured paths over nested data AND `@query`-bound result arrays:
|
|
58
|
+
* `q.count` / `q.length` → number of rows
|
|
59
|
+
* `q.first.col` / `q.last.col` / `q[2].col` → a specific row's column
|
|
60
|
+
* `q.col` → shorthand for the first row's column
|
|
61
|
+
*/
|
|
62
|
+
private resolve(key: string): any {
|
|
63
|
+
// 1. Exact flat key — captured vars (set()) live under a literal, possibly dotted, key.
|
|
64
|
+
if (this.row && key in this.row && this.row[key] !== undefined && this.row[key] !== null) {
|
|
65
|
+
return this.row[key];
|
|
66
|
+
}
|
|
67
|
+
if (this.data[key] !== undefined && this.data[key] !== null) {
|
|
68
|
+
return this.data[key];
|
|
69
|
+
}
|
|
70
|
+
// 2. Structured path: head from the row (cases) or shared data, then walk segments.
|
|
71
|
+
const tokens = String(key).replace(/\[(\d+)\]/g, '.$1').split('.');
|
|
72
|
+
let cur: any = (this.row && tokens[0] in this.row) ? this.row[tokens[0]] : this.data[tokens[0]];
|
|
73
|
+
for (let i = 1; i < tokens.length && cur != null; i++) cur = TestDataLoader.step(cur, tokens[i]);
|
|
74
|
+
return cur;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** One navigation step over an array (with count/first/last/index/field-shorthand) or object. */
|
|
78
|
+
private static step(cur: any, token: string): any {
|
|
79
|
+
if (Array.isArray(cur)) {
|
|
80
|
+
if (token === 'count' || token === 'length') return cur.length;
|
|
81
|
+
if (token === 'first') return cur[0];
|
|
82
|
+
if (token === 'last') return cur[cur.length - 1];
|
|
83
|
+
if (/^\d+$/.test(token)) return cur[Number(token)];
|
|
84
|
+
return cur[0] == null ? undefined : cur[0][token]; // shorthand: first row's field
|
|
85
|
+
}
|
|
86
|
+
if (cur && typeof cur === 'object') return cur[token];
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Bind a raw value (e.g. an `@query` result array) under `key` so `{{key.…}}` paths resolve.
|
|
92
|
+
* Unlike set(), the value is stored as-is (array/object), not coerced to a string.
|
|
93
|
+
*/
|
|
94
|
+
bind(key: string, value: any): void {
|
|
95
|
+
this.data[key] = value;
|
|
61
96
|
}
|
|
62
97
|
|
|
63
98
|
/**
|
|
@@ -68,6 +103,32 @@ export class TestDataLoader {
|
|
|
68
103
|
set(key: string, value: string): void {
|
|
69
104
|
this.data[key] = value;
|
|
70
105
|
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Data-driven (@cases): return the list of rows at `key` (after env-overlay merge),
|
|
109
|
+
* each stamped with `__label` for the test title / report. Throws if missing or not a list.
|
|
110
|
+
*/
|
|
111
|
+
cases(key: string): Array<Record<string, any>> {
|
|
112
|
+
const list = this.data[key];
|
|
113
|
+
if (!Array.isArray(list)) {
|
|
114
|
+
throw new Error(`@cases dataset "${key}" not found or not a list in test-data (got ${typeof list}).`);
|
|
115
|
+
}
|
|
116
|
+
return list.map((row: any, i: number) => {
|
|
117
|
+
const r: Record<string, any> = (row && typeof row === 'object' && !Array.isArray(row)) ? { ...row } : { value: row };
|
|
118
|
+
r.__label = String(r.case ?? r.name ?? r.label ?? `row ${i + 1}`);
|
|
119
|
+
return r;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Data-driven (@cases): a view whose get() prefers the given row's columns and falls
|
|
125
|
+
* back to the shared data. Used inside the per-row test() loop.
|
|
126
|
+
*/
|
|
127
|
+
withRow(row: Record<string, any>): TestDataLoader {
|
|
128
|
+
const view = new TestDataLoader({ ...this.data }); // clone → per-row set() stays isolated
|
|
129
|
+
view.row = row;
|
|
130
|
+
return view;
|
|
131
|
+
}
|
|
71
132
|
}
|
|
72
133
|
|
|
73
134
|
function loadYamlSync(filePath: string): Record<string, any> | null {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sun-asterisk/sungen",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.2-beta.93",
|
|
4
4
|
"description": "Deterministic E2E Test Compiler - Gherkin + Selectors → Playwright tests",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"copy-templates": "mkdir -p dist/generators/test-generator/adapters/playwright/templates/steps && mkdir -p dist/generators/test-generator/templates && mkdir -p dist/orchestrator/templates && mkdir -p dist/dashboard/templates && cp -r src/generators/test-generator/adapters/playwright/templates/*.hbs dist/generators/test-generator/adapters/playwright/templates/ 2>/dev/null || true && cp -r src/generators/test-generator/adapters/playwright/templates/steps dist/generators/test-generator/adapters/playwright/templates/ && cp src/generators/test-generator/templates/*.hbs dist/generators/test-generator/templates/ 2>/dev/null || true && cp -r src/orchestrator/templates/* dist/orchestrator/templates/ && cp src/dashboard/templates/index.html dist/dashboard/templates/index.html && mkdir -p dist/harness/catalog && cp src/harness/catalog/*.yaml dist/harness/catalog/",
|
|
13
13
|
"build:dashboard": "cd dashboard && npm install --silent && npm run build && cd .. && cp dashboard/dist/index.html src/dashboard/templates/index.html",
|
|
14
14
|
"dev": "tsx src/cli/index.ts",
|
|
15
|
-
"test": "tsx tests/golden/run.ts && tsx tests/audit/run.ts && tsx tests/ingest/run.ts && tsx tests/eval/run.ts",
|
|
15
|
+
"test": "tsx tests/golden/run.ts && tsx tests/audit/run.ts && tsx tests/ingest/run.ts && tsx tests/eval/run.ts && tsx tests/exporter/run.ts",
|
|
16
16
|
"test:update": "tsx tests/golden/run.ts --update && tsx tests/audit/run.ts --update && tsx tests/ingest/run.ts --update",
|
|
17
17
|
"prepublishOnly": "npm run build:dashboard && npm run build"
|
|
18
18
|
},
|
|
@@ -38,11 +38,15 @@ export function registerChallengeCommand(program: Command): void {
|
|
|
38
38
|
if (report.collectionClaimSingular.length) {
|
|
39
39
|
for (const f of report.collectionClaimSingular) L(` ⚠ ${f.scenario}\n → ${f.suggestion}`);
|
|
40
40
|
} else L(' ✓ none');
|
|
41
|
-
L(' ②
|
|
41
|
+
L(' ② Data-driven — scenarios that should be one `@cases` (collapse data-variants / cover EP classes)');
|
|
42
|
+
if (report.dataDriven.length) {
|
|
43
|
+
for (const f of report.dataDriven) L(` ⚠ ${f.scenario}\n → ${f.suggestion}`);
|
|
44
|
+
} else L(' ✓ none');
|
|
45
|
+
L(' ③ Coverage — over-covered / shallow');
|
|
42
46
|
if (report.overCovered.length) for (const o2 of report.overCovered) L(` • ${o2.bucket}: ${o2.note}`);
|
|
43
47
|
if (report.shallowThemes.length) L(` • shallow themes: ${report.shallowThemes.join(', ')}`);
|
|
44
48
|
if (!report.overCovered.length && !report.shallowThemes.length) L(' ✓ balanced');
|
|
45
|
-
L('
|
|
49
|
+
L(' ④ Novelty — prompts for the `sungen-challenge` agent (≤20% of official, no auto-merge)');
|
|
46
50
|
for (const p of report.noveltyPrompts) L(` • ${p}`);
|
|
47
51
|
L(' ── Exploration readiness ──');
|
|
48
52
|
for (const e of report.explorationReadiness) L(` • ${e}`);
|
|
@@ -200,11 +200,12 @@ function discoverLocaleVariants(cwd: string, target: DeliveryTarget): LocaleVari
|
|
|
200
200
|
const prefix = `${target.featureBaseName}-test-result`;
|
|
201
201
|
const variants: LocaleVariant[] = [];
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
// Base variant: per-target result file if present, else fall back to the global
|
|
204
|
+
// test-results/results.json (what playwright.config writes by default) via resolveResultsPath.
|
|
204
205
|
variants.push({
|
|
205
206
|
locale: '',
|
|
206
207
|
displayCode: DEFAULT_BASE_LOCALE.toUpperCase(),
|
|
207
|
-
resultsPath:
|
|
208
|
+
resultsPath: resolveResultsPath(cwd, target),
|
|
208
209
|
});
|
|
209
210
|
|
|
210
211
|
if (fs.existsSync(genDir)) {
|