@sun-asterisk/sungen 2.4.5 → 2.4.6
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/delivery.d.ts +7 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -0
- package/dist/cli/commands/delivery.js +348 -0
- package/dist/cli/commands/delivery.js.map +1 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +64 -1
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +4 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/exporters/csv-exporter.d.ts +32 -0
- package/dist/exporters/csv-exporter.d.ts.map +1 -0
- package/dist/exporters/csv-exporter.js +311 -0
- package/dist/exporters/csv-exporter.js.map +1 -0
- package/dist/exporters/feature-parser.d.ts +48 -0
- package/dist/exporters/feature-parser.d.ts.map +1 -0
- package/dist/exporters/feature-parser.js +178 -0
- package/dist/exporters/feature-parser.js.map +1 -0
- package/dist/exporters/package-info.d.ts +9 -0
- package/dist/exporters/package-info.d.ts.map +1 -0
- package/dist/exporters/package-info.js +73 -0
- package/dist/exporters/package-info.js.map +1 -0
- package/dist/exporters/playwright-report-parser.d.ts +21 -0
- package/dist/exporters/playwright-report-parser.d.ts.map +1 -0
- package/dist/exporters/playwright-report-parser.js +184 -0
- package/dist/exporters/playwright-report-parser.js.map +1 -0
- package/dist/exporters/scenario-merger.d.ts +21 -0
- package/dist/exporters/scenario-merger.d.ts.map +1 -0
- package/dist/exporters/scenario-merger.js +51 -0
- package/dist/exporters/scenario-merger.js.map +1 -0
- package/dist/exporters/spec-parser.d.ts +20 -0
- package/dist/exporters/spec-parser.d.ts.map +1 -0
- package/dist/exporters/spec-parser.js +259 -0
- package/dist/exporters/spec-parser.js.map +1 -0
- package/dist/exporters/step-formatter.d.ts +32 -0
- package/dist/exporters/step-formatter.d.ts.map +1 -0
- package/dist/exporters/step-formatter.js +76 -0
- package/dist/exporters/step-formatter.js.map +1 -0
- package/dist/exporters/test-data-resolver.d.ts +20 -0
- package/dist/exporters/test-data-resolver.d.ts.map +1 -0
- package/dist/exporters/test-data-resolver.js +96 -0
- package/dist/exporters/test-data-resolver.js.map +1 -0
- package/dist/exporters/types.d.ts +104 -0
- package/dist/exporters/types.d.ts.map +1 -0
- package/dist/exporters/types.js +6 -0
- package/dist/exporters/types.js.map +1 -0
- package/dist/exporters/xlsx-exporter.d.ts +19 -0
- package/dist/exporters/xlsx-exporter.d.ts.map +1 -0
- package/dist/exporters/xlsx-exporter.js +309 -0
- package/dist/exporters/xlsx-exporter.js.map +1 -0
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +26 -0
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
- package/dist/orchestrator/ai-rules-updater.js +12 -0
- package/dist/orchestrator/ai-rules-updater.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +12 -1
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +84 -64
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +2 -0
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +15 -17
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +7 -5
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-delivery.md +71 -0
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +27 -0
- package/dist/orchestrator/templates/ai-instructions/claude-config.md +12 -2
- package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-figma.md +142 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +100 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-local.md +73 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-delivery.md +103 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +2 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +22 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -15
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -4
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +71 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +38 -14
- package/dist/orchestrator/templates/ai-instructions/copilot-config.md +12 -2
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-figma.md +142 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +100 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-local.md +73 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +103 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +2 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +22 -0
- package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -1
- package/dist/orchestrator/templates/playwright.config.js +6 -1
- package/dist/orchestrator/templates/playwright.config.js.map +1 -1
- package/dist/orchestrator/templates/playwright.config.ts +6 -1
- package/package.json +2 -1
- package/src/cli/commands/delivery.ts +348 -0
- package/src/cli/commands/update.ts +84 -2
- package/src/cli/index.ts +4 -2
- package/src/exporters/csv-exporter.ts +304 -0
- package/src/exporters/feature-parser.ts +168 -0
- package/src/exporters/package-info.ts +35 -0
- package/src/exporters/playwright-report-parser.ts +168 -0
- package/src/exporters/scenario-merger.ts +63 -0
- package/src/exporters/spec-parser.ts +247 -0
- package/src/exporters/step-formatter.ts +80 -0
- package/src/exporters/test-data-resolver.ts +59 -0
- package/src/exporters/types.ts +112 -0
- package/src/exporters/xlsx-exporter.ts +301 -0
- package/src/generators/test-generator/utils/selector-resolver.ts +26 -0
- package/src/orchestrator/ai-rules-updater.ts +12 -0
- package/src/orchestrator/project-initializer.ts +103 -70
- package/src/orchestrator/screen-manager.ts +2 -0
- package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +15 -17
- package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +7 -5
- package/src/orchestrator/templates/ai-instructions/claude-cmd-delivery.md +71 -0
- package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +27 -0
- package/src/orchestrator/templates/ai-instructions/claude-config.md +12 -2
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture-figma.md +142 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +100 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-capture-local.md +73 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +103 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +2 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +22 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -15
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +6 -4
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +71 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +38 -14
- package/src/orchestrator/templates/ai-instructions/copilot-config.md +12 -2
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-figma.md +142 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +100 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-local.md +73 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +103 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +2 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +22 -0
- package/src/orchestrator/templates/playwright.config.ts +6 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Convert raw Gherkin step text OR generated .spec.ts comment lines into
|
|
4
|
+
* concise, numbered natural language for the CSV Steps/Expected columns.
|
|
5
|
+
*
|
|
6
|
+
* Deterministic — no AI calls.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.formatNumberedSteps = formatNumberedSteps;
|
|
10
|
+
exports.cleanStepLine = cleanStepLine;
|
|
11
|
+
exports.formatPrecondition = formatPrecondition;
|
|
12
|
+
/**
|
|
13
|
+
* Format a list of raw step lines for the Steps / Expected Results columns.
|
|
14
|
+
*
|
|
15
|
+
* - 0 lines → empty string
|
|
16
|
+
* - 1 line → the line verbatim (no "1. " prefix — avoids Google Sheets clutter)
|
|
17
|
+
* - ≥ 2 → each line on its own row, "1. ", "2. ", … prefixes, newline-joined
|
|
18
|
+
* so spreadsheet cells auto-wrap one step per visual line.
|
|
19
|
+
*/
|
|
20
|
+
function formatNumberedSteps(lines) {
|
|
21
|
+
const cleaned = lines.map(cleanStepLine).filter((l) => l.length > 0);
|
|
22
|
+
if (cleaned.length === 0)
|
|
23
|
+
return '';
|
|
24
|
+
if (cleaned.length === 1)
|
|
25
|
+
return cleaned[0];
|
|
26
|
+
return cleaned.map((line, idx) => `${idx + 1}. ${line}`).join('\n');
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Clean a raw step line (either Gherkin text or .spec.ts comment).
|
|
30
|
+
*
|
|
31
|
+
* Handles patterns like:
|
|
32
|
+
* "User click [login] button" → "Click 'login' button"
|
|
33
|
+
* "User fill [Email] field with {{email}}" → "Fill 'Email' field with {{email}}"
|
|
34
|
+
* "Click Signature 2025 Creator" → "Click 'Signature 2025 Creator'"
|
|
35
|
+
* "Assert title error has text err_xxx" → "Title error has text err_xxx"
|
|
36
|
+
* "Open awards page" → "Open awards page"
|
|
37
|
+
*/
|
|
38
|
+
function cleanStepLine(raw) {
|
|
39
|
+
let s = raw.trim();
|
|
40
|
+
// Strip leading "User " actor
|
|
41
|
+
s = s.replace(/^User\s+/i, '');
|
|
42
|
+
// Strip Gherkin-style element decoration "[Ref] type" → "'Ref' type"
|
|
43
|
+
// e.g., "click [Login] button" → "click 'Login' button"
|
|
44
|
+
s = s.replace(/\[([^\]]+)\]/g, "'$1'");
|
|
45
|
+
// Collapse multiple spaces
|
|
46
|
+
s = s.replace(/\s+/g, ' ');
|
|
47
|
+
// For .spec.ts comments that start with "Assert ..." keep as-is (they read naturally)
|
|
48
|
+
// For action comments like "Click X", "Fill X with Y" keep as-is.
|
|
49
|
+
// Capitalize first letter
|
|
50
|
+
if (s.length > 0)
|
|
51
|
+
s = s.charAt(0).toUpperCase() + s.slice(1);
|
|
52
|
+
return s;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Natural language for Given → Pre-condition.
|
|
56
|
+
* Combines auth info + Given steps into a single sentence.
|
|
57
|
+
*/
|
|
58
|
+
function formatPrecondition(authRole, givenLines) {
|
|
59
|
+
const parts = [];
|
|
60
|
+
// Auth prefix
|
|
61
|
+
if (authRole === 'no-auth') {
|
|
62
|
+
parts.push('Not authenticated.');
|
|
63
|
+
}
|
|
64
|
+
else if (authRole) {
|
|
65
|
+
parts.push(`Logged in as ${authRole}.`);
|
|
66
|
+
}
|
|
67
|
+
// Given lines (clean + period-separated)
|
|
68
|
+
for (const line of givenLines) {
|
|
69
|
+
const cleaned = cleanStepLine(line);
|
|
70
|
+
if (!cleaned)
|
|
71
|
+
continue;
|
|
72
|
+
parts.push(cleaned.endsWith('.') ? cleaned : cleaned + '.');
|
|
73
|
+
}
|
|
74
|
+
return parts.join(' ').trim();
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=step-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-formatter.js","sourceRoot":"","sources":["../../src/exporters/step-formatter.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAUH,kDAKC;AAYD,sCAoBC;AAMD,gDAqBC;AAxED;;;;;;;GAOG;AACH,SAAgB,mBAAmB,CAAC,KAAe;IACjD,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACrE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAEnB,8BAA8B;IAC9B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAE/B,qEAAqE;IACrE,wDAAwD;IACxD,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAEvC,2BAA2B;IAC3B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE3B,sFAAsF;IACtF,kEAAkE;IAElE,0BAA0B;IAC1B,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE7D,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,SAAgB,kBAAkB,CAChC,QAAuB,EACvB,UAAoB;IAEpB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,cAAc;IACd,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACnC,CAAC;SAAM,IAAI,QAAQ,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,gBAAgB,QAAQ,GAAG,CAAC,CAAC;IAC1C,CAAC;IAED,yCAAyC;IACzC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve test-data.yaml variables for the CSV Test Data column.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Load test-data.yaml into a flat key→value map.
|
|
6
|
+
* Returns empty map if file missing.
|
|
7
|
+
*/
|
|
8
|
+
export declare function loadTestData(testDataFilePath: string): Record<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Format a list of variable references into a "key: value; key2: value2" string
|
|
11
|
+
* suitable for the CSV Test Data column.
|
|
12
|
+
*
|
|
13
|
+
* Long values (>80 chars) are truncated with "…".
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatTestData(referencedVars: string[], testData: Record<string, string>): string;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the test-data file path for a given screen.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveTestDataPath(cwd: string, screen: string): string;
|
|
20
|
+
//# sourceMappingURL=test-data-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-data-resolver.d.ts","sourceRoot":"","sources":["../../src/exporters/test-data-resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;;GAGG;AACH,wBAAgB,YAAY,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAc7E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,MAAM,EAAE,EACxB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,MAAM,CASR;AAOD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvE"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve test-data.yaml variables for the CSV Test Data column.
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.loadTestData = loadTestData;
|
|
40
|
+
exports.formatTestData = formatTestData;
|
|
41
|
+
exports.resolveTestDataPath = resolveTestDataPath;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const yaml_1 = require("yaml");
|
|
45
|
+
/**
|
|
46
|
+
* Load test-data.yaml into a flat key→value map.
|
|
47
|
+
* Returns empty map if file missing.
|
|
48
|
+
*/
|
|
49
|
+
function loadTestData(testDataFilePath) {
|
|
50
|
+
if (!fs.existsSync(testDataFilePath))
|
|
51
|
+
return {};
|
|
52
|
+
const content = fs.readFileSync(testDataFilePath, 'utf-8');
|
|
53
|
+
const parsed = (0, yaml_1.parse)(content);
|
|
54
|
+
if (!parsed || typeof parsed !== 'object')
|
|
55
|
+
return {};
|
|
56
|
+
// Flatten shallow object to string values
|
|
57
|
+
const result = {};
|
|
58
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
59
|
+
if (value === null || value === undefined)
|
|
60
|
+
continue;
|
|
61
|
+
if (typeof value === 'object')
|
|
62
|
+
continue; // skip nested structures
|
|
63
|
+
result[key] = String(value);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Format a list of variable references into a "key: value; key2: value2" string
|
|
69
|
+
* suitable for the CSV Test Data column.
|
|
70
|
+
*
|
|
71
|
+
* Long values (>80 chars) are truncated with "…".
|
|
72
|
+
*/
|
|
73
|
+
function formatTestData(referencedVars, testData) {
|
|
74
|
+
if (referencedVars.length === 0)
|
|
75
|
+
return '';
|
|
76
|
+
const pairs = [];
|
|
77
|
+
for (const key of referencedVars) {
|
|
78
|
+
const value = testData[key];
|
|
79
|
+
if (value === undefined)
|
|
80
|
+
continue;
|
|
81
|
+
pairs.push(`${key}: ${truncate(value, 80)}`);
|
|
82
|
+
}
|
|
83
|
+
return pairs.join('; ');
|
|
84
|
+
}
|
|
85
|
+
function truncate(s, max) {
|
|
86
|
+
if (s.length <= max)
|
|
87
|
+
return s;
|
|
88
|
+
return s.substring(0, max - 1) + '…';
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Resolve the test-data file path for a given screen.
|
|
92
|
+
*/
|
|
93
|
+
function resolveTestDataPath(cwd, screen) {
|
|
94
|
+
return path.join(cwd, 'qa', 'screens', screen, 'test-data', `${screen}.yaml`);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=test-data-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-data-resolver.js","sourceRoot":"","sources":["../../src/exporters/test-data-resolver.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUH,oCAcC;AAQD,wCAYC;AAUD,kDAEC;AAtDD,uCAAyB;AACzB,2CAA6B;AAC7B,+BAA0C;AAE1C;;;GAGG;AACH,SAAgB,YAAY,CAAC,gBAAwB;IACnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,IAAA,YAAS,EAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAErD,0CAA0C;IAC1C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,EAAE,CAAC;QAC7E,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS,CAAC,yBAAyB;QAClE,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAC5B,cAAwB,EACxB,QAAgC;IAEhC,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,QAAQ,CAAC,CAAS,EAAE,GAAW;IACtC,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CAAC,GAAW,EAAE,MAAc;IAC7D,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the delivery exporter.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Test case row in the final CSV output.
|
|
6
|
+
*/
|
|
7
|
+
export interface TestCaseRow {
|
|
8
|
+
tcId: string;
|
|
9
|
+
category1: string;
|
|
10
|
+
category2: string;
|
|
11
|
+
category3: string;
|
|
12
|
+
category4: string;
|
|
13
|
+
precondition: string;
|
|
14
|
+
testData: string;
|
|
15
|
+
steps: string;
|
|
16
|
+
expectedResults: string;
|
|
17
|
+
priority: string;
|
|
18
|
+
testcaseType: string;
|
|
19
|
+
testResult: string;
|
|
20
|
+
executedDate: string;
|
|
21
|
+
testExecutor: string;
|
|
22
|
+
testEnvironment: string;
|
|
23
|
+
note: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Summary stats per screen.
|
|
27
|
+
*/
|
|
28
|
+
export interface ScreenSummary {
|
|
29
|
+
screen: string;
|
|
30
|
+
total: number;
|
|
31
|
+
passed: number;
|
|
32
|
+
failed: number;
|
|
33
|
+
pending: number;
|
|
34
|
+
na: number;
|
|
35
|
+
notCompiled: number;
|
|
36
|
+
outputFile: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Pre-flight check result for a single screen.
|
|
40
|
+
*/
|
|
41
|
+
export interface PreflightCheck {
|
|
42
|
+
screen: string;
|
|
43
|
+
featureOk: boolean;
|
|
44
|
+
testDataOk: boolean;
|
|
45
|
+
selectorsOk: boolean;
|
|
46
|
+
specOk: boolean;
|
|
47
|
+
resultsOk: boolean;
|
|
48
|
+
missing: string[];
|
|
49
|
+
suggestions: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Metadata extracted from a .feature file.
|
|
53
|
+
*/
|
|
54
|
+
export interface FeatureMetadata {
|
|
55
|
+
featureName: string;
|
|
56
|
+
featurePath?: string;
|
|
57
|
+
featureTags: string[];
|
|
58
|
+
scenarios: ScenarioMetadata[];
|
|
59
|
+
}
|
|
60
|
+
export interface ScenarioMetadata {
|
|
61
|
+
name: string;
|
|
62
|
+
tags: string[];
|
|
63
|
+
stepsName?: string;
|
|
64
|
+
extendsName?: string;
|
|
65
|
+
referencedVars: string[];
|
|
66
|
+
rawGivenSteps: string[];
|
|
67
|
+
rawWhenSteps: string[];
|
|
68
|
+
rawThenSteps: string[];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Structure extracted from a compiled .spec.ts test block.
|
|
72
|
+
*/
|
|
73
|
+
export interface SpecTest {
|
|
74
|
+
describeName: string;
|
|
75
|
+
authRole?: string;
|
|
76
|
+
testTitle: string;
|
|
77
|
+
scenarioName: string;
|
|
78
|
+
vpId?: string;
|
|
79
|
+
precondition: string[];
|
|
80
|
+
steps: string[];
|
|
81
|
+
expectations: string[];
|
|
82
|
+
}
|
|
83
|
+
export interface SpecFileData {
|
|
84
|
+
tests: SpecTest[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Result from results.json per test.
|
|
88
|
+
*/
|
|
89
|
+
export interface PlaywrightResult {
|
|
90
|
+
testTitle: string;
|
|
91
|
+
status: 'passed' | 'failed' | 'skipped' | 'timedOut' | 'interrupted' | 'unknown';
|
|
92
|
+
startTime?: string;
|
|
93
|
+
error?: string;
|
|
94
|
+
tracePath?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Environment metadata.
|
|
98
|
+
*/
|
|
99
|
+
export interface EnvironmentInfo {
|
|
100
|
+
baseURL: string;
|
|
101
|
+
projectName: string;
|
|
102
|
+
executor: string;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/exporters/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/exporters/types.ts"],"names":[],"mappings":";AAAA;;GAEG"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render the same rows/summary the CSV exporter produces into a styled .xlsx
|
|
3
|
+
* workbook. Keeps the BM-2-901-13 layout but adds:
|
|
4
|
+
* - bold header row with filled background + white font
|
|
5
|
+
* - borders on the data region
|
|
6
|
+
* - text wrapping in Steps / Expected / Pre-condition / Test Data
|
|
7
|
+
* - frozen header so the first data rows stay aligned with the title row
|
|
8
|
+
* - sensible column widths
|
|
9
|
+
* - category-separator rows rendered as a filled bar spanning the table
|
|
10
|
+
*/
|
|
11
|
+
import ExcelJS from 'exceljs';
|
|
12
|
+
import { ScreenSummary, TestCaseRow } from './types';
|
|
13
|
+
export declare function renderXlsx(summary: ScreenSummary, rows: TestCaseRow[], specLink: string): ExcelJS.Workbook;
|
|
14
|
+
/**
|
|
15
|
+
* Write the workbook to `qa/deliverables/<screen>-testcases.xlsx`.
|
|
16
|
+
* Directory is created on demand. Returns the absolute output path.
|
|
17
|
+
*/
|
|
18
|
+
export declare function writeXlsx(cwd: string, screen: string, wb: ExcelJS.Workbook): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=xlsx-exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xlsx-exporter.d.ts","sourceRoot":"","sources":["../../src/exporters/xlsx-exporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAsBrD,wBAAgB,UAAU,CACxB,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,WAAW,EAAE,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,CAiPlB;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,OAAO,CAAC,QAAQ,GACnB,OAAO,CAAC,MAAM,CAAC,CAMjB"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Render the same rows/summary the CSV exporter produces into a styled .xlsx
|
|
4
|
+
* workbook. Keeps the BM-2-901-13 layout but adds:
|
|
5
|
+
* - bold header row with filled background + white font
|
|
6
|
+
* - borders on the data region
|
|
7
|
+
* - text wrapping in Steps / Expected / Pre-condition / Test Data
|
|
8
|
+
* - frozen header so the first data rows stay aligned with the title row
|
|
9
|
+
* - sensible column widths
|
|
10
|
+
* - category-separator rows rendered as a filled bar spanning the table
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.renderXlsx = renderXlsx;
|
|
50
|
+
exports.writeXlsx = writeXlsx;
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const exceljs_1 = __importDefault(require("exceljs"));
|
|
54
|
+
const package_info_1 = require("./package-info");
|
|
55
|
+
const COL_COUNT = 16;
|
|
56
|
+
const HEADER_FILL = 'FF1F4E78'; // deep blue band
|
|
57
|
+
const HEADER_FONT = 'FFFFFFFF';
|
|
58
|
+
const META_FILL = 'FFDCE6F1'; // soft blue for meta rows
|
|
59
|
+
const CATEGORY_FILL = 'FFFFF2CC'; // soft yellow for group dividers
|
|
60
|
+
const BORDER_COLOR = 'FFBFBFBF';
|
|
61
|
+
function applyBorder(cell) {
|
|
62
|
+
cell.border = {
|
|
63
|
+
top: { style: 'thin', color: { argb: BORDER_COLOR } },
|
|
64
|
+
left: { style: 'thin', color: { argb: BORDER_COLOR } },
|
|
65
|
+
bottom: { style: 'thin', color: { argb: BORDER_COLOR } },
|
|
66
|
+
right: { style: 'thin', color: { argb: BORDER_COLOR } },
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function renderXlsx(summary, rows, specLink) {
|
|
70
|
+
const wb = new exceljs_1.default.Workbook();
|
|
71
|
+
wb.creator = 'sungen delivery';
|
|
72
|
+
wb.created = new Date();
|
|
73
|
+
const ws = wb.addWorksheet('Testcases', {
|
|
74
|
+
views: [{ state: 'frozen', ySplit: 0, xSplit: 0 }],
|
|
75
|
+
});
|
|
76
|
+
const issueDate = (() => {
|
|
77
|
+
const d = new Date();
|
|
78
|
+
return `${String(d.getDate()).padStart(2, '0')}/${String(d.getMonth() + 1).padStart(2, '0')}/${d.getFullYear()}`;
|
|
79
|
+
})();
|
|
80
|
+
const total = summary.total || 1;
|
|
81
|
+
const pct = (n) => `${Math.round((n / total) * 100)}%`;
|
|
82
|
+
// -- Column widths (matches CSV column order) --
|
|
83
|
+
ws.columns = [
|
|
84
|
+
{ width: 18 }, // TC ID
|
|
85
|
+
{ width: 42 }, // Category 1
|
|
86
|
+
{ width: 14 }, // Category 2
|
|
87
|
+
{ width: 26 }, // Category 3
|
|
88
|
+
{ width: 14 }, // Category 4
|
|
89
|
+
{ width: 36 }, // Pre-condition
|
|
90
|
+
{ width: 30 }, // Test Data
|
|
91
|
+
{ width: 46 }, // Steps
|
|
92
|
+
{ width: 52 }, // Expected results
|
|
93
|
+
{ width: 10 }, // Priority
|
|
94
|
+
{ width: 14 }, // Testcase type
|
|
95
|
+
{ width: 14 }, // Test Result
|
|
96
|
+
{ width: 14 }, // Executed Date
|
|
97
|
+
{ width: 16 }, // Test Executor
|
|
98
|
+
{ width: 38 }, // Test Environment
|
|
99
|
+
{ width: 40 }, // Note
|
|
100
|
+
];
|
|
101
|
+
// -- Top metadata band (rows 1-4) --
|
|
102
|
+
const titleLabel = `${summary.screen.toUpperCase()} TESTCASE`;
|
|
103
|
+
const titleRow = ws.addRow(['', '', '', titleLabel, '', '', 'No: BM-2-901-13']);
|
|
104
|
+
titleRow.getCell(4).font = { bold: true, size: 16 };
|
|
105
|
+
titleRow.getCell(4).alignment = { horizontal: 'center', vertical: 'middle' };
|
|
106
|
+
ws.mergeCells(titleRow.number, 4, titleRow.number, 6);
|
|
107
|
+
titleRow.getCell(7).font = { bold: true };
|
|
108
|
+
titleRow.height = 22;
|
|
109
|
+
const versionRow = ws.addRow(['', '', '', '', '', '', `Version: ${(0, package_info_1.getPackageVersion)()}`]);
|
|
110
|
+
versionRow.getCell(7).font = { bold: true };
|
|
111
|
+
const dateRow = ws.addRow(['', '', '', '', '', '', `Issue Date: ${issueDate}`]);
|
|
112
|
+
dateRow.getCell(7).font = { bold: true };
|
|
113
|
+
const companyRow = ws.addRow([
|
|
114
|
+
'SUN ASTERISK VIETNAM CO., LTD',
|
|
115
|
+
'',
|
|
116
|
+
'',
|
|
117
|
+
'',
|
|
118
|
+
'',
|
|
119
|
+
'',
|
|
120
|
+
'ISO/IEC 27001:2022 & ISO 9001:2015',
|
|
121
|
+
]);
|
|
122
|
+
companyRow.getCell(1).font = { bold: true };
|
|
123
|
+
companyRow.getCell(7).font = { bold: true };
|
|
124
|
+
ws.addRow([]); // spacer
|
|
125
|
+
// -- Summary band --
|
|
126
|
+
const summaryHeader = ws.addRow([
|
|
127
|
+
'',
|
|
128
|
+
'',
|
|
129
|
+
'Total TCs',
|
|
130
|
+
'Passed',
|
|
131
|
+
'Failed',
|
|
132
|
+
'Pending',
|
|
133
|
+
'N/A',
|
|
134
|
+
'Remaining',
|
|
135
|
+
]);
|
|
136
|
+
for (let i = 3; i <= 8; i++) {
|
|
137
|
+
const c = summaryHeader.getCell(i);
|
|
138
|
+
c.font = { bold: true, color: { argb: HEADER_FONT } };
|
|
139
|
+
c.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: HEADER_FILL } };
|
|
140
|
+
c.alignment = { horizontal: 'center', vertical: 'middle' };
|
|
141
|
+
applyBorder(c);
|
|
142
|
+
}
|
|
143
|
+
const summaryCounts = ws.addRow([
|
|
144
|
+
'',
|
|
145
|
+
'',
|
|
146
|
+
summary.total,
|
|
147
|
+
summary.passed,
|
|
148
|
+
summary.failed,
|
|
149
|
+
summary.pending,
|
|
150
|
+
summary.na,
|
|
151
|
+
summary.pending + summary.na,
|
|
152
|
+
]);
|
|
153
|
+
for (let i = 3; i <= 8; i++) {
|
|
154
|
+
const c = summaryCounts.getCell(i);
|
|
155
|
+
c.font = { bold: true };
|
|
156
|
+
c.alignment = { horizontal: 'center' };
|
|
157
|
+
c.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: META_FILL } };
|
|
158
|
+
applyBorder(c);
|
|
159
|
+
}
|
|
160
|
+
const summaryPct = ws.addRow([
|
|
161
|
+
'',
|
|
162
|
+
'',
|
|
163
|
+
'',
|
|
164
|
+
pct(summary.passed),
|
|
165
|
+
pct(summary.failed),
|
|
166
|
+
pct(summary.pending),
|
|
167
|
+
pct(summary.na),
|
|
168
|
+
pct(summary.pending + summary.na),
|
|
169
|
+
]);
|
|
170
|
+
for (let i = 4; i <= 8; i++) {
|
|
171
|
+
const c = summaryPct.getCell(i);
|
|
172
|
+
c.alignment = { horizontal: 'center' };
|
|
173
|
+
c.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: META_FILL } };
|
|
174
|
+
applyBorder(c);
|
|
175
|
+
}
|
|
176
|
+
ws.addRow([]); // spacer
|
|
177
|
+
const specRow = ws.addRow(['Spec/Design link:', specLink]);
|
|
178
|
+
specRow.getCell(1).font = { bold: true };
|
|
179
|
+
specRow.getCell(2).font = { color: { argb: 'FF1F4E78' }, underline: true };
|
|
180
|
+
ws.addRow([]); // spacer
|
|
181
|
+
const legendRow = ws.addRow(['*: Mandatory']);
|
|
182
|
+
legendRow.getCell(1).font = { italic: true, color: { argb: 'FF808080' } };
|
|
183
|
+
// -- Column header row (bold, filled, wrapped) --
|
|
184
|
+
const headerRow = ws.addRow([
|
|
185
|
+
'TC ID*',
|
|
186
|
+
'{Category 1}',
|
|
187
|
+
'{Category 2}',
|
|
188
|
+
'{Category 3}',
|
|
189
|
+
'{Category 4}',
|
|
190
|
+
'Pre-condition',
|
|
191
|
+
'Test Data',
|
|
192
|
+
'Steps*',
|
|
193
|
+
'Expected results*',
|
|
194
|
+
'Priority',
|
|
195
|
+
'Testcase type',
|
|
196
|
+
'Test Result*',
|
|
197
|
+
'Executed Date*',
|
|
198
|
+
'Test Executor*',
|
|
199
|
+
'Test Environment',
|
|
200
|
+
'Note\n(Test evidence, DefectID, Actual result)',
|
|
201
|
+
]);
|
|
202
|
+
headerRow.height = 38;
|
|
203
|
+
headerRow.eachCell((cell) => {
|
|
204
|
+
cell.font = { bold: true, color: { argb: HEADER_FONT } };
|
|
205
|
+
cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: HEADER_FILL } };
|
|
206
|
+
cell.alignment = { horizontal: 'center', vertical: 'middle', wrapText: true };
|
|
207
|
+
applyBorder(cell);
|
|
208
|
+
});
|
|
209
|
+
// Freeze everything above and below the header row — reveal header when scrolling.
|
|
210
|
+
ws.views = [{ state: 'frozen', ySplit: headerRow.number }];
|
|
211
|
+
// -- Data rows grouped by category --
|
|
212
|
+
const order = ['Accessing', 'GUI', 'Function'];
|
|
213
|
+
const grouped = new Map();
|
|
214
|
+
for (const r of rows) {
|
|
215
|
+
const g = grouped.get(r.category2) || [];
|
|
216
|
+
g.push(r);
|
|
217
|
+
grouped.set(r.category2, g);
|
|
218
|
+
}
|
|
219
|
+
const emittedGroups = new Set();
|
|
220
|
+
function emitGroup(groupName, groupRows) {
|
|
221
|
+
const divider = ws.addRow(['', groupName]);
|
|
222
|
+
divider.getCell(2).font = { bold: true };
|
|
223
|
+
divider.eachCell({ includeEmpty: false }, (cell) => {
|
|
224
|
+
cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: CATEGORY_FILL } };
|
|
225
|
+
});
|
|
226
|
+
// Fill the full width so the band spans the whole table
|
|
227
|
+
for (let i = 1; i <= COL_COUNT; i++) {
|
|
228
|
+
const c = divider.getCell(i);
|
|
229
|
+
c.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: CATEGORY_FILL } };
|
|
230
|
+
applyBorder(c);
|
|
231
|
+
}
|
|
232
|
+
for (const r of groupRows) {
|
|
233
|
+
const row = ws.addRow([
|
|
234
|
+
r.tcId,
|
|
235
|
+
r.category1,
|
|
236
|
+
'',
|
|
237
|
+
'',
|
|
238
|
+
'',
|
|
239
|
+
r.precondition,
|
|
240
|
+
r.testData,
|
|
241
|
+
r.steps,
|
|
242
|
+
r.expectedResults,
|
|
243
|
+
r.priority,
|
|
244
|
+
r.testcaseType,
|
|
245
|
+
r.testResult,
|
|
246
|
+
r.executedDate,
|
|
247
|
+
r.testExecutor,
|
|
248
|
+
r.testEnvironment,
|
|
249
|
+
r.note,
|
|
250
|
+
]);
|
|
251
|
+
row.alignment = { vertical: 'top', wrapText: true };
|
|
252
|
+
row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
253
|
+
applyBorder(cell);
|
|
254
|
+
if (colNumber === 1) {
|
|
255
|
+
cell.font = { bold: true };
|
|
256
|
+
}
|
|
257
|
+
if (colNumber === 12) {
|
|
258
|
+
// Test Result — colour-code
|
|
259
|
+
const val = String(cell.value || '');
|
|
260
|
+
if (val === 'Passed') {
|
|
261
|
+
cell.font = { color: { argb: 'FF107C41' }, bold: true };
|
|
262
|
+
}
|
|
263
|
+
else if (val === 'Failed') {
|
|
264
|
+
cell.font = { color: { argb: 'FFC00000' }, bold: true };
|
|
265
|
+
}
|
|
266
|
+
else if (val === 'Pending') {
|
|
267
|
+
cell.font = { color: { argb: 'FF996D00' }, bold: true };
|
|
268
|
+
}
|
|
269
|
+
else if (val === 'N/A') {
|
|
270
|
+
cell.font = { color: { argb: 'FF808080' } };
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
for (const groupName of order) {
|
|
277
|
+
const groupRows = grouped.get(groupName);
|
|
278
|
+
if (!groupRows || groupRows.length === 0)
|
|
279
|
+
continue;
|
|
280
|
+
emittedGroups.add(groupName);
|
|
281
|
+
emitGroup(groupName, groupRows);
|
|
282
|
+
}
|
|
283
|
+
for (const [groupName, groupRows] of grouped.entries()) {
|
|
284
|
+
if (emittedGroups.has(groupName))
|
|
285
|
+
continue;
|
|
286
|
+
emitGroup(groupName, groupRows);
|
|
287
|
+
}
|
|
288
|
+
// Auto-filter on the header row so QA can filter by result / priority / category
|
|
289
|
+
ws.autoFilter = {
|
|
290
|
+
from: { row: headerRow.number, column: 1 },
|
|
291
|
+
to: { row: ws.rowCount, column: COL_COUNT },
|
|
292
|
+
};
|
|
293
|
+
return wb;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Write the workbook to `qa/deliverables/<screen>-testcases.xlsx`.
|
|
297
|
+
* Directory is created on demand. Returns the absolute output path.
|
|
298
|
+
*/
|
|
299
|
+
async function writeXlsx(cwd, screen, wb) {
|
|
300
|
+
const outDir = path.join(cwd, 'qa', 'deliverables');
|
|
301
|
+
if (!fs.existsSync(outDir))
|
|
302
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
303
|
+
const outPath = path.join(outDir, `${screen}-testcases.xlsx`);
|
|
304
|
+
await wb.xlsx.writeFile(outPath);
|
|
305
|
+
return outPath;
|
|
306
|
+
}
|
|
307
|
+
void applyBorder;
|
|
308
|
+
void {};
|
|
309
|
+
//# sourceMappingURL=xlsx-exporter.js.map
|