@facet-coverage/core 0.1.0 → 0.3.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/README.md +296 -48
- package/dist/cli/commands/analyze.d.ts.map +1 -1
- package/dist/cli/commands/analyze.js +2 -35
- package/dist/cli/commands/analyze.js.map +1 -1
- package/dist/cli/commands/generate.d.ts +6 -2
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +371 -9
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/validate.d.ts.map +1 -1
- package/dist/cli/commands/validate.js +2 -34
- package/dist/cli/commands/validate.js.map +1 -1
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +2 -34
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/cli/index.js +9 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/config.d.ts +15 -0
- package/dist/cli/utils/config.d.ts.map +1 -0
- package/dist/cli/utils/config.js +88 -0
- package/dist/cli/utils/config.js.map +1 -0
- package/dist/core/FacetParser.d.ts +18 -1
- package/dist/core/FacetParser.d.ts.map +1 -1
- package/dist/core/FacetParser.js +45 -3
- package/dist/core/FacetParser.js.map +1 -1
- package/dist/core/IDChangeDetector.d.ts +50 -0
- package/dist/core/IDChangeDetector.d.ts.map +1 -0
- package/dist/core/IDChangeDetector.js +147 -0
- package/dist/core/IDChangeDetector.js.map +1 -0
- package/dist/core/TestScanner.d.ts +10 -1
- package/dist/core/TestScanner.d.ts.map +1 -1
- package/dist/core/TestScanner.js +124 -6
- package/dist/core/TestScanner.js.map +1 -1
- package/dist/types.d.ts +7 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,26 +1,65 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
1
3
|
# Facet Coverage
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
**Test every facet of your features**
|
|
6
|
+
|
|
7
|
+
*Natural specifications. Multiple perspectives. Rigorous coverage.*
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@facet-coverage/core)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
[](https://dl.circleci.com/pipelines/gh/iraycd/facet-coverage)
|
|
12
|
+
[](https://nodejs.org)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
- [What is Facet?](#what-is-facet)
|
|
21
|
+
- [Installation](#installation)
|
|
22
|
+
- [Quick Start](#quick-start)
|
|
23
|
+
- [Linking Tests to Facets](#linking-tests-to-facets)
|
|
24
|
+
- [Project Structure](#project-structure)
|
|
25
|
+
- [CLI Commands](#cli-commands)
|
|
26
|
+
- [Playwright Integration](#playwright-integration)
|
|
27
|
+
- [Configuration](#configuration)
|
|
28
|
+
- [ID Patterns](#id-patterns)
|
|
29
|
+
- [Programmatic API](#programmatic-api)
|
|
30
|
+
- [Benefits](#benefits)
|
|
31
|
+
- [How Facet Differs](#how-facet-differs)
|
|
32
|
+
- [Key Principles](#key-principles)
|
|
33
|
+
- [Contributing](#contributing)
|
|
34
|
+
- [License](#license)
|
|
35
|
+
|
|
36
|
+
---
|
|
5
37
|
|
|
6
38
|
## What is Facet?
|
|
7
39
|
|
|
8
40
|
Facet is a modern testing framework that lets you document features from multiple stakeholder perspectives while maintaining exact traceability to your tests.
|
|
9
41
|
|
|
10
42
|
**One feature. Many facets.**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
43
|
+
|
|
44
|
+
| Perspective | Description |
|
|
45
|
+
|-------------|-------------|
|
|
46
|
+
| **Business requirements** | Product owner specifications |
|
|
47
|
+
| **Compliance mandates** | Regulatory requirements (PCI-DSS, GDPR, etc.) |
|
|
48
|
+
| **UX standards** | Design system and accessibility rules |
|
|
49
|
+
| **Technical specs** | Architecture and API contracts |
|
|
15
50
|
|
|
16
51
|
All connected to the same tests. All tracked for coverage.
|
|
17
52
|
|
|
53
|
+
---
|
|
54
|
+
|
|
18
55
|
## Installation
|
|
19
56
|
|
|
20
57
|
```bash
|
|
21
58
|
bun add -d @facet-coverage/core
|
|
22
59
|
```
|
|
23
60
|
|
|
61
|
+
---
|
|
62
|
+
|
|
24
63
|
## Quick Start
|
|
25
64
|
|
|
26
65
|
### 1. Create Your First Facets
|
|
@@ -56,13 +95,17 @@ We handle credit card data, so PCI-DSS compliance is mandatory:
|
|
|
56
95
|
3. **Card masking** - Display only last 4 digits
|
|
57
96
|
```
|
|
58
97
|
|
|
59
|
-
### 2. Generate Structure
|
|
98
|
+
### 2. Generate Structure & Types
|
|
60
99
|
|
|
61
100
|
```bash
|
|
62
101
|
bunx facet generate features/checkout/facets/
|
|
63
102
|
```
|
|
64
103
|
|
|
65
|
-
This creates `features/checkout/.facet
|
|
104
|
+
This creates two files in `features/checkout/.facet/`:
|
|
105
|
+
- `structure.json` - facet definitions
|
|
106
|
+
- `facets.ts` - TypeScript types for type-safe linking
|
|
107
|
+
|
|
108
|
+
**structure.json:**
|
|
66
109
|
|
|
67
110
|
```json
|
|
68
111
|
{
|
|
@@ -90,26 +133,27 @@ This creates `features/checkout/.facet/structure.json`:
|
|
|
90
133
|
|
|
91
134
|
### 3. Link Tests
|
|
92
135
|
|
|
136
|
+
Import the generated types and use `facet()` in your tests:
|
|
137
|
+
|
|
93
138
|
```typescript
|
|
94
139
|
// features/checkout/tests/checkout.spec.ts
|
|
95
|
-
import { test, expect } from '
|
|
96
|
-
import { facet } from '
|
|
97
|
-
|
|
98
|
-
test('guest user completes purchase', {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
// Verify compliance: card masking
|
|
108
|
-
const maskedCard = page.locator('.card-last-four');
|
|
109
|
-
await expect(maskedCard).toHaveText('•••• 4242');
|
|
140
|
+
import { test, expect } from 'bun:test'; // or jest, vitest, mocha...
|
|
141
|
+
import { Facets, facet } from '../.facet/facets';
|
|
142
|
+
|
|
143
|
+
test('guest user completes purchase', () => {
|
|
144
|
+
// Declare which facets this test covers
|
|
145
|
+
facet(Facets.BUSINESS_GUEST_PURCHASE_FLOW);
|
|
146
|
+
facet(Facets.COMPLIANCE_PCI_DSS_PAYMENT_REQUIREMENTS);
|
|
147
|
+
|
|
148
|
+
// Your test code
|
|
149
|
+
const order = checkout(cart, 'user@example.com', '4242...');
|
|
150
|
+
expect(order.confirmed).toBe(true);
|
|
151
|
+
expect(order.maskedCard).toBe('•••• 4242'); // PCI-DSS compliance
|
|
110
152
|
});
|
|
111
153
|
```
|
|
112
154
|
|
|
155
|
+
The `facet()` function is type-safe - TypeScript will error if you use an invalid facet ID!
|
|
156
|
+
|
|
113
157
|
### 4. Run Coverage
|
|
114
158
|
|
|
115
159
|
```bash
|
|
@@ -118,20 +162,22 @@ bunx facet analyze
|
|
|
118
162
|
|
|
119
163
|
**Output:**
|
|
120
164
|
```
|
|
121
|
-
|
|
165
|
+
Facet Coverage Report
|
|
122
166
|
|
|
123
167
|
Overall: 100%
|
|
124
168
|
|
|
125
169
|
By Type:
|
|
126
|
-
|
|
127
|
-
|
|
170
|
+
business: 100% (1/1)
|
|
171
|
+
compliance: 100% (1/1)
|
|
128
172
|
|
|
129
173
|
Reports generated:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
174
|
+
.facet-coverage/coverage.json
|
|
175
|
+
.facet-coverage/coverage.html
|
|
176
|
+
.facet-coverage/coverage.md
|
|
133
177
|
```
|
|
134
178
|
|
|
179
|
+
---
|
|
180
|
+
|
|
135
181
|
## Project Structure
|
|
136
182
|
|
|
137
183
|
```
|
|
@@ -141,9 +187,10 @@ project/
|
|
|
141
187
|
│ │ ├── facets/
|
|
142
188
|
│ │ │ ├── business.md # Product owner writes
|
|
143
189
|
│ │ │ ├── compliance.md # Compliance team writes
|
|
144
|
-
│ │ │ └── ux.md
|
|
190
|
+
│ │ │ └── ux.md # UX designer writes
|
|
145
191
|
│ │ ├── .facet/
|
|
146
|
-
│ │ │
|
|
192
|
+
│ │ │ ├── structure.json # Generated facet definitions
|
|
193
|
+
│ │ │ └── facets.ts # Generated TypeScript types
|
|
147
194
|
│ │ └── tests/
|
|
148
195
|
│ │ └── checkout.spec.ts
|
|
149
196
|
│ │
|
|
@@ -160,17 +207,80 @@ project/
|
|
|
160
207
|
└── facet.config.js # Configuration
|
|
161
208
|
```
|
|
162
209
|
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Linking Tests to Facets
|
|
213
|
+
|
|
214
|
+
Use the `facet()` function inside your tests - just like `expect()` but for coverage tracking!
|
|
215
|
+
|
|
216
|
+
### Recommended: Type-Safe with `facet()` Function
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { test, expect } from 'bun:test'; // or jest, vitest, mocha...
|
|
220
|
+
import { Facets, facet } from '../.facet/facets';
|
|
221
|
+
|
|
222
|
+
test('guest user can complete a purchase', () => {
|
|
223
|
+
// Declare which facets this test covers - type-safe with autocomplete!
|
|
224
|
+
facet(Facets.BUSINESS_GUEST_PURCHASE_FLOW);
|
|
225
|
+
facet(Facets.COMPLIANCE_PCI_DSS_PAYMENT_REQUIREMENTS);
|
|
226
|
+
|
|
227
|
+
// Your test code
|
|
228
|
+
const order = checkout(cart, email, card);
|
|
229
|
+
expect(order.confirmed).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test('payment meets compliance', () => {
|
|
233
|
+
// Multiple facets in one call
|
|
234
|
+
facet(Facets.COMPLIANCE_PCI_DSS, Facets.COMPLIANCE_GDPR);
|
|
235
|
+
|
|
236
|
+
expect(payment.encrypted).toBe(true);
|
|
237
|
+
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Benefits:**
|
|
241
|
+
- Full TypeScript autocomplete
|
|
242
|
+
- Compile-time validation (invalid facet IDs cause errors)
|
|
243
|
+
- Clean, readable syntax
|
|
244
|
+
- Works with any testing framework
|
|
245
|
+
|
|
246
|
+
**Generated `facets.ts` includes:**
|
|
247
|
+
- `FacetId` - Union type of all valid facet IDs
|
|
248
|
+
- `Facets` - Object with constants for each facet
|
|
249
|
+
- `facet()` - Type-safe function to declare coverage
|
|
250
|
+
|
|
251
|
+
### Alternative: Comment Annotations
|
|
252
|
+
|
|
253
|
+
For quick setup without imports, use comment annotations:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// @facet business:guest-purchase-flow, compliance:pci-dss
|
|
257
|
+
test('guest user completes purchase', () => {
|
|
258
|
+
// Your test code
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### All Linking Methods
|
|
263
|
+
|
|
264
|
+
| Method | Type-Safe | Syntax |
|
|
265
|
+
|--------|-----------|--------|
|
|
266
|
+
| `facet()` function | Yes | `facet(Facets.ID)` inside test body |
|
|
267
|
+
| Comment annotation | No | `// @facet id` above test |
|
|
268
|
+
| Playwright annotation | Yes | `{ annotation: facet(...) }` in test options |
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
163
272
|
## CLI Commands
|
|
164
273
|
|
|
165
|
-
### Generate Structure
|
|
274
|
+
### Generate Structure & Types
|
|
166
275
|
|
|
167
276
|
```bash
|
|
168
|
-
# Generate structure from facet documents
|
|
277
|
+
# Generate structure.json and facets.ts from facet documents
|
|
169
278
|
bunx facet generate <facets-dir>
|
|
170
279
|
|
|
171
280
|
# Options
|
|
172
|
-
bunx facet generate features/checkout/facets/ -o ./custom-output
|
|
173
|
-
bunx facet generate features/checkout/facets/ -t business
|
|
281
|
+
bunx facet generate features/checkout/facets/ -o ./custom-output # Custom output dir
|
|
282
|
+
bunx facet generate features/checkout/facets/ -t business # Override type
|
|
283
|
+
bunx facet generate features/checkout/facets/ --no-types # Skip TypeScript generation
|
|
174
284
|
```
|
|
175
285
|
|
|
176
286
|
### Analyze Coverage
|
|
@@ -208,8 +318,18 @@ bunx facet watch
|
|
|
208
318
|
bunx facet watch -v # Validate before analysis
|
|
209
319
|
```
|
|
210
320
|
|
|
321
|
+
---
|
|
322
|
+
|
|
211
323
|
## Playwright Integration
|
|
212
324
|
|
|
325
|
+
> **Note:** Playwright works with [comment annotations](#method-1-comment-annotations-any-framework) and [generated types](#method-2-type-safe-with-generated-types-recommended) out of the box. This section covers the **optional** enhanced integration with a custom reporter and annotation helper.
|
|
326
|
+
|
|
327
|
+
### Why Use the Playwright Integration?
|
|
328
|
+
|
|
329
|
+
- **Automatic coverage on test run** - Coverage reports generated after `playwright test`
|
|
330
|
+
- **Runtime annotation capture** - Works with dynamic test generation
|
|
331
|
+
- **Native annotation syntax** - Uses Playwright's built-in annotation system
|
|
332
|
+
|
|
213
333
|
### Reporter Setup
|
|
214
334
|
|
|
215
335
|
```typescript
|
|
@@ -260,16 +380,28 @@ test('comprehensive test', {
|
|
|
260
380
|
});
|
|
261
381
|
```
|
|
262
382
|
|
|
383
|
+
---
|
|
384
|
+
|
|
263
385
|
## Configuration
|
|
264
386
|
|
|
265
|
-
|
|
387
|
+
Facet Coverage supports multiple configuration file formats. The CLI looks for config files in this order:
|
|
388
|
+
|
|
389
|
+
1. `facet.config.js` (ESM or CommonJS)
|
|
390
|
+
2. `facet.config.mjs` (ESM only)
|
|
391
|
+
3. `facet.config.json` (JSON)
|
|
392
|
+
|
|
393
|
+
### Configuration Formats
|
|
394
|
+
|
|
395
|
+
**JavaScript (ESM):**
|
|
266
396
|
|
|
267
397
|
```javascript
|
|
398
|
+
// facet.config.js
|
|
268
399
|
export default {
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
400
|
+
// Glob pattern(s) for finding facet markdown files
|
|
401
|
+
facetPattern: ['features/**/*.facet.md', 'features/**/facets/*.md'],
|
|
402
|
+
|
|
403
|
+
// Where structure files are generated
|
|
404
|
+
structureFiles: ['features/**/.facet/structure.json'],
|
|
273
405
|
|
|
274
406
|
// Where tests live
|
|
275
407
|
testDir: './features/**/tests',
|
|
@@ -300,6 +432,50 @@ export default {
|
|
|
300
432
|
};
|
|
301
433
|
```
|
|
302
434
|
|
|
435
|
+
**JSON:**
|
|
436
|
+
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"facetPattern": ["features/**/*.facet.md", "features/**/facets/*.md"],
|
|
440
|
+
"structureFiles": ["features/**/.facet/structure.json"],
|
|
441
|
+
"testDir": "./features/**/tests",
|
|
442
|
+
"testPatterns": ["**/*.spec.ts", "**/*.test.ts"],
|
|
443
|
+
"validation": {
|
|
444
|
+
"requireSourceExists": true,
|
|
445
|
+
"requireSectionExists": true,
|
|
446
|
+
"requireAllTestsLinked": false
|
|
447
|
+
},
|
|
448
|
+
"output": {
|
|
449
|
+
"dir": ".facet-coverage",
|
|
450
|
+
"formats": ["json", "html", "markdown"]
|
|
451
|
+
},
|
|
452
|
+
"thresholds": {
|
|
453
|
+
"global": 75,
|
|
454
|
+
"byType": {
|
|
455
|
+
"compliance": 100
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Configuration Options
|
|
462
|
+
|
|
463
|
+
| Option | Type | Default | Description |
|
|
464
|
+
|--------|------|---------|-------------|
|
|
465
|
+
| `facetPattern` | `string \| string[]` | `['features/**/*.facet.md', 'features/**/facets/*.md']` | Glob pattern(s) for finding facet files |
|
|
466
|
+
| `structureFiles` | `string[]` | `['features/**/.facet/structure.json']` | Glob patterns for structure files |
|
|
467
|
+
| `testDir` | `string` | `'./features/**/tests'` | Test directory pattern |
|
|
468
|
+
| `testPatterns` | `string[]` | `['**/*.spec.ts', '**/*.test.ts']` | Test file patterns |
|
|
469
|
+
| `validation.requireSourceExists` | `boolean` | `true` | Check if source files exist |
|
|
470
|
+
| `validation.requireSectionExists` | `boolean` | `true` | Check if sections exist in files |
|
|
471
|
+
| `validation.requireAllTestsLinked` | `boolean` | `false` | Require every test links to a facet |
|
|
472
|
+
| `output.dir` | `string` | `'.facet-coverage'` | Output directory for reports |
|
|
473
|
+
| `output.formats` | `string[]` | `['json', 'html', 'markdown']` | Report formats to generate |
|
|
474
|
+
| `thresholds.global` | `number` | `75` | Overall coverage threshold % |
|
|
475
|
+
| `thresholds.byType` | `object` | `{}` | Per-type coverage thresholds |
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
303
479
|
## ID Patterns
|
|
304
480
|
|
|
305
481
|
### Auto-Generated (Recommended)
|
|
@@ -335,6 +511,8 @@ facet('business:guest-purchase-flow') // Auto-generated
|
|
|
335
511
|
facet('facets/business.md#guest-purchase-flow') // Direct path
|
|
336
512
|
```
|
|
337
513
|
|
|
514
|
+
---
|
|
515
|
+
|
|
338
516
|
## Programmatic API
|
|
339
517
|
|
|
340
518
|
```typescript
|
|
@@ -375,8 +553,14 @@ const mdReporter = new MarkdownReporter();
|
|
|
375
553
|
mdReporter.write(report);
|
|
376
554
|
```
|
|
377
555
|
|
|
556
|
+
---
|
|
557
|
+
|
|
378
558
|
## Benefits
|
|
379
559
|
|
|
560
|
+
<table>
|
|
561
|
+
<tr>
|
|
562
|
+
<td width="50%">
|
|
563
|
+
|
|
380
564
|
### For Product Owners
|
|
381
565
|
- Write in natural language
|
|
382
566
|
- Focus on business value
|
|
@@ -395,6 +579,9 @@ mdReporter.write(report);
|
|
|
395
579
|
- Track accessibility coverage
|
|
396
580
|
- Mobile/desktop requirements clear
|
|
397
581
|
|
|
582
|
+
</td>
|
|
583
|
+
<td width="50%">
|
|
584
|
+
|
|
398
585
|
### For Developers
|
|
399
586
|
- One test covers multiple facets
|
|
400
587
|
- Clear requirements from all stakeholders
|
|
@@ -407,16 +594,77 @@ mdReporter.write(report);
|
|
|
407
594
|
- Multi-perspective coverage
|
|
408
595
|
- Progress tracking
|
|
409
596
|
|
|
597
|
+
</td>
|
|
598
|
+
</tr>
|
|
599
|
+
</table>
|
|
600
|
+
|
|
601
|
+
---
|
|
602
|
+
|
|
603
|
+
## How Facet Differs
|
|
604
|
+
|
|
605
|
+
| Approach | Focus | Facet's Difference |
|
|
606
|
+
|----------|-------|-------------------|
|
|
607
|
+
| **TDD** | Code correctness via unit tests | Facet tracks *what* is covered, not *how* to write code |
|
|
608
|
+
| **BDD** | Behavior via Given-When-Then | Facet uses free-form natural language, not structured syntax |
|
|
609
|
+
| **ATDD** | Acceptance criteria drive development | Facet maps multiple perspectives to tests, not just acceptance |
|
|
610
|
+
| **Traditional Coverage** | Lines/branches executed | Facet measures *requirement* coverage, not code coverage |
|
|
611
|
+
|
|
612
|
+
**Key insight:** TDD/BDD/ATDD are *development methodologies*. Facet is a *coverage framework*. Use them together.
|
|
613
|
+
|
|
614
|
+
### Why Facet Works for AI-Driven Testing
|
|
615
|
+
|
|
616
|
+
AI coding assistants excel at generating tests but struggle with *what to test*. Facet solves this:
|
|
617
|
+
|
|
618
|
+
- **Natural language specs** → AI understands requirements without parsing Gherkin
|
|
619
|
+
- **Multi-perspective facets** → AI generates tests covering business, compliance, UX in one pass
|
|
620
|
+
- **Type-safe linking** → AI can programmatically verify coverage completeness
|
|
621
|
+
- **Gap detection** → AI identifies untested facets and generates missing tests
|
|
622
|
+
|
|
623
|
+
```
|
|
624
|
+
Human: "Generate tests for checkout"
|
|
625
|
+
AI: Reads facets → Understands business rules, PCI compliance, UX requirements → Generates comprehensive tests → Links to facets automatically
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
Facet bridges human intent and AI execution with traceable, verifiable coverage.
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
410
632
|
## Key Principles
|
|
411
633
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
634
|
+
| Principle | Description |
|
|
635
|
+
|-----------|-------------|
|
|
636
|
+
| **Multi-Perspective** | Every feature has multiple facets |
|
|
637
|
+
| **Natural Language** | Write like humans, not machines |
|
|
638
|
+
| **Evolutionary** | Documentation grows with understanding |
|
|
639
|
+
| **Traceable** | Exact test-to-facet mapping |
|
|
640
|
+
| **Feature-Modular** | Self-contained, team-owned |
|
|
641
|
+
| **Lightweight** | Markdown + JSON, nothing heavy |
|
|
642
|
+
| **Flexible** | Adopt incrementally, customize freely |
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
## Contributing
|
|
647
|
+
|
|
648
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
649
|
+
|
|
650
|
+
1. Fork the repository
|
|
651
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
652
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
653
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
654
|
+
5. Open a Pull Request
|
|
655
|
+
|
|
656
|
+
---
|
|
419
657
|
|
|
420
658
|
## License
|
|
421
659
|
|
|
422
|
-
MIT
|
|
660
|
+
MIT License - see the [LICENSE](LICENSE) file for details.
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
<div align="center">
|
|
665
|
+
|
|
666
|
+
**[Report Bug](https://github.com/iraycd/facet-coverage/issues) | [Request Feature](https://github.com/iraycd/facet-coverage/issues)**
|
|
667
|
+
|
|
668
|
+
If you find this project useful, please consider giving it a star!
|
|
669
|
+
|
|
670
|
+
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":"AAOA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwEhF"}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.analyzeCommand = analyzeCommand;
|
|
4
|
-
const fs_1 = require("fs");
|
|
5
|
-
const path_1 = require("path");
|
|
6
4
|
const CoverageCalculator_js_1 = require("../../core/CoverageCalculator.js");
|
|
7
5
|
const JsonReporter_js_1 = require("../../reporters/JsonReporter.js");
|
|
8
6
|
const HtmlReporter_js_1 = require("../../reporters/HtmlReporter.js");
|
|
9
7
|
const MarkdownReporter_js_1 = require("../../reporters/MarkdownReporter.js");
|
|
10
|
-
const
|
|
8
|
+
const config_js_1 = require("../utils/config.js");
|
|
11
9
|
/**
|
|
12
10
|
* Analyze facet coverage
|
|
13
11
|
*/
|
|
14
12
|
async function analyzeCommand(options = {}) {
|
|
15
13
|
const cwd = process.cwd();
|
|
16
14
|
// Load config
|
|
17
|
-
const config = await loadConfig(options.config, cwd);
|
|
15
|
+
const config = await (0, config_js_1.loadConfig)(options.config, cwd);
|
|
18
16
|
// Override with CLI options
|
|
19
17
|
if (options.threshold) {
|
|
20
18
|
config.thresholds.global = parseInt(options.threshold, 10);
|
|
@@ -72,37 +70,6 @@ async function analyzeCommand(options = {}) {
|
|
|
72
70
|
process.exit(1);
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Load configuration from file or use defaults
|
|
77
|
-
*/
|
|
78
|
-
async function loadConfig(configPath, cwd) {
|
|
79
|
-
const configFiles = [
|
|
80
|
-
configPath,
|
|
81
|
-
'facet.config.js',
|
|
82
|
-
'facet.config.mjs',
|
|
83
|
-
'facet.config.json',
|
|
84
|
-
].filter(Boolean);
|
|
85
|
-
for (const file of configFiles) {
|
|
86
|
-
const fullPath = (0, path_1.resolve)(cwd, file);
|
|
87
|
-
if ((0, fs_1.existsSync)(fullPath)) {
|
|
88
|
-
if (file.endsWith('.json')) {
|
|
89
|
-
const content = (0, fs_1.readFileSync)(fullPath, 'utf-8');
|
|
90
|
-
return { ...types_js_1.defaultConfig, ...JSON.parse(content) };
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
// Dynamic import for JS config
|
|
94
|
-
try {
|
|
95
|
-
const imported = await import(fullPath);
|
|
96
|
-
return { ...types_js_1.defaultConfig, ...(imported.default || imported) };
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
console.warn(`Warning: Could not load config from ${file}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return types_js_1.defaultConfig;
|
|
105
|
-
}
|
|
106
73
|
/**
|
|
107
74
|
* Print coverage report to console
|
|
108
75
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../../src/cli/commands/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
interface GenerateOptions {
|
|
2
2
|
output?: string;
|
|
3
3
|
type?: string;
|
|
4
|
+
noTypes?: boolean;
|
|
5
|
+
config?: string;
|
|
6
|
+
global?: boolean;
|
|
7
|
+
quiet?: boolean;
|
|
4
8
|
}
|
|
5
9
|
/**
|
|
6
|
-
* Generate structure.json from facet markdown files
|
|
10
|
+
* Generate structure.json and TypeScript types from facet markdown files
|
|
7
11
|
*/
|
|
8
|
-
export declare function generateCommand(dir
|
|
12
|
+
export declare function generateCommand(dir?: string, options?: GenerateOptions): Promise<void>;
|
|
9
13
|
export {};
|
|
10
14
|
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AASA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAqfD;;GAEG;AACH,wBAAsB,eAAe,CACnC,GAAG,CAAC,EAAE,MAAM,EACZ,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAWf"}
|