executable-stories-formatters 0.7.15 → 0.8.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/dist/cli.js +217 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +217 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +217 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -319,7 +319,7 @@ interface FormatterOptions {
|
|
|
319
319
|
includeTags?: string[];
|
|
320
320
|
/** Tags to exclude test cases (any match). Applied after includeTags. */
|
|
321
321
|
excludeTags?: string[];
|
|
322
|
-
/** Output formats to generate. Default: ["
|
|
322
|
+
/** Output formats to generate. Default: ["html"] */
|
|
323
323
|
formats?: OutputFormat[];
|
|
324
324
|
/** Output directory for generated reports. Default: "reports" */
|
|
325
325
|
outputDir?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -319,7 +319,7 @@ interface FormatterOptions {
|
|
|
319
319
|
includeTags?: string[];
|
|
320
320
|
/** Tags to exclude test cases (any match). Applied after includeTags. */
|
|
321
321
|
excludeTags?: string[];
|
|
322
|
-
/** Output formats to generate. Default: ["
|
|
322
|
+
/** Output formats to generate. Default: ["html"] */
|
|
323
323
|
formats?: OutputFormat[];
|
|
324
324
|
/** Output directory for generated reports. Default: "reports" */
|
|
325
325
|
outputDir?: string;
|
package/dist/index.js
CHANGED
|
@@ -1321,11 +1321,53 @@ function initKeyboardShortcuts() {
|
|
|
1321
1321
|
});
|
|
1322
1322
|
}
|
|
1323
1323
|
|
|
1324
|
-
// Collapse/expand functionality
|
|
1324
|
+
// Collapse/expand functionality (persisted in localStorage)
|
|
1325
|
+
var COLLAPSE_KEY = 'es-collapsed-ids';
|
|
1326
|
+
|
|
1327
|
+
function loadCollapseState() {
|
|
1328
|
+
try {
|
|
1329
|
+
var raw = localStorage.getItem(COLLAPSE_KEY);
|
|
1330
|
+
return raw ? new Set(JSON.parse(raw)) : new Set();
|
|
1331
|
+
} catch (e) {
|
|
1332
|
+
return new Set();
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
function saveCollapseState(set) {
|
|
1337
|
+
try {
|
|
1338
|
+
localStorage.setItem(COLLAPSE_KEY, JSON.stringify(Array.from(set)));
|
|
1339
|
+
} catch (e) { /* quota or disabled */ }
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
function persistCollapse(container) {
|
|
1343
|
+
if (!container || !container.id) return;
|
|
1344
|
+
var state = loadCollapseState();
|
|
1345
|
+
if (container.classList.contains('collapsed')) {
|
|
1346
|
+
state.add(container.id);
|
|
1347
|
+
} else {
|
|
1348
|
+
state.delete(container.id);
|
|
1349
|
+
}
|
|
1350
|
+
saveCollapseState(state);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1325
1353
|
function toggleCollapse(header, container) {
|
|
1326
1354
|
container?.classList.toggle('collapsed');
|
|
1327
1355
|
const isCollapsed = container?.classList.contains('collapsed');
|
|
1328
1356
|
header.setAttribute('aria-expanded', !isCollapsed);
|
|
1357
|
+
persistCollapse(container);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
function restoreCollapseState() {
|
|
1361
|
+
var state = loadCollapseState();
|
|
1362
|
+
if (state.size === 0) return;
|
|
1363
|
+
state.forEach(function(id) {
|
|
1364
|
+
var el = document.getElementById(id);
|
|
1365
|
+
if (!el) return;
|
|
1366
|
+
if (!el.classList.contains('feature') && !el.classList.contains('scenario')) return;
|
|
1367
|
+
el.classList.add('collapsed');
|
|
1368
|
+
var header = el.querySelector('.feature-header, .scenario-header');
|
|
1369
|
+
if (header) header.setAttribute('aria-expanded', 'false');
|
|
1370
|
+
});
|
|
1329
1371
|
}
|
|
1330
1372
|
|
|
1331
1373
|
function initCollapse() {
|
|
@@ -1372,14 +1414,20 @@ function expandAll() {
|
|
|
1372
1414
|
const header = el.querySelector('.feature-header, .scenario-header, .trace-view-header');
|
|
1373
1415
|
header?.setAttribute('aria-expanded', 'true');
|
|
1374
1416
|
});
|
|
1417
|
+
saveCollapseState(new Set());
|
|
1375
1418
|
}
|
|
1376
1419
|
|
|
1377
1420
|
function collapseAll() {
|
|
1421
|
+
var ids = new Set();
|
|
1378
1422
|
document.querySelectorAll('.feature, .scenario, .trace-view').forEach(el => {
|
|
1379
1423
|
el.classList.add('collapsed');
|
|
1380
1424
|
const header = el.querySelector('.feature-header, .scenario-header, .trace-view-header');
|
|
1381
1425
|
header?.setAttribute('aria-expanded', 'false');
|
|
1426
|
+
if (el.id && (el.classList.contains('feature') || el.classList.contains('scenario'))) {
|
|
1427
|
+
ids.add(el.id);
|
|
1428
|
+
}
|
|
1382
1429
|
});
|
|
1430
|
+
saveCollapseState(ids);
|
|
1383
1431
|
}
|
|
1384
1432
|
|
|
1385
1433
|
// Detail level toggle
|
|
@@ -1506,6 +1554,68 @@ function copyScenarioAsMarkdown(scenarioId) {
|
|
|
1506
1554
|
});
|
|
1507
1555
|
}
|
|
1508
1556
|
|
|
1557
|
+
// Copy scenario as Claude-ready prompt (failure investigation context)
|
|
1558
|
+
function copyScenarioAsPrompt(scenarioId) {
|
|
1559
|
+
var scenario = document.getElementById(scenarioId);
|
|
1560
|
+
if (!scenario) return;
|
|
1561
|
+
|
|
1562
|
+
var feature = scenario.closest('.feature');
|
|
1563
|
+
var featureTitle = feature ? (feature.querySelector('.feature-title') || {}).textContent || '' : '';
|
|
1564
|
+
var title = (scenario.querySelector('.scenario-name') || {}).textContent || '';
|
|
1565
|
+
var statusEl = scenario.querySelector('.status-icon');
|
|
1566
|
+
var status = statusEl && statusEl.classList.contains('status-passed') ? 'passed' :
|
|
1567
|
+
statusEl && statusEl.classList.contains('status-failed') ? 'failed' :
|
|
1568
|
+
statusEl && statusEl.classList.contains('status-skipped') ? 'skipped' : 'pending';
|
|
1569
|
+
var sourceLink = scenario.querySelector('.source-link');
|
|
1570
|
+
var source = sourceLink ? sourceLink.textContent || '' : '';
|
|
1571
|
+
var tags = Array.from(scenario.querySelectorAll('.scenario-meta .tag')).map(function(t) { return t.textContent.trim(); });
|
|
1572
|
+
var steps = scenario.querySelectorAll('.step, .step.continuation');
|
|
1573
|
+
|
|
1574
|
+
var lines = [];
|
|
1575
|
+
lines.push('I need help investigating a failing executable-story scenario.');
|
|
1576
|
+
lines.push('');
|
|
1577
|
+
if (featureTitle.trim()) lines.push('Feature: ' + featureTitle.trim());
|
|
1578
|
+
lines.push('Scenario: ' + title.trim());
|
|
1579
|
+
lines.push('Status: ' + status);
|
|
1580
|
+
if (source.trim()) lines.push('Source: ' + source.trim());
|
|
1581
|
+
if (tags.length > 0) lines.push('Tags: ' + tags.join(', '));
|
|
1582
|
+
lines.push('');
|
|
1583
|
+
lines.push('Steps:');
|
|
1584
|
+
steps.forEach(function(step) {
|
|
1585
|
+
var keyword = step.getAttribute('data-keyword') || '';
|
|
1586
|
+
var text = step.getAttribute('data-text') || '';
|
|
1587
|
+
var stepStatusEl = step.querySelector('.step-status');
|
|
1588
|
+
var marker = ' ';
|
|
1589
|
+
if (stepStatusEl) {
|
|
1590
|
+
if (stepStatusEl.classList.contains('status-failed')) marker = 'x ';
|
|
1591
|
+
else if (stepStatusEl.classList.contains('status-passed')) marker = '+ ';
|
|
1592
|
+
else if (stepStatusEl.classList.contains('status-skipped')) marker = '- ';
|
|
1593
|
+
}
|
|
1594
|
+
lines.push(marker + keyword + ' ' + text);
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
var errorBox = scenario.querySelector('.error-message');
|
|
1598
|
+
if (errorBox) {
|
|
1599
|
+
lines.push('');
|
|
1600
|
+
lines.push('Error:');
|
|
1601
|
+
lines.push((errorBox.textContent || '').trim());
|
|
1602
|
+
}
|
|
1603
|
+
var stackBox = scenario.querySelector('.error-stack');
|
|
1604
|
+
if (stackBox) {
|
|
1605
|
+
lines.push('');
|
|
1606
|
+
lines.push('Stack:');
|
|
1607
|
+
lines.push((stackBox.textContent || '').trim());
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
lines.push('');
|
|
1611
|
+
lines.push('Please read the source file, identify the root cause, and propose a fix.');
|
|
1612
|
+
|
|
1613
|
+
var text = lines.join('\\n');
|
|
1614
|
+
navigator.clipboard.writeText(text).then(function() {
|
|
1615
|
+
showCopyToast(scenario);
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1509
1619
|
// Hash scroll on load
|
|
1510
1620
|
function initHashScroll() {
|
|
1511
1621
|
if (!location.hash) return;
|
|
@@ -1675,6 +1785,7 @@ function generateScript(options) {
|
|
|
1675
1785
|
initCalls.push("initStatusFilter();");
|
|
1676
1786
|
initCalls.push("initKeyboardShortcuts();");
|
|
1677
1787
|
initCalls.push("initCollapse();");
|
|
1788
|
+
initCalls.push("restoreCollapseState();");
|
|
1678
1789
|
initCalls.push("initDetailLevel();");
|
|
1679
1790
|
initCalls.push("applyAllFilters();");
|
|
1680
1791
|
initCalls.push("initHashScroll();");
|
|
@@ -3782,6 +3893,33 @@ body {
|
|
|
3782
3893
|
color: var(--primary);
|
|
3783
3894
|
}
|
|
3784
3895
|
|
|
3896
|
+
.copy-prompt-btn {
|
|
3897
|
+
display: inline-flex;
|
|
3898
|
+
align-items: center;
|
|
3899
|
+
justify-content: center;
|
|
3900
|
+
width: 1.5rem;
|
|
3901
|
+
height: 1.5rem;
|
|
3902
|
+
border: none;
|
|
3903
|
+
background: none;
|
|
3904
|
+
color: var(--muted-foreground);
|
|
3905
|
+
cursor: pointer;
|
|
3906
|
+
opacity: 0.6;
|
|
3907
|
+
transition: opacity 0.15s ease, transform 0.15s ease;
|
|
3908
|
+
font-size: 0.95rem;
|
|
3909
|
+
padding: 0;
|
|
3910
|
+
flex-shrink: 0;
|
|
3911
|
+
}
|
|
3912
|
+
|
|
3913
|
+
.scenario-header:hover .copy-prompt-btn,
|
|
3914
|
+
.copy-prompt-btn:focus-visible {
|
|
3915
|
+
opacity: 1;
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3918
|
+
.copy-prompt-btn:hover {
|
|
3919
|
+
color: var(--primary);
|
|
3920
|
+
transform: scale(1.15);
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3785
3923
|
/* ============================================================================
|
|
3786
3924
|
Keyboard Navigation
|
|
3787
3925
|
============================================================================ */
|
|
@@ -4019,6 +4157,82 @@ a.toc-title:hover {
|
|
|
4019
4157
|
outline-offset: 2px;
|
|
4020
4158
|
}
|
|
4021
4159
|
|
|
4160
|
+
/* ============================================================================
|
|
4161
|
+
Mobile responsive refinements
|
|
4162
|
+
============================================================================ */
|
|
4163
|
+
@media (max-width: 640px) {
|
|
4164
|
+
.container {
|
|
4165
|
+
padding: 0.875rem;
|
|
4166
|
+
}
|
|
4167
|
+
|
|
4168
|
+
.header {
|
|
4169
|
+
flex-direction: column;
|
|
4170
|
+
align-items: stretch;
|
|
4171
|
+
gap: 0.75rem;
|
|
4172
|
+
}
|
|
4173
|
+
|
|
4174
|
+
.header-actions {
|
|
4175
|
+
flex-wrap: wrap;
|
|
4176
|
+
gap: 0.5rem;
|
|
4177
|
+
}
|
|
4178
|
+
|
|
4179
|
+
.search-input {
|
|
4180
|
+
width: 100%;
|
|
4181
|
+
flex: 1 1 100%;
|
|
4182
|
+
min-width: 0;
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4185
|
+
.header h1 {
|
|
4186
|
+
font-size: 1.25rem;
|
|
4187
|
+
}
|
|
4188
|
+
|
|
4189
|
+
.scenario-header,
|
|
4190
|
+
.feature-header {
|
|
4191
|
+
flex-wrap: wrap;
|
|
4192
|
+
gap: 0.5rem;
|
|
4193
|
+
}
|
|
4194
|
+
|
|
4195
|
+
.scenario-meta {
|
|
4196
|
+
flex-wrap: wrap;
|
|
4197
|
+
}
|
|
4198
|
+
|
|
4199
|
+
.scenario-actions {
|
|
4200
|
+
flex-wrap: wrap;
|
|
4201
|
+
}
|
|
4202
|
+
|
|
4203
|
+
/* Always-visible action buttons on touch (no hover) */
|
|
4204
|
+
.copy-scenario-btn,
|
|
4205
|
+
.copy-prompt-btn,
|
|
4206
|
+
.permalink-anchor {
|
|
4207
|
+
opacity: 1 !important;
|
|
4208
|
+
}
|
|
4209
|
+
|
|
4210
|
+
.summary-card {
|
|
4211
|
+
padding: 0.75rem 0.875rem;
|
|
4212
|
+
}
|
|
4213
|
+
|
|
4214
|
+
.summary-card .value {
|
|
4215
|
+
font-size: 1.5rem;
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4218
|
+
.tag-bar {
|
|
4219
|
+
overflow-x: auto;
|
|
4220
|
+
-webkit-overflow-scrolling: touch;
|
|
4221
|
+
}
|
|
4222
|
+
|
|
4223
|
+
.shortcuts-overlay {
|
|
4224
|
+
padding: 1rem;
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
@media (hover: none) and (pointer: coarse) {
|
|
4229
|
+
.copy-scenario-btn,
|
|
4230
|
+
.copy-prompt-btn,
|
|
4231
|
+
.permalink-anchor {
|
|
4232
|
+
opacity: 1;
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
|
|
4022
4236
|
`;
|
|
4023
4237
|
|
|
4024
4238
|
// src/formatters/html/themes/default.ts
|
|
@@ -13745,6 +13959,7 @@ function renderScenario(args, deps) {
|
|
|
13745
13959
|
</div>
|
|
13746
13960
|
<div class="scenario-actions">
|
|
13747
13961
|
<button class="copy-scenario-btn" onclick="copyScenarioAsMarkdown('scenario-${tc.id}')" aria-label="Copy scenario as markdown" title="Copy as Markdown"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>
|
|
13962
|
+
${tc.status === "failed" ? `<button class="copy-prompt-btn" onclick="copyScenarioAsPrompt('scenario-${tc.id}')" aria-label="Copy as Claude prompt" title="Copy as AI prompt">\u2728</button>` : ""}
|
|
13748
13963
|
<button class="permalink-anchor" onclick="copyPermalink('scenario-${tc.id}')" aria-label="Copy link to scenario" title="Copy link">#</button>
|
|
13749
13964
|
<span class="scenario-duration">${duration}</span>
|
|
13750
13965
|
</div>
|
|
@@ -19540,7 +19755,7 @@ var ReportGenerator = class {
|
|
|
19540
19755
|
exclude: options.exclude ?? [],
|
|
19541
19756
|
includeTags: options.includeTags ?? [],
|
|
19542
19757
|
excludeTags: options.excludeTags ?? [],
|
|
19543
|
-
formats: options.formats ?? ["
|
|
19758
|
+
formats: options.formats ?? ["html"],
|
|
19544
19759
|
outputDir: options.outputDir ?? "reports",
|
|
19545
19760
|
outputName: options.outputName ?? "index",
|
|
19546
19761
|
outputNameTimestamp: options.outputNameTimestamp ?? false,
|