gherkin-ai 2.2.0 → 2.3.1
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/README.md +4 -1
- package/dist/commands/autopilot.d.ts.map +1 -1
- package/dist/commands/autopilot.js +5 -0
- package/dist/commands/autopilot.js.map +1 -1
- package/dist/commands/create.d.ts +2 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +50 -0
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +23 -2
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +5 -0
- package/dist/commands/verify.js.map +1 -1
- package/dist/core/agent-adapter.d.ts +1 -0
- package/dist/core/agent-adapter.d.ts.map +1 -1
- package/dist/core/agent-adapter.js +20 -9
- package/dist/core/agent-adapter.js.map +1 -1
- package/dist/core/context-extractor.d.ts +9 -0
- package/dist/core/context-extractor.d.ts.map +1 -0
- package/dist/core/context-extractor.js +60 -0
- package/dist/core/context-extractor.js.map +1 -0
- package/dist/core/gherkin-parser.d.ts.map +1 -1
- package/dist/core/gherkin-parser.js +4 -2
- package/dist/core/gherkin-parser.js.map +1 -1
- package/dist/core/step-indexer.d.ts +19 -0
- package/dist/core/step-indexer.d.ts.map +1 -0
- package/dist/core/step-indexer.js +86 -0
- package/dist/core/step-indexer.js.map +1 -0
- package/dist/core/syntax-validator.d.ts +6 -0
- package/dist/core/syntax-validator.d.ts.map +1 -0
- package/dist/core/syntax-validator.js +37 -0
- package/dist/core/syntax-validator.js.map +1 -0
- package/dist/generators/prompt-templates/base.d.ts +4 -0
- package/dist/generators/prompt-templates/base.d.ts.map +1 -1
- package/dist/generators/prompt-templates/base.js.map +1 -1
- package/dist/generators/prompts.d.ts.map +1 -1
- package/dist/generators/prompts.js +37 -1
- package/dist/generators/prompts.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/public/index.html +156 -0
- package/docs/ai-skills.md +42 -0
- package/docs/ast-step-indexer.md +47 -0
- package/docs/headless-mode.md +74 -0
- package/package.json +3 -3
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.StepIndexer = exports.RegexStepParser = exports.TypeScriptStepParser = void 0;
|
|
7
|
+
const ts_morph_1 = require("ts-morph");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const logger_1 = require("../utils/logger");
|
|
10
|
+
class TypeScriptStepParser {
|
|
11
|
+
parse(workspaceRoot) {
|
|
12
|
+
const steps = [];
|
|
13
|
+
const project = new ts_morph_1.Project();
|
|
14
|
+
// Look in common TS/JS E2E directories
|
|
15
|
+
const searchGlobs = [
|
|
16
|
+
path_1.default.join(workspaceRoot, 'cypress/support/**/*.ts'),
|
|
17
|
+
path_1.default.join(workspaceRoot, 'cypress/support/**/*.js'),
|
|
18
|
+
path_1.default.join(workspaceRoot, 'e2e/steps/**/*.ts'),
|
|
19
|
+
path_1.default.join(workspaceRoot, 'tests/steps/**/*.ts'),
|
|
20
|
+
path_1.default.join(workspaceRoot, 'features/step_definitions/**/*.ts')
|
|
21
|
+
];
|
|
22
|
+
project.addSourceFilesAtPaths(searchGlobs);
|
|
23
|
+
const sourceFiles = project.getSourceFiles();
|
|
24
|
+
for (const sf of sourceFiles) {
|
|
25
|
+
// Find all call expressions like Given('...', () => {})
|
|
26
|
+
const callExpressions = sf.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
|
|
27
|
+
for (const callExpr of callExpressions) {
|
|
28
|
+
const expression = callExpr.getExpression();
|
|
29
|
+
const funcName = expression.getText();
|
|
30
|
+
if (['Given', 'When', 'Then', 'step', 'dado', 'cuando', 'entonces'].includes(funcName)) {
|
|
31
|
+
const args = callExpr.getArguments();
|
|
32
|
+
if (args.length > 0) {
|
|
33
|
+
const firstArg = args[0];
|
|
34
|
+
let pattern = '';
|
|
35
|
+
// If it's a string literal: Given("I login", ...)
|
|
36
|
+
if (firstArg.getKindName() === 'StringLiteral' || firstArg.getKindName() === 'NoSubstitutionTemplateLiteral') {
|
|
37
|
+
pattern = firstArg.getText().replace(/^['"`]/, '').replace(/['"`]$/, '');
|
|
38
|
+
}
|
|
39
|
+
// If it's a regex: Given(/^I login$/, ...)
|
|
40
|
+
else if (firstArg.getKindName() === 'RegularExpressionLiteral') {
|
|
41
|
+
pattern = firstArg.getText();
|
|
42
|
+
}
|
|
43
|
+
if (pattern) {
|
|
44
|
+
steps.push({
|
|
45
|
+
keyword: funcName,
|
|
46
|
+
pattern,
|
|
47
|
+
filePath: sf.getFilePath()
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return steps;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.TypeScriptStepParser = TypeScriptStepParser;
|
|
58
|
+
class RegexStepParser {
|
|
59
|
+
parse(workspaceRoot) {
|
|
60
|
+
// A fallback parser for languages without AST support yet (Python, Java, etc.)
|
|
61
|
+
// Searches text for @given('...') or @When("...")
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.RegexStepParser = RegexStepParser;
|
|
66
|
+
class StepIndexer {
|
|
67
|
+
parsers = [
|
|
68
|
+
new TypeScriptStepParser(),
|
|
69
|
+
new RegexStepParser() // Fallback
|
|
70
|
+
];
|
|
71
|
+
getAvailableSteps(workspaceRoot) {
|
|
72
|
+
const allSteps = [];
|
|
73
|
+
for (const parser of this.parsers) {
|
|
74
|
+
try {
|
|
75
|
+
const parsed = parser.parse(workspaceRoot);
|
|
76
|
+
allSteps.push(...parsed);
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
logger_1.logger.error(`Error parsing steps: ${e.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return allSteps;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.StepIndexer = StepIndexer;
|
|
86
|
+
//# sourceMappingURL=step-indexer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-indexer.js","sourceRoot":"","sources":["../../src/core/step-indexer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates TypeScript syntax in-memory before writing to disk.
|
|
3
|
+
* Returns true if valid, false if syntax errors exist.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateTypeScriptSyntax(filename: string, content: string): boolean;
|
|
6
|
+
//# sourceMappingURL=syntax-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syntax-validator.d.ts","sourceRoot":"","sources":["../../src/core/syntax-validator.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAyBnF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateTypeScriptSyntax = validateTypeScriptSyntax;
|
|
7
|
+
const ts_morph_1 = require("ts-morph");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
/**
|
|
10
|
+
* Validates TypeScript syntax in-memory before writing to disk.
|
|
11
|
+
* Returns true if valid, false if syntax errors exist.
|
|
12
|
+
*/
|
|
13
|
+
function validateTypeScriptSyntax(filename, content) {
|
|
14
|
+
if (!filename.endsWith('.ts') && !filename.endsWith('.tsx')) {
|
|
15
|
+
return true; // We only validate TS files for now
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const project = new ts_morph_1.Project({ useInMemoryFileSystem: true });
|
|
19
|
+
const sourceFile = project.createSourceFile(filename, content);
|
|
20
|
+
// Check syntactic diagnostics (fast) rather than semantic (slow, requires full project)
|
|
21
|
+
const diagnostics = sourceFile.getPreEmitDiagnostics();
|
|
22
|
+
const errors = diagnostics.filter(d => d.getCategory() === 1); // Error category
|
|
23
|
+
if (errors.length > 0) {
|
|
24
|
+
console.log(chalk_1.default.yellow(` ⚠️ Pre-validation failed for ${filename}:`));
|
|
25
|
+
for (const diag of errors.slice(0, 3)) {
|
|
26
|
+
console.log(chalk_1.default.yellow(` - ${diag.getMessageText()}`));
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.log(chalk_1.default.yellow(` ⚠️ Pre-validation exception for ${filename}: ${err.message}`));
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=syntax-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syntax-validator.js","sourceRoot":"","sources":["../../src/core/syntax-validator.ts"],"names":[],"mappings":";;;;;AAOA,4DAyBC;AAhCD,uCAAmC;AACnC,kDAA0B;AAE1B;;;GAGG;AACH,SAAgB,wBAAwB,CAAC,QAAgB,EAAE,OAAe;IACxE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAC,CAAC,oCAAoC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,kBAAO,CAAC,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAE/D,wFAAwF;QACxF,MAAM,WAAW,GAAG,UAAU,CAAC,qBAAqB,EAAE,CAAC;QACvD,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB;QAEhF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,mCAAmC,QAAQ,GAAG,CAAC,CAAC,CAAC;YAC1E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBACtC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,sCAAsC,QAAQ,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC5F,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -2,12 +2,16 @@ import { GherkinAIConfig } from '../../core/config';
|
|
|
2
2
|
import { ParsedFeature } from '../../core/gherkin-parser';
|
|
3
3
|
import { ArchRuleSpec } from '../../core/arch-rules';
|
|
4
4
|
import { StackSpec } from '../../core/stack-specs';
|
|
5
|
+
import { ExtractedStep } from '../../core/step-indexer';
|
|
6
|
+
import { AppContext } from '../../core/context-extractor';
|
|
5
7
|
export interface PromptTemplateContext {
|
|
6
8
|
config: GherkinAIConfig;
|
|
7
9
|
parsed: ParsedFeature;
|
|
8
10
|
arch: ArchRuleSpec;
|
|
9
11
|
spec: StackSpec;
|
|
10
12
|
isSpanishUser: boolean;
|
|
13
|
+
availableSteps: ExtractedStep[];
|
|
14
|
+
appContext: AppContext;
|
|
11
15
|
}
|
|
12
16
|
export interface PromptTemplate {
|
|
13
17
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/generators/prompt-templates/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/generators/prompt-templates/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC;IAC5C,mBAAmB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAC5D,oBAAoB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IAC7D,eAAe,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;IACxD,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,MAAM,CAAC;CAC1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,qBAAqB,GAAG,MAAM,CAOrG;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,CAEnE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,qBAAqB,GAAG,MAAM,CAEjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/generators/prompt-templates/base.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/generators/prompt-templates/base.ts"],"names":[],"mappings":";;AA0BA,8CAOC;AAED,4CAEC;AAED,wCAEC;AAfD,SAAgB,iBAAiB,CAAC,IAAY,EAAE,SAAiB,EAAE,GAA0B;IAC3F,IAAI,MAAM,GAAG,YAAY,IAAI,IAAI,CAAC;IAClC,MAAM,IAAI,cAAc,SAAS,MAAM,CAAC;IACxC,IAAI,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,MAAM,IAAI,gJAAgJ,CAAC;IAC7J,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,gBAAgB,CAAC,GAA0B;IACzD,OAAO,6BAA6B,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAC/H,CAAC;AAED,SAAgB,cAAc,CAAC,GAA0B;IACvD,OAAO,6BAA6B,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACnH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/generators/prompts.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/generators/prompts.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AASjD,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgEtG"}
|
|
@@ -8,16 +8,24 @@ const arch_rules_1 = require("../core/arch-rules");
|
|
|
8
8
|
const stack_specs_1 = require("../core/stack-specs");
|
|
9
9
|
const factory_1 = require("./prompt-templates/factory");
|
|
10
10
|
const i18n_cli_1 = require("../utils/i18n-cli");
|
|
11
|
+
const step_indexer_1 = require("../core/step-indexer");
|
|
12
|
+
const context_extractor_1 = require("../core/context-extractor");
|
|
11
13
|
function generatePrompts(parsed, config) {
|
|
12
14
|
const arch = (0, arch_rules_1.getArchRule)(config.architecture);
|
|
13
15
|
const spec = (0, stack_specs_1.getStackSpec)(config.stack);
|
|
14
16
|
const isSpanishUser = (0, i18n_cli_1.getGlobalUserLocale)() === 'es';
|
|
17
|
+
const indexer = new step_indexer_1.StepIndexer();
|
|
18
|
+
const availableSteps = indexer.getAvailableSteps(process.cwd());
|
|
19
|
+
const extractor = new context_extractor_1.ContextExtractor();
|
|
20
|
+
const appContext = extractor.extract(process.cwd());
|
|
15
21
|
const ctx = {
|
|
16
22
|
config,
|
|
17
23
|
parsed,
|
|
18
24
|
arch,
|
|
19
25
|
spec,
|
|
20
|
-
isSpanishUser
|
|
26
|
+
isSpanishUser,
|
|
27
|
+
availableSteps,
|
|
28
|
+
appContext
|
|
21
29
|
};
|
|
22
30
|
const template = (0, factory_1.resolvePromptTemplate)(config);
|
|
23
31
|
const result = {
|
|
@@ -25,8 +33,36 @@ function generatePrompts(parsed, config) {
|
|
|
25
33
|
'backend-agent.md': template.generateBackendAgent(ctx),
|
|
26
34
|
'qa-agent.md': template.generateQaAgent(ctx)
|
|
27
35
|
};
|
|
36
|
+
// Inject DOM and Data Models to Backend/QA/Domain agents
|
|
37
|
+
let contextDict = '';
|
|
38
|
+
if (ctx.appContext.dataModels.length > 0) {
|
|
39
|
+
contextDict += `\n## [MANDATORY] Extracted Data Models (Prisma)\n\`\`\`prisma\n${ctx.appContext.dataModels.join('\n\n')}\n\`\`\`\n`;
|
|
40
|
+
result['backend-agent.md'] += contextDict;
|
|
41
|
+
result['domain-agent.md'] += contextDict;
|
|
42
|
+
}
|
|
43
|
+
if (ctx.appContext.domSelectors.length > 0) {
|
|
44
|
+
let domDict = `\n## [MANDATORY] Discovered DOM Selectors (POM)\nYou must use these selectors in your tests:\n${ctx.appContext.domSelectors.map(s => `- \`${s}\``).join('\n')}\n`;
|
|
45
|
+
result['qa-agent.md'] += domDict;
|
|
46
|
+
}
|
|
47
|
+
// Inject extracted Step Definitions (AST Indexing) to force step reuse
|
|
48
|
+
if (ctx.availableSteps && ctx.availableSteps.length > 0) {
|
|
49
|
+
let stepsDict = `\n## [MANDATORY] Step Definitions Dictionary\n`;
|
|
50
|
+
stepsDict += `You MUST reuse the following existing Step Definitions whenever possible instead of inventing new ones:\n\n`;
|
|
51
|
+
ctx.availableSteps.forEach(st => {
|
|
52
|
+
stepsDict += `- \`${st.keyword} ${st.pattern}\` (found in ${st.filePath})\n`;
|
|
53
|
+
});
|
|
54
|
+
result['qa-agent.md'] += stepsDict;
|
|
55
|
+
}
|
|
28
56
|
if (template.generateAiAgent && config.stack.aiEngine) {
|
|
29
57
|
result['ai-engineer-agent.md'] = template.generateAiAgent(ctx);
|
|
58
|
+
if (contextDict)
|
|
59
|
+
result['ai-engineer-agent.md'] += contextDict;
|
|
60
|
+
if (ctx.appContext.domSelectors.length > 0) {
|
|
61
|
+
result['ai-engineer-agent.md'] += `\n## [MANDATORY] Discovered DOM Selectors (POM)\nYou must use these selectors in your UI tests:\n${ctx.appContext.domSelectors.map(s => `- \`${s}\``).join('\n')}\n`;
|
|
62
|
+
}
|
|
63
|
+
if (ctx.availableSteps && ctx.availableSteps.length > 0) {
|
|
64
|
+
result['ai-engineer-agent.md'] += `\n## [MANDATORY] Step Definitions Dictionary\nYou MUST reuse existing Step Definitions in QA specs:\n${ctx.availableSteps.map(s => `- \`${s.keyword} ${s.pattern}\``).join('\n')}\n`;
|
|
65
|
+
}
|
|
30
66
|
}
|
|
31
67
|
return result;
|
|
32
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/generators/prompts.ts"],"names":[],"mappings":";AAAA;;gFAEgF;;
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/generators/prompts.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -135,6 +135,8 @@ program
|
|
|
135
135
|
.option('-t, --target <directory>', 'Target directory to inject contracts')
|
|
136
136
|
.option('-l, --lang <locale>', 'Override CLI interaction language for this run (en or es)')
|
|
137
137
|
.option('-C, --caveman', 'Enable simple prompt creation mode (skip step-by-step wizard)')
|
|
138
|
+
.option('--headless', 'Run in headless non-interactive mode for CI/CD')
|
|
139
|
+
.option('--config <file>', 'Path to JSON configuration file for headless mode')
|
|
138
140
|
.action(async (options) => {
|
|
139
141
|
await (0, create_1.handleCreateCommand)(options);
|
|
140
142
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Gherkin AI Studio</title>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
|
9
|
+
<style>
|
|
10
|
+
body { font-family: 'Inter', sans-serif; background-color: #0f172a; color: #e2e8f0; }
|
|
11
|
+
.glass-panel { background: rgba(30, 41, 59, 0.7); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px; }
|
|
12
|
+
.code-bg { background-color: #1e293b; color: #38bdf8; font-family: monospace; }
|
|
13
|
+
.gradient-text { background: linear-gradient(to right, #38bdf8, #818cf8); -webkit-background-clip: text; color: transparent; }
|
|
14
|
+
</style>
|
|
15
|
+
</head>
|
|
16
|
+
<body class="min-h-screen flex flex-col p-6">
|
|
17
|
+
<header class="flex justify-between items-center mb-8 glass-panel p-4 px-6 shadow-lg">
|
|
18
|
+
<h1 class="text-2xl font-bold gradient-text flex items-center gap-3">
|
|
19
|
+
<i class="fa-solid fa-robot"></i> Gherkin AI Studio
|
|
20
|
+
</h1>
|
|
21
|
+
<div id="stack-badge" class="hidden items-center gap-2 px-3 py-1 bg-indigo-900/50 text-indigo-200 border border-indigo-700/50 rounded-full text-sm font-medium">
|
|
22
|
+
<i class="fa-solid fa-layer-group"></i> <span id="stack-name">Detecting...</span>
|
|
23
|
+
</div>
|
|
24
|
+
</header>
|
|
25
|
+
|
|
26
|
+
<main class="flex-1 grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
27
|
+
<!-- Editor Section -->
|
|
28
|
+
<section class="glass-panel p-6 flex flex-col shadow-xl">
|
|
29
|
+
<h2 class="text-xl font-semibold mb-4 text-sky-400 border-b border-slate-700 pb-2"><i class="fa-regular fa-file-code"></i> Feature Specification</h2>
|
|
30
|
+
<div class="mb-4">
|
|
31
|
+
<label class="block text-sm font-medium text-slate-400 mb-1">Feature Name</label>
|
|
32
|
+
<input type="text" id="feature-name" placeholder="e.g. User Authentication" class="w-full bg-slate-800 border border-slate-600 rounded-md p-2 text-white focus:outline-none focus:ring-2 focus:ring-sky-500">
|
|
33
|
+
</div>
|
|
34
|
+
<div class="flex-1 flex flex-col">
|
|
35
|
+
<label class="block text-sm font-medium text-slate-400 mb-1">Gherkin Scenarios</label>
|
|
36
|
+
<textarea id="gherkin-text" class="w-full flex-1 min-h-[300px] bg-slate-900 border border-slate-700 rounded-md p-4 text-sky-100 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-sky-500" placeholder="Feature: Example Feature Scenario: Successful login Given the user is on the login page When they enter valid credentials Then they should be redirected to the dashboard"></textarea>
|
|
37
|
+
</div>
|
|
38
|
+
<button id="generate-btn" class="mt-6 w-full py-3 bg-gradient-to-r from-sky-500 to-indigo-600 hover:from-sky-400 hover:to-indigo-500 text-white font-bold rounded-lg shadow-lg shadow-sky-500/20 transition-all flex justify-center items-center gap-2">
|
|
39
|
+
<i class="fa-solid fa-wand-magic-sparkles"></i> Generate AI Agents & Contracts
|
|
40
|
+
</button>
|
|
41
|
+
</section>
|
|
42
|
+
|
|
43
|
+
<!-- Results Section -->
|
|
44
|
+
<section class="glass-panel p-6 flex flex-col shadow-xl">
|
|
45
|
+
<h2 class="text-xl font-semibold mb-4 text-indigo-400 border-b border-slate-700 pb-2"><i class="fa-solid fa-microchip"></i> Generation Results</h2>
|
|
46
|
+
|
|
47
|
+
<div id="loading" class="hidden flex-1 flex flex-col justify-center items-center text-slate-400">
|
|
48
|
+
<i class="fa-solid fa-circle-notch fa-spin text-4xl mb-4 text-sky-500"></i>
|
|
49
|
+
<p>Orchestrating agents and generating code...</p>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div id="results-empty" class="flex-1 flex flex-col justify-center items-center text-slate-500 text-center p-8">
|
|
53
|
+
<i class="fa-regular fa-folder-open text-6xl mb-4 opacity-50"></i>
|
|
54
|
+
<p>Waiting for Gherkin specification.<br>Click Generate to see the results here.</p>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div id="results-content" class="hidden flex-1 flex flex-col gap-4 overflow-y-auto pr-2">
|
|
58
|
+
<div class="bg-emerald-900/30 border border-emerald-700/50 text-emerald-200 p-4 rounded-lg flex items-start gap-3">
|
|
59
|
+
<i class="fa-solid fa-check-circle mt-1"></i>
|
|
60
|
+
<div>
|
|
61
|
+
<p class="font-bold">Generation Successful!</p>
|
|
62
|
+
<p class="text-sm opacity-80" id="success-path">Files saved to ./generated-specs/</p>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<h3 class="font-semibold text-slate-300 mt-2">Generated Files:</h3>
|
|
67
|
+
<div id="file-list" class="flex flex-col gap-2">
|
|
68
|
+
<!-- Files injected via JS -->
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
</main>
|
|
73
|
+
|
|
74
|
+
<script>
|
|
75
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
76
|
+
// Fetch detected stack
|
|
77
|
+
try {
|
|
78
|
+
const res = await fetch('/api/stack');
|
|
79
|
+
const data = await res.json();
|
|
80
|
+
if (data.success) {
|
|
81
|
+
const cfg = data.config;
|
|
82
|
+
document.getElementById('stack-name').textContent = `${cfg.architecture.toUpperCase()} | ${cfg.stack.language} (${cfg.stack.framework})`;
|
|
83
|
+
document.getElementById('stack-badge').classList.remove('hidden');
|
|
84
|
+
document.getElementById('stack-badge').classList.add('flex');
|
|
85
|
+
}
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error("Failed to fetch stack", err);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Handle Generate Button
|
|
91
|
+
document.getElementById('generate-btn').addEventListener('click', async () => {
|
|
92
|
+
const featureName = document.getElementById('feature-name').value;
|
|
93
|
+
const gherkinText = document.getElementById('gherkin-text').value;
|
|
94
|
+
|
|
95
|
+
if (!gherkinText.trim()) {
|
|
96
|
+
alert("Please write some Gherkin scenarios first.");
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// UI State
|
|
101
|
+
document.getElementById('results-empty').classList.add('hidden');
|
|
102
|
+
document.getElementById('results-content').classList.add('hidden');
|
|
103
|
+
document.getElementById('loading').classList.remove('hidden');
|
|
104
|
+
document.getElementById('loading').classList.add('flex');
|
|
105
|
+
document.getElementById('generate-btn').disabled = true;
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const res = await fetch('/api/generate', {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
headers: { 'Content-Type': 'application/json' },
|
|
111
|
+
body: JSON.stringify({ featureName, gherkinText })
|
|
112
|
+
});
|
|
113
|
+
const data = await res.json();
|
|
114
|
+
|
|
115
|
+
document.getElementById('loading').classList.add('hidden');
|
|
116
|
+
document.getElementById('loading').classList.remove('flex');
|
|
117
|
+
|
|
118
|
+
if (data.success) {
|
|
119
|
+
document.getElementById('results-content').classList.remove('hidden');
|
|
120
|
+
document.getElementById('results-content').classList.add('flex');
|
|
121
|
+
document.getElementById('success-path').textContent = `Saved to: ${data.outDir}`;
|
|
122
|
+
|
|
123
|
+
const fileList = document.getElementById('file-list');
|
|
124
|
+
fileList.innerHTML = '';
|
|
125
|
+
Object.keys(data.files).forEach(filename => {
|
|
126
|
+
const div = document.createElement('div');
|
|
127
|
+
const isMd = filename.endsWith('.md');
|
|
128
|
+
div.className = 'bg-slate-800 border border-slate-700 rounded p-3 text-sm flex justify-between items-center';
|
|
129
|
+
div.innerHTML = `
|
|
130
|
+
<div class="flex items-center gap-2">
|
|
131
|
+
<i class="fa-solid ${isMd ? 'fa-file-lines text-sky-400' : 'fa-code text-amber-400'}"></i>
|
|
132
|
+
<span class="font-mono">${filename}</span>
|
|
133
|
+
</div>
|
|
134
|
+
<span class="text-xs bg-slate-700 px-2 py-1 rounded text-slate-300">Generated</span>
|
|
135
|
+
`;
|
|
136
|
+
fileList.appendChild(div);
|
|
137
|
+
});
|
|
138
|
+
} else {
|
|
139
|
+
alert("Error generating specs: " + data.error);
|
|
140
|
+
document.getElementById('results-empty').classList.remove('hidden');
|
|
141
|
+
document.getElementById('results-empty').classList.add('flex');
|
|
142
|
+
}
|
|
143
|
+
} catch (err) {
|
|
144
|
+
alert("Network error: " + err.message);
|
|
145
|
+
document.getElementById('loading').classList.add('hidden');
|
|
146
|
+
document.getElementById('loading').classList.remove('flex');
|
|
147
|
+
document.getElementById('results-empty').classList.remove('hidden');
|
|
148
|
+
document.getElementById('results-empty').classList.add('flex');
|
|
149
|
+
} finally {
|
|
150
|
+
document.getElementById('generate-btn').disabled = false;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
</script>
|
|
155
|
+
</body>
|
|
156
|
+
</html>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# AI Skills & Context Extraction
|
|
2
|
+
|
|
3
|
+
`gherkin-ai` is built to seamlessly integrate with modern AI IDEs and standalone agents. It provides native skills and context anchors to ensure the LLM understands your architecture.
|
|
4
|
+
|
|
5
|
+
## 1. Context Anchoring (DOM & Data Models)
|
|
6
|
+
|
|
7
|
+
Generating Gherkin specs in a vacuum produces abstract scenarios that require human intervention to execute. To generate truly executable automation, the AI must understand your application's technical reality.
|
|
8
|
+
|
|
9
|
+
`gherkin-ai` introduces **Context Extractor**.
|
|
10
|
+
|
|
11
|
+
Before generating prompts or agent contexts, the CLI scans your workspace for:
|
|
12
|
+
- **Data Models:** It parses `prisma/schema.prisma` to extract your entity schemas (up to 5 models).
|
|
13
|
+
- **DOM Selectors (Page Object Model):** It scans your `e2e/` folder for `data-test` and `data-testid` attributes.
|
|
14
|
+
|
|
15
|
+
These assets are injected into the agent's markdown instructions as `[MANDATORY]` directives, forcing the LLM to write tests that match the actual database models and frontend HTML structure.
|
|
16
|
+
|
|
17
|
+
## 2. Cursor & Windsurf Skills (`ghk skill`)
|
|
18
|
+
|
|
19
|
+
Modern AI IDEs like [Cursor](https://cursor.sh/) and [Windsurf](https://codeium.com/windsurf) support custom `.cursorrules` and project instructions to steer the built-in AI's behavior.
|
|
20
|
+
|
|
21
|
+
The `ghk skill` command configures `gherkin-ai` as a native skill inside your IDE.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ghk skill
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This command automatically generates a `.cursorrules` file (or appends to an existing one) instructing the IDE's AI to:
|
|
28
|
+
1. Always parse `.feature` files to understand business logic.
|
|
29
|
+
2. Use `ghk verify --auto-fix` whenever running tests.
|
|
30
|
+
3. Automatically run `ghk diff` to ensure DTOs match specs.
|
|
31
|
+
|
|
32
|
+
By configuring this skill, your AI assistant goes from being a generic coding bot to an enterprise-grade QA engineer constrained by BDD specifications.
|
|
33
|
+
|
|
34
|
+
## 3. Model Context Protocol (MCP)
|
|
35
|
+
|
|
36
|
+
For desktop agents like Claude Desktop, `gherkin-ai` operates as a native JSON-RPC Model Context Protocol (MCP) server.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
ghk mcp install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This command auto-configures your `claude_desktop_config.json`, exposing tools that the AI can call natively to validate syntax, generate contracts, or read the Step Definitions dictionary in real-time.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# AST Step Definitions Indexer
|
|
2
|
+
|
|
3
|
+
A common challenge when integrating AI into Behavior-Driven Development (BDD) is **AI Hallucination**: Large Language Models (LLMs) tend to invent generic Gherkin steps (e.g., `Given that the user enters data`) rather than reusing the exact Step Definitions already implemented in your test automation framework (e.g., `Given I navigate to login`).
|
|
4
|
+
|
|
5
|
+
This lack of alignment forces QA engineers to manually rewrite generated steps or duplicate test executor code.
|
|
6
|
+
|
|
7
|
+
## How `gherkin-ai` Solves This
|
|
8
|
+
|
|
9
|
+
`gherkin-ai` incorporates an advanced **AST (Abstract Syntax Tree) Step Indexer** powered by `ts-morph`.
|
|
10
|
+
|
|
11
|
+
Instead of relying on the LLM's raw creativity, the CLI performs static code analysis on your project workspace before generating any AI prompts.
|
|
12
|
+
|
|
13
|
+
### 1. Static Analysis
|
|
14
|
+
The indexer scans common E2E directories in your project:
|
|
15
|
+
- `cypress/support/**/*.ts`
|
|
16
|
+
- `e2e/steps/**/*.ts`
|
|
17
|
+
- `features/step_definitions/**/*.ts`
|
|
18
|
+
|
|
19
|
+
It extracts the string literals and regular expressions defined inside `Given`, `When`, and `Then` function calls.
|
|
20
|
+
|
|
21
|
+
### 2. Prompt Injection (The Dictionary)
|
|
22
|
+
All extracted steps are compiled into a mandatory "Step Definitions Dictionary" and injected into the System Prompt for the `qa-agent` and `ai-engineer` agents.
|
|
23
|
+
|
|
24
|
+
The prompt explicitly enforces:
|
|
25
|
+
> *You MUST reuse the following existing Step Definitions whenever possible instead of inventing new ones.*
|
|
26
|
+
|
|
27
|
+
### Example
|
|
28
|
+
|
|
29
|
+
**Existing Cypress Step:**
|
|
30
|
+
```typescript
|
|
31
|
+
Given('I navigate to the {string} page', (pageName: string) => {
|
|
32
|
+
cy.visit(`/${pageName}`);
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**What the AI Agent sees:**
|
|
37
|
+
```markdown
|
|
38
|
+
## [MANDATORY] Step Definitions Dictionary
|
|
39
|
+
You MUST reuse the following existing Step Definitions whenever possible instead of inventing new ones:
|
|
40
|
+
- `Given I navigate to the {string} page` (found in cypress/support/steps.ts)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Phased Language Support
|
|
44
|
+
|
|
45
|
+
Currently, the AST Indexer natively supports TypeScript and JavaScript ecosystems (Cypress, Playwright, Cucumber-JS) via `ts-morph`.
|
|
46
|
+
|
|
47
|
+
A secondary `RegexStepParser` acts as a fallback foundation designed to support Python (Behave), Java (Cucumber-JVM), and other languages in future phases.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Headless CI/CD Mode
|
|
2
|
+
|
|
3
|
+
`gherkin-ai` is designed to be an enterprise automation framework. While the interactive CLI wizard (`ghk create`) is excellent for local development, CI/CD pipelines (like GitHub Actions, GitLab CI, Azure DevOps) operate in non-interactive (TTY-less) environments where standard input prompts cause execution to hang.
|
|
4
|
+
|
|
5
|
+
To solve this, `gherkin-ai` provides a robust **Headless Mode**.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
You can completely bypass the interactive `inquirer` prompts by combining the `--headless` flag with the `--config` flag.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
ghk create --headless --config my-spec.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Configuration File (`my-spec.json`)
|
|
16
|
+
|
|
17
|
+
The `--config` file must contain the structured JSON representation of your feature.
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"featureName": "Two Factor Authentication 2FA",
|
|
22
|
+
"actor": "authenticated system user",
|
|
23
|
+
"action": "enable and verify a two-factor OTP code",
|
|
24
|
+
"outcome": "protect my account against unauthorized access",
|
|
25
|
+
"scenarioName": "Enable and verify 2FA code successfully",
|
|
26
|
+
"injectTarget": "./src/application/dtos",
|
|
27
|
+
"steps": [
|
|
28
|
+
{
|
|
29
|
+
"keyword": "Given",
|
|
30
|
+
"text": "the user has logged in successfully"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"keyword": "When",
|
|
34
|
+
"text": "they enter a valid 6-digit OTP code"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"keyword": "Then",
|
|
38
|
+
"text": "the system authenticates the session"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Integration with GitHub Actions
|
|
45
|
+
|
|
46
|
+
Here is an example of running `gherkin-ai` completely headlessly inside a GitHub Actions workflow:
|
|
47
|
+
|
|
48
|
+
```yaml
|
|
49
|
+
name: Generate Contracts
|
|
50
|
+
|
|
51
|
+
on:
|
|
52
|
+
push:
|
|
53
|
+
branches: [ "main" ]
|
|
54
|
+
|
|
55
|
+
jobs:
|
|
56
|
+
generate:
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@v4
|
|
60
|
+
|
|
61
|
+
- name: Setup Node.js
|
|
62
|
+
uses: actions/setup-node@v4
|
|
63
|
+
with:
|
|
64
|
+
node-version: '20'
|
|
65
|
+
|
|
66
|
+
- name: Install gherkin-ai
|
|
67
|
+
run: npm install -g gherkin-ai
|
|
68
|
+
|
|
69
|
+
- name: Generate Feature Headlessly
|
|
70
|
+
run: ghk create --headless --config specs/login-spec.json --output specs/login.feature
|
|
71
|
+
|
|
72
|
+
- name: Generate Typings & Prompts
|
|
73
|
+
run: ghk generate -f specs/login.feature
|
|
74
|
+
```
|