cucumber-dressing 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/CHANGELOG.md +91 -0
- package/LICENSE +21 -0
- package/README.md +421 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +154 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +13 -0
- package/dist/parser.d.ts +39 -0
- package/dist/parser.js +140 -0
- package/dist/reporter.d.ts +74 -0
- package/dist/reporter.js +235 -0
- package/dist/statistics.d.ts +96 -0
- package/dist/statistics.js +256 -0
- package/dist/template-generator.d.ts +101 -0
- package/dist/template-generator.js +528 -0
- package/dist/templates/scripts.js.template.d.ts +3 -0
- package/dist/templates/scripts.js.template.js +297 -0
- package/dist/templates/styles.css.template.d.ts +3 -0
- package/dist/templates/styles.css.template.js +621 -0
- package/dist/types.d.ts +207 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +112 -0
- package/dist/utils.js +250 -0
- package/package.json +92 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statistics Calculator - Generates report statistics
|
|
3
|
+
*/
|
|
4
|
+
import { calculateFeatureStatus, calculatePassRate, calculateScenarioDuration, calculateScenarioStatus, } from './utils.js';
|
|
5
|
+
export class StatisticsCalculator {
|
|
6
|
+
/**
|
|
7
|
+
* Calculate comprehensive statistics from features
|
|
8
|
+
* @param features - Array of Gherkin features to analyze
|
|
9
|
+
* @returns Comprehensive statistics including counts, duration, and pass rate
|
|
10
|
+
*/
|
|
11
|
+
static calculateStatistics(features) {
|
|
12
|
+
const stats = {
|
|
13
|
+
features: features.length,
|
|
14
|
+
scenarios: 0,
|
|
15
|
+
steps: 0,
|
|
16
|
+
passed: 0,
|
|
17
|
+
failed: 0,
|
|
18
|
+
skipped: 0,
|
|
19
|
+
pending: 0,
|
|
20
|
+
undefined: 0,
|
|
21
|
+
ambiguous: 0,
|
|
22
|
+
duration: 0,
|
|
23
|
+
passRate: 0,
|
|
24
|
+
};
|
|
25
|
+
features.forEach(feature => {
|
|
26
|
+
feature.elements.forEach(scenario => {
|
|
27
|
+
if (scenario.type === 'background') {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
stats.scenarios++;
|
|
31
|
+
scenario.steps.forEach(step => {
|
|
32
|
+
stats.steps++;
|
|
33
|
+
stats.duration += step.result.duration ?? 0;
|
|
34
|
+
switch (step.result.status) {
|
|
35
|
+
case 'passed':
|
|
36
|
+
stats.passed++;
|
|
37
|
+
break;
|
|
38
|
+
case 'failed':
|
|
39
|
+
stats.failed++;
|
|
40
|
+
break;
|
|
41
|
+
case 'skipped':
|
|
42
|
+
stats.skipped++;
|
|
43
|
+
break;
|
|
44
|
+
case 'pending':
|
|
45
|
+
stats.pending++;
|
|
46
|
+
break;
|
|
47
|
+
case 'undefined':
|
|
48
|
+
stats.undefined++;
|
|
49
|
+
break;
|
|
50
|
+
case 'ambiguous':
|
|
51
|
+
stats.ambiguous++;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
stats.passRate = calculatePassRate(stats.passed, stats.steps);
|
|
58
|
+
return stats;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Calculate statistics for a single feature
|
|
62
|
+
* @param feature - Gherkin feature to analyze
|
|
63
|
+
* @returns Object containing total scenarios, status counts, and duration in nanoseconds
|
|
64
|
+
*/
|
|
65
|
+
static calculateFeatureStatistics(feature) {
|
|
66
|
+
const scenarios = feature.elements.filter(el => el.type === 'scenario');
|
|
67
|
+
const stats = {
|
|
68
|
+
total: scenarios.length,
|
|
69
|
+
passed: 0,
|
|
70
|
+
failed: 0,
|
|
71
|
+
skipped: 0,
|
|
72
|
+
pending: 0,
|
|
73
|
+
undefined: 0,
|
|
74
|
+
duration: 0,
|
|
75
|
+
};
|
|
76
|
+
scenarios.forEach(scenario => {
|
|
77
|
+
const status = calculateScenarioStatus(scenario.steps);
|
|
78
|
+
const duration = calculateScenarioDuration(scenario);
|
|
79
|
+
stats.duration += duration;
|
|
80
|
+
switch (status) {
|
|
81
|
+
case 'passed':
|
|
82
|
+
stats.passed++;
|
|
83
|
+
break;
|
|
84
|
+
case 'failed':
|
|
85
|
+
case 'undefined':
|
|
86
|
+
stats.failed++;
|
|
87
|
+
break;
|
|
88
|
+
case 'skipped':
|
|
89
|
+
stats.skipped++;
|
|
90
|
+
break;
|
|
91
|
+
case 'pending':
|
|
92
|
+
stats.pending++;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
return stats;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Calculate status breakdown across features, scenarios, and steps
|
|
100
|
+
* @param features - Array of Gherkin features to analyze
|
|
101
|
+
* @returns Nested object with status counts for features, scenarios, and steps
|
|
102
|
+
*/
|
|
103
|
+
static calculateStatusBreakdown(features) {
|
|
104
|
+
const breakdown = {
|
|
105
|
+
features: {
|
|
106
|
+
passed: 0,
|
|
107
|
+
failed: 0,
|
|
108
|
+
skipped: 0,
|
|
109
|
+
pending: 0,
|
|
110
|
+
},
|
|
111
|
+
scenarios: {
|
|
112
|
+
passed: 0,
|
|
113
|
+
failed: 0,
|
|
114
|
+
skipped: 0,
|
|
115
|
+
pending: 0,
|
|
116
|
+
undefined: 0,
|
|
117
|
+
},
|
|
118
|
+
steps: {
|
|
119
|
+
passed: 0,
|
|
120
|
+
failed: 0,
|
|
121
|
+
skipped: 0,
|
|
122
|
+
pending: 0,
|
|
123
|
+
undefined: 0,
|
|
124
|
+
ambiguous: 0,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
features.forEach(feature => {
|
|
128
|
+
const featureStatus = calculateFeatureStatus(feature.elements);
|
|
129
|
+
breakdown.features[featureStatus]++;
|
|
130
|
+
feature.elements.forEach(scenario => {
|
|
131
|
+
if (scenario.type === 'background') {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const scenarioStatus = calculateScenarioStatus(scenario.steps);
|
|
135
|
+
breakdown.scenarios[scenarioStatus]++;
|
|
136
|
+
scenario.steps.forEach(step => {
|
|
137
|
+
breakdown.steps[step.result.status]++;
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
return breakdown;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Process features with calculated status and duration for each feature and scenario
|
|
145
|
+
* @param features - Array of Gherkin features to process
|
|
146
|
+
* @returns Array of processed features with computed status, duration, and enriched scenarios
|
|
147
|
+
*/
|
|
148
|
+
static processFeatures(features) {
|
|
149
|
+
return features.map(feature => {
|
|
150
|
+
const scenarios = feature.elements
|
|
151
|
+
.filter(el => el.type === 'scenario')
|
|
152
|
+
.map(scenario => ({
|
|
153
|
+
...scenario,
|
|
154
|
+
status: calculateScenarioStatus(scenario.steps),
|
|
155
|
+
duration: calculateScenarioDuration(scenario),
|
|
156
|
+
featureName: feature.name,
|
|
157
|
+
featureId: feature.id,
|
|
158
|
+
}));
|
|
159
|
+
const status = calculateFeatureStatus(feature.elements);
|
|
160
|
+
const duration = scenarios.reduce((sum, s) => sum + s.duration, 0);
|
|
161
|
+
return {
|
|
162
|
+
...feature,
|
|
163
|
+
status,
|
|
164
|
+
duration,
|
|
165
|
+
scenarios,
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Extract all failed scenarios with error details
|
|
171
|
+
* @param features - Array of Gherkin features to search
|
|
172
|
+
* @returns Array of failed scenario objects with feature name, scenario name, failing step, error message, and tags
|
|
173
|
+
*/
|
|
174
|
+
static getFailedScenarios(features) {
|
|
175
|
+
const failed = [];
|
|
176
|
+
features.forEach(feature => {
|
|
177
|
+
feature.elements.forEach(scenario => {
|
|
178
|
+
if (scenario.type === 'background') {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const failedStep = scenario.steps.find(step => step.result.status === 'failed' ||
|
|
182
|
+
step.result.status === 'undefined' ||
|
|
183
|
+
step.result.status === 'ambiguous');
|
|
184
|
+
if (failedStep) {
|
|
185
|
+
failed.push({
|
|
186
|
+
feature: feature.name,
|
|
187
|
+
scenario: scenario.name,
|
|
188
|
+
step: `${failedStep.keyword}${failedStep.name}`,
|
|
189
|
+
error: failedStep.result.error_message ?? 'No error message',
|
|
190
|
+
tags: [
|
|
191
|
+
...(feature.tags ?? []).map(t => t.name),
|
|
192
|
+
...(scenario.tags ?? []).map(t => t.name),
|
|
193
|
+
],
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
return failed;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get the slowest scenarios sorted by duration
|
|
202
|
+
* @param features - Array of Gherkin features to analyze
|
|
203
|
+
* @param count - Maximum number of scenarios to return (default: 10)
|
|
204
|
+
* @returns Array of scenario objects with feature name, scenario name, and duration in nanoseconds, sorted by duration descending
|
|
205
|
+
*/
|
|
206
|
+
static getTopSlowestScenarios(features, count = 10) {
|
|
207
|
+
const scenarios = [];
|
|
208
|
+
features.forEach(feature => {
|
|
209
|
+
feature.elements.forEach(scenario => {
|
|
210
|
+
if (scenario.type === 'background') {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
scenarios.push({
|
|
214
|
+
feature: feature.name,
|
|
215
|
+
scenario: scenario.name,
|
|
216
|
+
duration: calculateScenarioDuration(scenario),
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
return scenarios.sort((a, b) => b.duration - a.duration).slice(0, count);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Calculate time-based statistics across all scenarios
|
|
224
|
+
* @param features - Array of Gherkin features to analyze
|
|
225
|
+
* @returns Object with min, max, average, median, and total duration in nanoseconds
|
|
226
|
+
*/
|
|
227
|
+
static calculateTimeStatistics(features) {
|
|
228
|
+
const durations = [];
|
|
229
|
+
features.forEach(feature => {
|
|
230
|
+
feature.elements.forEach(scenario => {
|
|
231
|
+
if (scenario.type === 'background') {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
durations.push(calculateScenarioDuration(scenario));
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
if (durations.length === 0) {
|
|
238
|
+
return {
|
|
239
|
+
min: 0,
|
|
240
|
+
max: 0,
|
|
241
|
+
average: 0,
|
|
242
|
+
median: 0,
|
|
243
|
+
total: 0,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
durations.sort((a, b) => a - b);
|
|
247
|
+
return {
|
|
248
|
+
min: durations[0],
|
|
249
|
+
max: durations[durations.length - 1],
|
|
250
|
+
average: durations.reduce((a, b) => a + b, 0) / durations.length,
|
|
251
|
+
median: durations[Math.floor(durations.length / 2)],
|
|
252
|
+
total: durations.reduce((a, b) => a + b, 0),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=statistics.js.map
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Generator - Creates HTML report from data
|
|
3
|
+
*/
|
|
4
|
+
import { ChartData, ProcessedFeature, ReportOptions, ReportStatistics } from './types.js';
|
|
5
|
+
export declare class TemplateGenerator {
|
|
6
|
+
private options;
|
|
7
|
+
constructor(options: ReportOptions);
|
|
8
|
+
/**
|
|
9
|
+
* Register Handlebars helpers for formatting, status handling, and data manipulation in templates
|
|
10
|
+
*/
|
|
11
|
+
private registerHelpers;
|
|
12
|
+
/**
|
|
13
|
+
* Generate complete HTML report from processed data
|
|
14
|
+
* @param features - Processed features with calculated status and duration
|
|
15
|
+
* @param statistics - Report statistics including counts and pass rate
|
|
16
|
+
* @param chartData - Chart.js data for visualization
|
|
17
|
+
* @returns Complete HTML report as a string
|
|
18
|
+
*/
|
|
19
|
+
generateReport(features: ProcessedFeature[], statistics: ReportStatistics, chartData: ChartData): string;
|
|
20
|
+
/**
|
|
21
|
+
* Get main HTML template structure with embedded styles and scripts
|
|
22
|
+
* @returns HTML template string with placeholders for Handlebars compilation
|
|
23
|
+
*/
|
|
24
|
+
private getMainTemplate;
|
|
25
|
+
/**
|
|
26
|
+
* Get header template with branding and report info
|
|
27
|
+
* @returns HTML template string for the report header section
|
|
28
|
+
*/
|
|
29
|
+
private getHeaderTemplate;
|
|
30
|
+
/**
|
|
31
|
+
* Get statistics overview template with test execution summary cards
|
|
32
|
+
* @returns HTML template string for statistics display
|
|
33
|
+
*/
|
|
34
|
+
private getStatisticsTemplate;
|
|
35
|
+
/**
|
|
36
|
+
* Get charts section template for status distribution and pass rate visualization
|
|
37
|
+
* @returns HTML template string with canvas elements for Chart.js
|
|
38
|
+
*/
|
|
39
|
+
private getChartsTemplate;
|
|
40
|
+
/**
|
|
41
|
+
* Get metadata section template for browser, platform, and custom data display
|
|
42
|
+
* @returns HTML template string for optional metadata sections
|
|
43
|
+
*/
|
|
44
|
+
private getMetadataTemplate;
|
|
45
|
+
/**
|
|
46
|
+
* Get features list template with search filter and feature cards
|
|
47
|
+
* @returns HTML template string for features section
|
|
48
|
+
*/
|
|
49
|
+
private getFeaturesListTemplate;
|
|
50
|
+
/**
|
|
51
|
+
* Get filter controls template for searching and status filtering
|
|
52
|
+
* @returns HTML template string with search input and filter buttons
|
|
53
|
+
*/
|
|
54
|
+
private getFilterTemplate;
|
|
55
|
+
/**
|
|
56
|
+
* Get feature card template with collapsible scenarios
|
|
57
|
+
* @returns HTML template string for individual feature display
|
|
58
|
+
*/
|
|
59
|
+
private getFeatureCardTemplate;
|
|
60
|
+
/**
|
|
61
|
+
* Get feature header template with title, tags, and toggle controls
|
|
62
|
+
* @returns HTML template string for feature header with collapsible functionality
|
|
63
|
+
*/
|
|
64
|
+
private getFeatureHeaderTemplate;
|
|
65
|
+
/**
|
|
66
|
+
* Get scenario card template with collapsible steps
|
|
67
|
+
* @returns HTML template string for individual scenario display
|
|
68
|
+
*/
|
|
69
|
+
private getScenarioCardTemplate;
|
|
70
|
+
/**
|
|
71
|
+
* Get scenario header template with title, tags, and toggle controls
|
|
72
|
+
* @returns HTML template string for scenario header with collapsible functionality
|
|
73
|
+
*/
|
|
74
|
+
private getScenarioHeaderTemplate;
|
|
75
|
+
/**
|
|
76
|
+
* Get steps list template with errors, data tables, and screenshots
|
|
77
|
+
* @returns HTML template string for scenario steps display
|
|
78
|
+
*/
|
|
79
|
+
private getStepsListTemplate;
|
|
80
|
+
/**
|
|
81
|
+
* Get footer template with branding and version info
|
|
82
|
+
* @returns HTML template string for report footer
|
|
83
|
+
*/
|
|
84
|
+
private getFooterTemplate;
|
|
85
|
+
/**
|
|
86
|
+
* Get CSS styles from template file
|
|
87
|
+
* @returns CSS stylesheet string for report styling
|
|
88
|
+
*/
|
|
89
|
+
private getStyles;
|
|
90
|
+
/**
|
|
91
|
+
* Generate custom CSS color variables if colors option is provided
|
|
92
|
+
* @returns CSS custom properties string with color overrides, or empty string if no colors specified
|
|
93
|
+
*/
|
|
94
|
+
private getCustomColorStyles;
|
|
95
|
+
/**
|
|
96
|
+
* Get JavaScript code from template file for report interactivity
|
|
97
|
+
* @returns JavaScript code string for charts, filtering, and collapsible sections
|
|
98
|
+
*/
|
|
99
|
+
private getScripts;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=template-generator.d.ts.map
|