@facet-coverage/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +422 -0
- package/bin/facet-coverage.js +3 -0
- package/dist/cli/commands/analyze.d.ts +13 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +161 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +10 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +67 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +11 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +120 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +10 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +151 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +47 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/CoverageCalculator.d.ts +34 -0
- package/dist/core/CoverageCalculator.d.ts.map +1 -0
- package/dist/core/CoverageCalculator.js +167 -0
- package/dist/core/CoverageCalculator.js.map +1 -0
- package/dist/core/FacetParser.d.ts +39 -0
- package/dist/core/FacetParser.d.ts.map +1 -0
- package/dist/core/FacetParser.js +114 -0
- package/dist/core/FacetParser.js.map +1 -0
- package/dist/core/StructureReader.d.ts +37 -0
- package/dist/core/StructureReader.d.ts.map +1 -0
- package/dist/core/StructureReader.js +126 -0
- package/dist/core/StructureReader.js.map +1 -0
- package/dist/core/TestScanner.d.ts +36 -0
- package/dist/core/TestScanner.d.ts.map +1 -0
- package/dist/core/TestScanner.js +192 -0
- package/dist/core/TestScanner.js.map +1 -0
- package/dist/core/Validator.d.ts +33 -0
- package/dist/core/Validator.d.ts.map +1 -0
- package/dist/core/Validator.js +183 -0
- package/dist/core/Validator.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/playwright.d.ts +95 -0
- package/dist/integrations/playwright.d.ts.map +1 -0
- package/dist/integrations/playwright.js +168 -0
- package/dist/integrations/playwright.js.map +1 -0
- package/dist/reporters/HtmlReporter.d.ts +53 -0
- package/dist/reporters/HtmlReporter.d.ts.map +1 -0
- package/dist/reporters/HtmlReporter.js +484 -0
- package/dist/reporters/HtmlReporter.js.map +1 -0
- package/dist/reporters/JsonReporter.d.ts +21 -0
- package/dist/reporters/JsonReporter.d.ts.map +1 -0
- package/dist/reporters/JsonReporter.js +58 -0
- package/dist/reporters/JsonReporter.js.map +1 -0
- package/dist/reporters/MarkdownReporter.d.ts +25 -0
- package/dist/reporters/MarkdownReporter.d.ts.map +1 -0
- package/dist/reporters/MarkdownReporter.js +141 -0
- package/dist/reporters/MarkdownReporter.js.map +1 -0
- package/dist/reporters/index.d.ts +4 -0
- package/dist/reporters/index.d.ts.map +1 -0
- package/dist/reporters/index.js +10 -0
- package/dist/reporters/index.js.map +1 -0
- package/dist/types.d.ts +205 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Validator = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const types_js_1 = require("../types.js");
|
|
7
|
+
const StructureReader_js_1 = require("./StructureReader.js");
|
|
8
|
+
const FacetParser_js_1 = require("./FacetParser.js");
|
|
9
|
+
const TestScanner_js_1 = require("./TestScanner.js");
|
|
10
|
+
/**
|
|
11
|
+
* Validates facet structures, source files, and test links
|
|
12
|
+
*/
|
|
13
|
+
class Validator {
|
|
14
|
+
config;
|
|
15
|
+
structureReader;
|
|
16
|
+
facetParser;
|
|
17
|
+
testScanner;
|
|
18
|
+
constructor(config = {}) {
|
|
19
|
+
this.config = { ...types_js_1.defaultConfig, ...config };
|
|
20
|
+
this.structureReader = new StructureReader_js_1.StructureReader(this.config);
|
|
21
|
+
this.facetParser = new FacetParser_js_1.FacetParser();
|
|
22
|
+
this.testScanner = new TestScanner_js_1.TestScanner(this.config);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Run full validation
|
|
26
|
+
*/
|
|
27
|
+
async validate(cwd = process.cwd()) {
|
|
28
|
+
const errors = [];
|
|
29
|
+
const warnings = [];
|
|
30
|
+
// Get all structures
|
|
31
|
+
const structures = await this.structureReader.readAllStructures(cwd);
|
|
32
|
+
// Get all test links
|
|
33
|
+
const testLinks = await this.testScanner.scanAllTests(cwd);
|
|
34
|
+
// Collect all facet IDs
|
|
35
|
+
const allFacetIds = new Set();
|
|
36
|
+
const facetIdToStructureFile = new Map();
|
|
37
|
+
for (const [structureFile, structure] of structures) {
|
|
38
|
+
for (const facet of structure.facets) {
|
|
39
|
+
if (allFacetIds.has(facet.id)) {
|
|
40
|
+
errors.push({
|
|
41
|
+
type: 'duplicate-id',
|
|
42
|
+
message: `Duplicate facet ID '${facet.id}' found in multiple structure files`,
|
|
43
|
+
file: structureFile,
|
|
44
|
+
facetId: facet.id,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
allFacetIds.add(facet.id);
|
|
48
|
+
facetIdToStructureFile.set(facet.id, structureFile);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Validate each structure
|
|
52
|
+
for (const [structureFile, structure] of structures) {
|
|
53
|
+
const structureErrors = this.validateStructure(structure, structureFile, cwd);
|
|
54
|
+
errors.push(...structureErrors.errors);
|
|
55
|
+
warnings.push(...structureErrors.warnings);
|
|
56
|
+
}
|
|
57
|
+
// Validate test links
|
|
58
|
+
const referencedIds = new Set();
|
|
59
|
+
for (const link of testLinks) {
|
|
60
|
+
for (const facetId of link.facetIds) {
|
|
61
|
+
referencedIds.add(facetId);
|
|
62
|
+
if (!allFacetIds.has(facetId)) {
|
|
63
|
+
// Check if it's a flexible path reference
|
|
64
|
+
const isValidPathRef = this.isValidPathReference(facetId, structures);
|
|
65
|
+
if (!isValidPathRef) {
|
|
66
|
+
warnings.push({
|
|
67
|
+
type: 'orphan-test',
|
|
68
|
+
message: `Test references unknown facet ID '${facetId}'`,
|
|
69
|
+
file: link.file,
|
|
70
|
+
line: link.line,
|
|
71
|
+
facetId,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Check for uncovered facets (as warnings)
|
|
78
|
+
for (const facetId of allFacetIds) {
|
|
79
|
+
if (!referencedIds.has(facetId)) {
|
|
80
|
+
const structureFile = facetIdToStructureFile.get(facetId);
|
|
81
|
+
warnings.push({
|
|
82
|
+
type: 'orphan-test',
|
|
83
|
+
message: `Facet '${facetId}' is not covered by any test`,
|
|
84
|
+
file: structureFile,
|
|
85
|
+
facetId,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
valid: errors.length === 0,
|
|
91
|
+
errors,
|
|
92
|
+
warnings,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Validate a single structure
|
|
97
|
+
*/
|
|
98
|
+
validateStructure(structure, structureFile, cwd) {
|
|
99
|
+
const errors = [];
|
|
100
|
+
const warnings = [];
|
|
101
|
+
const structureDir = (0, path_1.dirname)(structureFile);
|
|
102
|
+
const featureDir = (0, path_1.dirname)(structureDir);
|
|
103
|
+
for (const facet of structure.facets) {
|
|
104
|
+
// Validate source file exists
|
|
105
|
+
if (this.config.validation.requireSourceExists) {
|
|
106
|
+
const sourcePath = (0, path_1.resolve)(featureDir, facet.source.file);
|
|
107
|
+
if (!(0, fs_1.existsSync)(sourcePath)) {
|
|
108
|
+
errors.push({
|
|
109
|
+
type: 'missing-source',
|
|
110
|
+
message: `Source file not found: ${facet.source.file}`,
|
|
111
|
+
file: structureFile,
|
|
112
|
+
facetId: facet.id,
|
|
113
|
+
});
|
|
114
|
+
continue; // Skip section check if file doesn't exist
|
|
115
|
+
}
|
|
116
|
+
// Validate section exists
|
|
117
|
+
if (this.config.validation.requireSectionExists) {
|
|
118
|
+
const sectionExists = this.facetParser.sectionExists(sourcePath, facet.source.section);
|
|
119
|
+
if (!sectionExists) {
|
|
120
|
+
errors.push({
|
|
121
|
+
type: 'missing-section',
|
|
122
|
+
message: `Section '${facet.source.section}' not found in ${facet.source.file}`,
|
|
123
|
+
file: structureFile,
|
|
124
|
+
facetId: facet.id,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Validate facet ID format
|
|
130
|
+
if (!this.isValidFacetId(facet.id)) {
|
|
131
|
+
warnings.push({
|
|
132
|
+
type: 'invalid-facet-id',
|
|
133
|
+
message: `Facet ID '${facet.id}' uses non-standard format`,
|
|
134
|
+
file: structureFile,
|
|
135
|
+
facetId: facet.id,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
valid: errors.length === 0,
|
|
141
|
+
errors,
|
|
142
|
+
warnings,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if a facet ID is valid
|
|
147
|
+
*/
|
|
148
|
+
isValidFacetId(id) {
|
|
149
|
+
// Allow alphanumeric, hyphens, underscores, and colons
|
|
150
|
+
return /^[a-zA-Z0-9_-]+(:?[a-zA-Z0-9_-]+)*$/.test(id);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if a reference is a valid path-style reference
|
|
154
|
+
* e.g., 'facets/business.md#guest-purchase-flow'
|
|
155
|
+
*/
|
|
156
|
+
isValidPathReference(ref, structures) {
|
|
157
|
+
// Check for path#section format
|
|
158
|
+
const pathMatch = ref.match(/^(.+\.md)#(.+)$/);
|
|
159
|
+
if (!pathMatch) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
const [, filePath, section] = pathMatch;
|
|
163
|
+
// Check if any facet matches this path reference
|
|
164
|
+
for (const structure of structures.values()) {
|
|
165
|
+
for (const facet of structure.facets) {
|
|
166
|
+
if (facet.source.file.endsWith(filePath) &&
|
|
167
|
+
facet.source.section === section) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Quick validation check - returns boolean
|
|
176
|
+
*/
|
|
177
|
+
async isValid(cwd = process.cwd()) {
|
|
178
|
+
const result = await this.validate(cwd);
|
|
179
|
+
return result.valid;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.Validator = Validator;
|
|
183
|
+
//# sourceMappingURL=Validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Validator.js","sourceRoot":"","sources":["../../src/core/Validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { StructureReader } from './StructureReader.js';
|
|
2
|
+
export { FacetParser } from './FacetParser.js';
|
|
3
|
+
export { TestScanner } from './TestScanner.js';
|
|
4
|
+
export { Validator } from './Validator.js';
|
|
5
|
+
export { CoverageCalculator } from './CoverageCalculator.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CoverageCalculator = exports.Validator = exports.TestScanner = exports.FacetParser = exports.StructureReader = void 0;
|
|
4
|
+
var StructureReader_js_1 = require("./StructureReader.js");
|
|
5
|
+
Object.defineProperty(exports, "StructureReader", { enumerable: true, get: function () { return StructureReader_js_1.StructureReader; } });
|
|
6
|
+
var FacetParser_js_1 = require("./FacetParser.js");
|
|
7
|
+
Object.defineProperty(exports, "FacetParser", { enumerable: true, get: function () { return FacetParser_js_1.FacetParser; } });
|
|
8
|
+
var TestScanner_js_1 = require("./TestScanner.js");
|
|
9
|
+
Object.defineProperty(exports, "TestScanner", { enumerable: true, get: function () { return TestScanner_js_1.TestScanner; } });
|
|
10
|
+
var Validator_js_1 = require("./Validator.js");
|
|
11
|
+
Object.defineProperty(exports, "Validator", { enumerable: true, get: function () { return Validator_js_1.Validator; } });
|
|
12
|
+
var CoverageCalculator_js_1 = require("./CoverageCalculator.js");
|
|
13
|
+
Object.defineProperty(exports, "CoverageCalculator", { enumerable: true, get: function () { return CoverageCalculator_js_1.CoverageCalculator; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;AAAA,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,mDAA+C;AAAtC,6GAAA,WAAW,OAAA;AACpB,mDAA+C;AAAtC,6GAAA,WAAW,OAAA;AACpB,+CAA2C;AAAlC,yGAAA,SAAS,OAAA;AAClB,iEAA6D;AAApD,2HAAA,kBAAkB,OAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { StructureReader, FacetParser, TestScanner, Validator, CoverageCalculator, } from './core/index.js';
|
|
2
|
+
export { JsonReporter, HtmlReporter, MarkdownReporter, } from './reporters/index.js';
|
|
3
|
+
export { facet, FacetCoverageReporter, createFacetFixture, } from './integrations/playwright.js';
|
|
4
|
+
export type { Facet, FacetStructure, TestLink, FacetCoverage, TypeCoverage, FeatureCoverage, CoverageReport, ValidationError, ValidationResult, FacetConfig, MarkdownSection, ParsedMarkdown, } from './types.js';
|
|
5
|
+
export { defaultConfig } from './types.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,WAAW,EACX,WAAW,EACX,SAAS,EACT,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,KAAK,EACL,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,8BAA8B,CAAC;AAGtC,YAAY,EACV,KAAK,EACL,cAAc,EACd,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultConfig = exports.createFacetFixture = exports.FacetCoverageReporter = exports.facet = exports.MarkdownReporter = exports.HtmlReporter = exports.JsonReporter = exports.CoverageCalculator = exports.Validator = exports.TestScanner = exports.FacetParser = exports.StructureReader = void 0;
|
|
4
|
+
// Core exports
|
|
5
|
+
var index_js_1 = require("./core/index.js");
|
|
6
|
+
Object.defineProperty(exports, "StructureReader", { enumerable: true, get: function () { return index_js_1.StructureReader; } });
|
|
7
|
+
Object.defineProperty(exports, "FacetParser", { enumerable: true, get: function () { return index_js_1.FacetParser; } });
|
|
8
|
+
Object.defineProperty(exports, "TestScanner", { enumerable: true, get: function () { return index_js_1.TestScanner; } });
|
|
9
|
+
Object.defineProperty(exports, "Validator", { enumerable: true, get: function () { return index_js_1.Validator; } });
|
|
10
|
+
Object.defineProperty(exports, "CoverageCalculator", { enumerable: true, get: function () { return index_js_1.CoverageCalculator; } });
|
|
11
|
+
// Reporter exports
|
|
12
|
+
var index_js_2 = require("./reporters/index.js");
|
|
13
|
+
Object.defineProperty(exports, "JsonReporter", { enumerable: true, get: function () { return index_js_2.JsonReporter; } });
|
|
14
|
+
Object.defineProperty(exports, "HtmlReporter", { enumerable: true, get: function () { return index_js_2.HtmlReporter; } });
|
|
15
|
+
Object.defineProperty(exports, "MarkdownReporter", { enumerable: true, get: function () { return index_js_2.MarkdownReporter; } });
|
|
16
|
+
// Playwright integration exports (re-export for convenience)
|
|
17
|
+
var playwright_js_1 = require("./integrations/playwright.js");
|
|
18
|
+
Object.defineProperty(exports, "facet", { enumerable: true, get: function () { return playwright_js_1.facet; } });
|
|
19
|
+
Object.defineProperty(exports, "FacetCoverageReporter", { enumerable: true, get: function () { return playwright_js_1.FacetCoverageReporter; } });
|
|
20
|
+
Object.defineProperty(exports, "createFacetFixture", { enumerable: true, get: function () { return playwright_js_1.createFacetFixture; } });
|
|
21
|
+
var types_js_1 = require("./types.js");
|
|
22
|
+
Object.defineProperty(exports, "defaultConfig", { enumerable: true, get: function () { return types_js_1.defaultConfig; } });
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,eAAe;AACf,4CAMyB;AALvB,2GAAA,eAAe,OAAA;AACf,uGAAA,WAAW,OAAA;AACX,uGAAA,WAAW,OAAA;AACX,qGAAA,SAAS,OAAA;AACT,8GAAA,kBAAkB,OAAA;AAGpB,mBAAmB;AACnB,iDAI8B;AAH5B,wGAAA,YAAY,OAAA;AACZ,wGAAA,YAAY,OAAA;AACZ,4GAAA,gBAAgB,OAAA;AAGlB,6DAA6D;AAC7D,8DAIsC;AAHpC,sGAAA,KAAK,OAAA;AACL,sHAAA,qBAAqB,OAAA;AACrB,mHAAA,kBAAkB,OAAA;AAmBpB,uCAA2C;AAAlC,yGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { FacetConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Helper function to link tests to facets
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* test('my test', {
|
|
7
|
+
* annotation: facet('guest-checkout-flow', 'pci-card-masking')
|
|
8
|
+
* }, async ({ page }) => {
|
|
9
|
+
* // test code
|
|
10
|
+
* });
|
|
11
|
+
*/
|
|
12
|
+
export declare function facet(...facetIds: string[]): {
|
|
13
|
+
type: string;
|
|
14
|
+
description: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Type for Playwright test annotations
|
|
18
|
+
*/
|
|
19
|
+
export interface FacetAnnotation {
|
|
20
|
+
type: 'facet-coverage';
|
|
21
|
+
description: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Playwright reporter interface (minimal type to avoid direct dependency)
|
|
25
|
+
*/
|
|
26
|
+
interface PlaywrightTestCase {
|
|
27
|
+
title: string;
|
|
28
|
+
titlePath(): string[];
|
|
29
|
+
location: {
|
|
30
|
+
file: string;
|
|
31
|
+
line: number;
|
|
32
|
+
};
|
|
33
|
+
annotations: Array<{
|
|
34
|
+
type: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
interface PlaywrightTestResult {
|
|
39
|
+
status: 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted';
|
|
40
|
+
}
|
|
41
|
+
interface PlaywrightFullResult {
|
|
42
|
+
status: 'passed' | 'failed' | 'timedOut' | 'interrupted';
|
|
43
|
+
}
|
|
44
|
+
interface PlaywrightFullConfig {
|
|
45
|
+
rootDir: string;
|
|
46
|
+
}
|
|
47
|
+
interface PlaywrightSuite {
|
|
48
|
+
title: string;
|
|
49
|
+
suites: PlaywrightSuite[];
|
|
50
|
+
tests: PlaywrightTestCase[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Playwright reporter for Facet coverage
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // playwright.config.ts
|
|
57
|
+
* import { FacetCoverageReporter } from 'facet-coverage/playwright';
|
|
58
|
+
*
|
|
59
|
+
* export default {
|
|
60
|
+
* reporter: [
|
|
61
|
+
* ['html'],
|
|
62
|
+
* [FacetCoverageReporter]
|
|
63
|
+
* ]
|
|
64
|
+
* };
|
|
65
|
+
*/
|
|
66
|
+
export declare class FacetCoverageReporter {
|
|
67
|
+
private config;
|
|
68
|
+
private testLinks;
|
|
69
|
+
private rootDir;
|
|
70
|
+
constructor(options?: Partial<FacetConfig>);
|
|
71
|
+
onBegin(config: PlaywrightFullConfig, suite: PlaywrightSuite): void;
|
|
72
|
+
onTestEnd(test: PlaywrightTestCase, result: PlaywrightTestResult): void;
|
|
73
|
+
onEnd(result: PlaywrightFullResult): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Calculate coverage using collected test links
|
|
76
|
+
*/
|
|
77
|
+
private calculateCoverageWithLinks;
|
|
78
|
+
/**
|
|
79
|
+
* Generate all configured report formats
|
|
80
|
+
*/
|
|
81
|
+
private generateReports;
|
|
82
|
+
/**
|
|
83
|
+
* Print coverage summary to console
|
|
84
|
+
*/
|
|
85
|
+
private printSummary;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Create a facet coverage fixture for Playwright
|
|
89
|
+
*/
|
|
90
|
+
export declare function createFacetFixture(): {
|
|
91
|
+
facet: typeof facet;
|
|
92
|
+
FacetCoverageReporter: typeof FacetCoverageReporter;
|
|
93
|
+
};
|
|
94
|
+
export {};
|
|
95
|
+
//# sourceMappingURL=playwright.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.d.ts","sourceRoot":"","sources":["../../src/integrations/playwright.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAA4B,MAAM,aAAa,CAAC;AAOzE;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAKlF;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,gBAAgB,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,UAAU,kBAAkB;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,IAAI,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,UAAU,oBAAoB;IAC5B,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;CACtE;AAED,UAAU,oBAAoB;IAC5B,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,CAAC;CAC1D;AAED,UAAU,oBAAoB;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,OAAO,CAAyB;gBAE5B,OAAO,GAAE,OAAO,CAAC,WAAW,CAAM;IAI9C,OAAO,CAAC,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI;IAKnE,SAAS,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI;IA6BjE,KAAK,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBxD;;OAEG;YACW,0BAA0B;IAmBxC;;OAEG;YACW,eAAe;IAmB7B;;OAEG;IACH,OAAO,CAAC,YAAY;CAgCrB;AAED;;GAEG;AACH,wBAAgB,kBAAkB;;;EAKjC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FacetCoverageReporter = void 0;
|
|
4
|
+
exports.facet = facet;
|
|
5
|
+
exports.createFacetFixture = createFacetFixture;
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const types_js_1 = require("../types.js");
|
|
9
|
+
const CoverageCalculator_js_1 = require("../core/CoverageCalculator.js");
|
|
10
|
+
const JsonReporter_js_1 = require("../reporters/JsonReporter.js");
|
|
11
|
+
const HtmlReporter_js_1 = require("../reporters/HtmlReporter.js");
|
|
12
|
+
const MarkdownReporter_js_1 = require("../reporters/MarkdownReporter.js");
|
|
13
|
+
/**
|
|
14
|
+
* Helper function to link tests to facets
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* test('my test', {
|
|
18
|
+
* annotation: facet('guest-checkout-flow', 'pci-card-masking')
|
|
19
|
+
* }, async ({ page }) => {
|
|
20
|
+
* // test code
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
function facet(...facetIds) {
|
|
24
|
+
return {
|
|
25
|
+
type: 'facet-coverage',
|
|
26
|
+
description: facetIds.join(','),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Playwright reporter for Facet coverage
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // playwright.config.ts
|
|
34
|
+
* import { FacetCoverageReporter } from 'facet-coverage/playwright';
|
|
35
|
+
*
|
|
36
|
+
* export default {
|
|
37
|
+
* reporter: [
|
|
38
|
+
* ['html'],
|
|
39
|
+
* [FacetCoverageReporter]
|
|
40
|
+
* ]
|
|
41
|
+
* };
|
|
42
|
+
*/
|
|
43
|
+
class FacetCoverageReporter {
|
|
44
|
+
config;
|
|
45
|
+
testLinks = [];
|
|
46
|
+
rootDir = process.cwd();
|
|
47
|
+
constructor(options = {}) {
|
|
48
|
+
this.config = { ...types_js_1.defaultConfig, ...options };
|
|
49
|
+
}
|
|
50
|
+
onBegin(config, suite) {
|
|
51
|
+
this.rootDir = config.rootDir;
|
|
52
|
+
this.testLinks = [];
|
|
53
|
+
}
|
|
54
|
+
onTestEnd(test, result) {
|
|
55
|
+
// Only process passed tests for coverage
|
|
56
|
+
if (result.status !== 'passed') {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Find facet annotations
|
|
60
|
+
const facetAnnotations = test.annotations.filter(a => a.type === 'facet-coverage' && a.description);
|
|
61
|
+
for (const annotation of facetAnnotations) {
|
|
62
|
+
const facetIds = annotation.description.split(',').map(id => id.trim());
|
|
63
|
+
if (facetIds.length > 0) {
|
|
64
|
+
const titlePath = test.titlePath();
|
|
65
|
+
const fullTitle = titlePath.join(' > ');
|
|
66
|
+
this.testLinks.push({
|
|
67
|
+
file: test.location.file.replace(this.rootDir + '/', ''),
|
|
68
|
+
title: test.title,
|
|
69
|
+
fullTitle,
|
|
70
|
+
facetIds,
|
|
71
|
+
line: test.location.line,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async onEnd(result) {
|
|
77
|
+
// Write collected test links to a temp file for the coverage calculator
|
|
78
|
+
const tempDir = (0, path_1.join)(this.rootDir, this.config.output.dir);
|
|
79
|
+
(0, fs_1.mkdirSync)(tempDir, { recursive: true });
|
|
80
|
+
const linksPath = (0, path_1.join)(tempDir, '.test-links.json');
|
|
81
|
+
(0, fs_1.writeFileSync)(linksPath, JSON.stringify(this.testLinks, null, 2));
|
|
82
|
+
// Calculate coverage using the collected links
|
|
83
|
+
const calculator = new CoverageCalculator_js_1.CoverageCalculator(this.config);
|
|
84
|
+
const report = await this.calculateCoverageWithLinks(calculator);
|
|
85
|
+
// Generate reports
|
|
86
|
+
await this.generateReports(report);
|
|
87
|
+
// Print summary to console
|
|
88
|
+
this.printSummary(report);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Calculate coverage using collected test links
|
|
92
|
+
*/
|
|
93
|
+
async calculateCoverageWithLinks(calculator) {
|
|
94
|
+
// For now, use the standard calculator
|
|
95
|
+
// In the future, we could inject our collected links
|
|
96
|
+
const report = await calculator.calculateCoverage(this.rootDir);
|
|
97
|
+
// Merge our collected links with any found by scanning
|
|
98
|
+
// This ensures we capture runtime annotations that might not be statically detected
|
|
99
|
+
const existingFiles = new Set(report.tests.map(t => `${t.file}:${t.line}`));
|
|
100
|
+
for (const link of this.testLinks) {
|
|
101
|
+
const key = `${link.file}:${link.line}`;
|
|
102
|
+
if (!existingFiles.has(key)) {
|
|
103
|
+
report.tests.push(link);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return report;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Generate all configured report formats
|
|
110
|
+
*/
|
|
111
|
+
async generateReports(report) {
|
|
112
|
+
const formats = this.config.output.formats;
|
|
113
|
+
if (formats.includes('json')) {
|
|
114
|
+
const jsonReporter = new JsonReporter_js_1.JsonReporter(this.config);
|
|
115
|
+
jsonReporter.write(report, this.rootDir);
|
|
116
|
+
}
|
|
117
|
+
if (formats.includes('html')) {
|
|
118
|
+
const htmlReporter = new HtmlReporter_js_1.HtmlReporter(this.config);
|
|
119
|
+
htmlReporter.write(report, this.rootDir);
|
|
120
|
+
}
|
|
121
|
+
if (formats.includes('markdown')) {
|
|
122
|
+
const mdReporter = new MarkdownReporter_js_1.MarkdownReporter(this.config);
|
|
123
|
+
mdReporter.write(report, this.rootDir);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Print coverage summary to console
|
|
128
|
+
*/
|
|
129
|
+
printSummary(report) {
|
|
130
|
+
console.log('\nš Facet Coverage Report\n');
|
|
131
|
+
console.log(`Overall: ${report.summary.percentage}% (${report.summary.coveredFacets}/${report.summary.totalFacets} facets)`);
|
|
132
|
+
if (report.byType.length > 0) {
|
|
133
|
+
console.log('\nBy Type:');
|
|
134
|
+
for (const type of report.byType) {
|
|
135
|
+
const icon = type.percentage === 100 ? 'ā
' : type.percentage >= 75 ? 'š”' : 'ā';
|
|
136
|
+
console.log(` ${icon} ${type.type}: ${type.percentage}% (${type.covered}/${type.total})`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (report.features.length > 0) {
|
|
140
|
+
console.log('\nFeatures:');
|
|
141
|
+
for (const feature of report.features) {
|
|
142
|
+
const icon = feature.percentage === 100 ? 'ā
' : feature.percentage >= 75 ? 'š”' : 'ā';
|
|
143
|
+
console.log(` ${icon} ${feature.feature}: ${feature.percentage}% (${feature.coveredFacets}/${feature.totalFacets})`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (report.uncovered.length > 0) {
|
|
147
|
+
console.log(`\nā Uncovered Facets (${report.uncovered.length}):`);
|
|
148
|
+
for (const facet of report.uncovered.slice(0, 5)) {
|
|
149
|
+
console.log(` - ${facet.id} (${facet.type})`);
|
|
150
|
+
}
|
|
151
|
+
if (report.uncovered.length > 5) {
|
|
152
|
+
console.log(` ... and ${report.uncovered.length - 5} more`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
console.log(`\nReports: ${(0, path_1.join)(this.rootDir, this.config.output.dir)}/`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.FacetCoverageReporter = FacetCoverageReporter;
|
|
159
|
+
/**
|
|
160
|
+
* Create a facet coverage fixture for Playwright
|
|
161
|
+
*/
|
|
162
|
+
function createFacetFixture() {
|
|
163
|
+
return {
|
|
164
|
+
facet,
|
|
165
|
+
FacetCoverageReporter,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=playwright.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.js","sourceRoot":"","sources":["../../src/integrations/playwright.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { CoverageReport, FacetConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates HTML coverage reports
|
|
4
|
+
*/
|
|
5
|
+
export declare class HtmlReporter {
|
|
6
|
+
private config;
|
|
7
|
+
constructor(config?: Partial<FacetConfig>);
|
|
8
|
+
/**
|
|
9
|
+
* Generate HTML report
|
|
10
|
+
*/
|
|
11
|
+
generate(report: CoverageReport): string;
|
|
12
|
+
/**
|
|
13
|
+
* Get CSS styles
|
|
14
|
+
*/
|
|
15
|
+
private getStyles;
|
|
16
|
+
/**
|
|
17
|
+
* Get JavaScript for interactivity
|
|
18
|
+
*/
|
|
19
|
+
private getScript;
|
|
20
|
+
/**
|
|
21
|
+
* Generate summary section HTML
|
|
22
|
+
*/
|
|
23
|
+
private generateSummarySection;
|
|
24
|
+
/**
|
|
25
|
+
* Generate type breakdown section
|
|
26
|
+
*/
|
|
27
|
+
private generateTypeSection;
|
|
28
|
+
/**
|
|
29
|
+
* Generate features section
|
|
30
|
+
*/
|
|
31
|
+
private generateFeaturesSection;
|
|
32
|
+
/**
|
|
33
|
+
* Generate HTML for a single feature
|
|
34
|
+
*/
|
|
35
|
+
private generateFeatureHtml;
|
|
36
|
+
/**
|
|
37
|
+
* Generate HTML for a single facet
|
|
38
|
+
*/
|
|
39
|
+
private generateFacetHtml;
|
|
40
|
+
/**
|
|
41
|
+
* Generate uncovered facets section
|
|
42
|
+
*/
|
|
43
|
+
private generateUncoveredSection;
|
|
44
|
+
/**
|
|
45
|
+
* Get CSS class for coverage percentage
|
|
46
|
+
*/
|
|
47
|
+
private getCoverageClass;
|
|
48
|
+
/**
|
|
49
|
+
* Write HTML report to file
|
|
50
|
+
*/
|
|
51
|
+
write(report: CoverageReport, cwd?: string): string;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=HtmlReporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HtmlReporter.d.ts","sourceRoot":"","sources":["../../src/reporters/HtmlReporter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAkC,MAAM,aAAa,CAAC;AAG/F;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAI7C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;IAmCxC;;OAEG;IACH,OAAO,CAAC,SAAS;IA8PjB;;OAEG;IACH,OAAO,CAAC,SAAS;IAUjB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA8B9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAU/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuB3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAkBhC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM;CAYnE"}
|