executable-stories-formatters 0.3.0 → 0.4.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/adapters.d.cts +1 -1
- package/dist/adapters.d.ts +1 -1
- package/dist/cli.js +322 -4
- package/dist/cli.js.map +1 -1
- package/dist/{index-DCJ0NvAp.d.cts → index-DyeUWfYK.d.cts} +26 -1
- package/dist/{index-DCJ0NvAp.d.ts → index-DyeUWfYK.d.ts} +26 -1
- package/dist/index.cjs +324 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +324 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/adapters.d.cts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { J as JestAdapterOptions, i as JestAggregatedResult, j as JestFileResult, k as JestTestResult, P as PlaywrightAdapterOptions,
|
|
1
|
+
export { J as JestAdapterOptions, i as JestAggregatedResult, j as JestFileResult, k as JestTestResult, P as PlaywrightAdapterOptions, m as PlaywrightAnnotation, n as PlaywrightAttachment, o as PlaywrightError, p as PlaywrightLocation, q as PlaywrightStatus, r as PlaywrightTestCase, s as PlaywrightTestResult, y as StoryFileReport, V as VitestAdapterOptions, z as VitestSerializedError, A as VitestState, B as VitestTestCase, C as VitestTestModule, E as VitestTestResult, e as adaptJestRun, f as adaptPlaywrightRun, g as adaptVitestRun } from './index-DyeUWfYK.cjs';
|
package/dist/adapters.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { J as JestAdapterOptions, i as JestAggregatedResult, j as JestFileResult, k as JestTestResult, P as PlaywrightAdapterOptions,
|
|
1
|
+
export { J as JestAdapterOptions, i as JestAggregatedResult, j as JestFileResult, k as JestTestResult, P as PlaywrightAdapterOptions, m as PlaywrightAnnotation, n as PlaywrightAttachment, o as PlaywrightError, p as PlaywrightLocation, q as PlaywrightStatus, r as PlaywrightTestCase, s as PlaywrightTestResult, y as StoryFileReport, V as VitestAdapterOptions, z as VitestSerializedError, A as VitestState, B as VitestTestCase, C as VitestTestModule, E as VitestTestResult, e as adaptJestRun, f as adaptPlaywrightRun, g as adaptVitestRun } from './index-DyeUWfYK.js';
|
package/dist/cli.js
CHANGED
|
@@ -1101,17 +1101,17 @@ function initCollapse() {
|
|
|
1101
1101
|
}
|
|
1102
1102
|
|
|
1103
1103
|
function expandAll() {
|
|
1104
|
-
document.querySelectorAll('.feature, .scenario').forEach(el => {
|
|
1104
|
+
document.querySelectorAll('.feature, .scenario, .trace-view').forEach(el => {
|
|
1105
1105
|
el.classList.remove('collapsed');
|
|
1106
|
-
const header = el.querySelector('.feature-header, .scenario-header');
|
|
1106
|
+
const header = el.querySelector('.feature-header, .scenario-header, .trace-view-header');
|
|
1107
1107
|
header?.setAttribute('aria-expanded', 'true');
|
|
1108
1108
|
});
|
|
1109
1109
|
}
|
|
1110
1110
|
|
|
1111
1111
|
function collapseAll() {
|
|
1112
|
-
document.querySelectorAll('.feature, .scenario').forEach(el => {
|
|
1112
|
+
document.querySelectorAll('.feature, .scenario, .trace-view').forEach(el => {
|
|
1113
1113
|
el.classList.add('collapsed');
|
|
1114
|
-
const header = el.querySelector('.feature-header, .scenario-header');
|
|
1114
|
+
const header = el.querySelector('.feature-header, .scenario-header, .trace-view-header');
|
|
1115
1115
|
header?.setAttribute('aria-expanded', 'false');
|
|
1116
1116
|
});
|
|
1117
1117
|
}
|
|
@@ -2638,6 +2638,132 @@ body {
|
|
|
2638
2638
|
background: none;
|
|
2639
2639
|
}
|
|
2640
2640
|
|
|
2641
|
+
/* ============================================================================
|
|
2642
|
+
Trace View - OTel span waterfall
|
|
2643
|
+
============================================================================ */
|
|
2644
|
+
.trace-view {
|
|
2645
|
+
margin-top: 0.75rem;
|
|
2646
|
+
border: 1px solid var(--border);
|
|
2647
|
+
border-radius: calc(var(--radius) - 2px);
|
|
2648
|
+
overflow: hidden;
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
.trace-view-header {
|
|
2652
|
+
display: flex;
|
|
2653
|
+
align-items: center;
|
|
2654
|
+
gap: 0.5rem;
|
|
2655
|
+
padding: 0.5rem 0.75rem;
|
|
2656
|
+
background: var(--card);
|
|
2657
|
+
cursor: pointer;
|
|
2658
|
+
user-select: none;
|
|
2659
|
+
font-size: 0.8125rem;
|
|
2660
|
+
font-weight: 500;
|
|
2661
|
+
color: var(--foreground);
|
|
2662
|
+
transition: background-color 0.15s ease;
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
.trace-view-header:hover {
|
|
2666
|
+
background: var(--accordion-header-hover);
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
.trace-view-count {
|
|
2670
|
+
font-size: 0.6875rem;
|
|
2671
|
+
font-weight: 500;
|
|
2672
|
+
padding: 0.125rem 0.5rem;
|
|
2673
|
+
background: var(--success-light);
|
|
2674
|
+
color: var(--success);
|
|
2675
|
+
border: 1px solid var(--success-border);
|
|
2676
|
+
border-radius: 9999px;
|
|
2677
|
+
font-family: var(--font-mono);
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
.trace-view-content {
|
|
2681
|
+
border-top: 1px solid var(--border);
|
|
2682
|
+
padding: 0.5rem 0.75rem;
|
|
2683
|
+
background: var(--accordion-content-bg);
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
.trace-view.collapsed .trace-view-content {
|
|
2687
|
+
display: none;
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
.trace-view-axis {
|
|
2691
|
+
display: flex;
|
|
2692
|
+
justify-content: space-between;
|
|
2693
|
+
font-size: 0.625rem;
|
|
2694
|
+
font-family: var(--font-mono);
|
|
2695
|
+
color: var(--muted-foreground);
|
|
2696
|
+
padding-bottom: 0.375rem;
|
|
2697
|
+
margin-bottom: 0.375rem;
|
|
2698
|
+
border-bottom: 1px solid var(--border);
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
.trace-view-row {
|
|
2702
|
+
display: flex;
|
|
2703
|
+
align-items: center;
|
|
2704
|
+
gap: 0.5rem;
|
|
2705
|
+
padding: 0.1875rem 0;
|
|
2706
|
+
font-size: 0.75rem;
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
.trace-view-name {
|
|
2710
|
+
width: 35%;
|
|
2711
|
+
flex-shrink: 0;
|
|
2712
|
+
display: flex;
|
|
2713
|
+
align-items: center;
|
|
2714
|
+
gap: 0.375rem;
|
|
2715
|
+
font-family: var(--font-mono);
|
|
2716
|
+
white-space: nowrap;
|
|
2717
|
+
overflow: hidden;
|
|
2718
|
+
text-overflow: ellipsis;
|
|
2719
|
+
color: var(--foreground);
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2722
|
+
.trace-view-status-dot {
|
|
2723
|
+
width: 8px;
|
|
2724
|
+
height: 8px;
|
|
2725
|
+
border-radius: 50%;
|
|
2726
|
+
flex-shrink: 0;
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2729
|
+
.trace-view-status-ok { background: var(--success); }
|
|
2730
|
+
.trace-view-status-error { background: var(--error); }
|
|
2731
|
+
.trace-view-status-unset { background: var(--muted-foreground); }
|
|
2732
|
+
|
|
2733
|
+
.trace-view-bar-container {
|
|
2734
|
+
flex: 1;
|
|
2735
|
+
position: relative;
|
|
2736
|
+
height: 1.25rem;
|
|
2737
|
+
background: var(--muted);
|
|
2738
|
+
border-radius: 2px;
|
|
2739
|
+
}
|
|
2740
|
+
|
|
2741
|
+
.trace-view-bar {
|
|
2742
|
+
position: absolute;
|
|
2743
|
+
top: 0;
|
|
2744
|
+
height: 100%;
|
|
2745
|
+
border-radius: 2px;
|
|
2746
|
+
min-width: 2px;
|
|
2747
|
+
display: flex;
|
|
2748
|
+
align-items: center;
|
|
2749
|
+
padding: 0 0.375rem;
|
|
2750
|
+
font-size: 0.625rem;
|
|
2751
|
+
font-family: var(--font-mono);
|
|
2752
|
+
color: white;
|
|
2753
|
+
white-space: nowrap;
|
|
2754
|
+
overflow: hidden;
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
.trace-view-bar-ok { background: var(--success); }
|
|
2758
|
+
.trace-view-bar-error { background: var(--error); }
|
|
2759
|
+
.trace-view-bar-unset { background: var(--muted-foreground); }
|
|
2760
|
+
|
|
2761
|
+
@media print {
|
|
2762
|
+
.trace-view.collapsed .trace-view-content {
|
|
2763
|
+
display: block;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
|
|
2641
2767
|
`;
|
|
2642
2768
|
|
|
2643
2769
|
// src/formatters/html/renderers/status.ts
|
|
@@ -2962,6 +3088,10 @@ function renderScenario(args, deps) {
|
|
|
2962
3088
|
embedScreenshots: deps.embedScreenshots
|
|
2963
3089
|
}
|
|
2964
3090
|
);
|
|
3091
|
+
const traceView = deps.renderTraceView(
|
|
3092
|
+
{ spans: tc.story.otelSpans },
|
|
3093
|
+
{ escapeHtml: deps.escapeHtml }
|
|
3094
|
+
);
|
|
2965
3095
|
const collapsedClass = deps.startCollapsed ? " collapsed" : "";
|
|
2966
3096
|
const ariaExpanded = !deps.startCollapsed;
|
|
2967
3097
|
return `
|
|
@@ -2981,6 +3111,193 @@ function renderScenario(args, deps) {
|
|
|
2981
3111
|
${steps}
|
|
2982
3112
|
${error}
|
|
2983
3113
|
${attachments}
|
|
3114
|
+
${traceView}
|
|
3115
|
+
</div>
|
|
3116
|
+
</div>`;
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3119
|
+
// src/formatters/html/renderers/trace-view.ts
|
|
3120
|
+
var VALID_STATUSES = /* @__PURE__ */ new Set(["ok", "error", "unset"]);
|
|
3121
|
+
var TOOLTIP_MAX_LENGTH = 4096;
|
|
3122
|
+
function safeStatus(status) {
|
|
3123
|
+
return VALID_STATUSES.has(status) ? status : "unset";
|
|
3124
|
+
}
|
|
3125
|
+
function formatDuration(ms) {
|
|
3126
|
+
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
|
|
3127
|
+
return `${ms.toFixed(1)}ms`;
|
|
3128
|
+
}
|
|
3129
|
+
function clamp(value, min, max) {
|
|
3130
|
+
return Math.min(max, Math.max(min, value));
|
|
3131
|
+
}
|
|
3132
|
+
function normalizeSpans(spans) {
|
|
3133
|
+
const result = [];
|
|
3134
|
+
for (const span of spans) {
|
|
3135
|
+
if (!span || typeof span !== "object") continue;
|
|
3136
|
+
if (typeof span.spanId !== "string" || typeof span.name !== "string") continue;
|
|
3137
|
+
let startTimeMs;
|
|
3138
|
+
let durationMs;
|
|
3139
|
+
if (span.startTimeMs != null && span.durationMs != null) {
|
|
3140
|
+
startTimeMs = span.startTimeMs;
|
|
3141
|
+
durationMs = span.durationMs;
|
|
3142
|
+
} else if (span.startTimeUnixNano != null && span.endTimeUnixNano != null) {
|
|
3143
|
+
startTimeMs = span.startTimeUnixNano / 1e6;
|
|
3144
|
+
durationMs = (span.endTimeUnixNano - span.startTimeUnixNano) / 1e6;
|
|
3145
|
+
} else {
|
|
3146
|
+
continue;
|
|
3147
|
+
}
|
|
3148
|
+
durationMs = Math.max(0, durationMs);
|
|
3149
|
+
if (!isFinite(startTimeMs) || !isFinite(durationMs)) continue;
|
|
3150
|
+
result.push({
|
|
3151
|
+
spanId: span.spanId,
|
|
3152
|
+
parentSpanId: span.parentSpanId,
|
|
3153
|
+
name: span.name,
|
|
3154
|
+
startTimeMs,
|
|
3155
|
+
durationMs,
|
|
3156
|
+
status: safeStatus(span.status),
|
|
3157
|
+
statusMessage: span.statusMessage,
|
|
3158
|
+
attributes: span.attributes
|
|
3159
|
+
});
|
|
3160
|
+
}
|
|
3161
|
+
return result;
|
|
3162
|
+
}
|
|
3163
|
+
function buildTree(spans) {
|
|
3164
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3165
|
+
for (const span of spans) {
|
|
3166
|
+
let key = span.spanId;
|
|
3167
|
+
if (byId.has(key)) {
|
|
3168
|
+
let suffix = 2;
|
|
3169
|
+
while (byId.has(`${span.spanId}__dup${suffix}`)) suffix++;
|
|
3170
|
+
key = `${span.spanId}__dup${suffix}`;
|
|
3171
|
+
}
|
|
3172
|
+
byId.set(key, { span: { ...span, spanId: key }, children: [], depth: 0 });
|
|
3173
|
+
}
|
|
3174
|
+
const roots = [];
|
|
3175
|
+
for (const node of byId.values()) {
|
|
3176
|
+
const parentId = node.span.parentSpanId;
|
|
3177
|
+
const parent = parentId ? byId.get(parentId) : void 0;
|
|
3178
|
+
if (parent && parent !== node) {
|
|
3179
|
+
parent.children.push(node);
|
|
3180
|
+
} else {
|
|
3181
|
+
roots.push(node);
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
for (const node of byId.values()) {
|
|
3185
|
+
node.children.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
3186
|
+
}
|
|
3187
|
+
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
3188
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3189
|
+
function assignDepth(node, depth) {
|
|
3190
|
+
if (visited.has(node.span.spanId)) return;
|
|
3191
|
+
visited.add(node.span.spanId);
|
|
3192
|
+
node.depth = depth;
|
|
3193
|
+
for (const child of node.children) {
|
|
3194
|
+
assignDepth(child, depth + 1);
|
|
3195
|
+
}
|
|
3196
|
+
}
|
|
3197
|
+
for (const root of roots) {
|
|
3198
|
+
assignDepth(root, 0);
|
|
3199
|
+
}
|
|
3200
|
+
for (const node of byId.values()) {
|
|
3201
|
+
if (!visited.has(node.span.spanId)) {
|
|
3202
|
+
node.children = [];
|
|
3203
|
+
roots.push(node);
|
|
3204
|
+
assignDepth(node, 0);
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
3208
|
+
return roots;
|
|
3209
|
+
}
|
|
3210
|
+
function flattenTree(roots) {
|
|
3211
|
+
const result = [];
|
|
3212
|
+
function walk(node) {
|
|
3213
|
+
result.push(node);
|
|
3214
|
+
for (const child of node.children) {
|
|
3215
|
+
walk(child);
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
for (const root of roots) {
|
|
3219
|
+
walk(root);
|
|
3220
|
+
}
|
|
3221
|
+
return result;
|
|
3222
|
+
}
|
|
3223
|
+
function buildTooltip(span, escapeHtml2) {
|
|
3224
|
+
const parts = [];
|
|
3225
|
+
parts.push(`${span.name} (${formatDuration(span.durationMs)})`);
|
|
3226
|
+
if (span.statusMessage) {
|
|
3227
|
+
parts.push(`Status: ${span.statusMessage}`);
|
|
3228
|
+
}
|
|
3229
|
+
if (span.attributes) {
|
|
3230
|
+
const keys = Object.keys(span.attributes).sort();
|
|
3231
|
+
for (const key of keys) {
|
|
3232
|
+
const val = span.attributes[key];
|
|
3233
|
+
const formatted = Array.isArray(val) ? `[${val.map((v) => String(v)).join(", ")}]` : String(val);
|
|
3234
|
+
parts.push(`${key}=${formatted}`);
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
let text = parts.join("\n");
|
|
3238
|
+
if (text.length > TOOLTIP_MAX_LENGTH) {
|
|
3239
|
+
text = text.slice(0, TOOLTIP_MAX_LENGTH - 3) + "...";
|
|
3240
|
+
}
|
|
3241
|
+
return escapeHtml2(text);
|
|
3242
|
+
}
|
|
3243
|
+
function renderTraceView(args, deps) {
|
|
3244
|
+
if (!args.spans || args.spans.length === 0) return "";
|
|
3245
|
+
const normalized = normalizeSpans(args.spans);
|
|
3246
|
+
if (normalized.length === 0) return "";
|
|
3247
|
+
const roots = buildTree(normalized);
|
|
3248
|
+
const flat = flattenTree(roots);
|
|
3249
|
+
let minStart = Infinity;
|
|
3250
|
+
let maxEnd = -Infinity;
|
|
3251
|
+
for (const node of flat) {
|
|
3252
|
+
const s = node.span.startTimeMs;
|
|
3253
|
+
const e = s + node.span.durationMs;
|
|
3254
|
+
if (s < minStart) minStart = s;
|
|
3255
|
+
if (e > maxEnd) maxEnd = e;
|
|
3256
|
+
}
|
|
3257
|
+
let totalDuration = maxEnd - minStart;
|
|
3258
|
+
if (totalDuration <= 0) totalDuration = 1;
|
|
3259
|
+
const rows = flat.map((node) => {
|
|
3260
|
+
const { span, depth } = node;
|
|
3261
|
+
const indent = depth * 16;
|
|
3262
|
+
const minWidth = 0.5;
|
|
3263
|
+
let spanLeft = clamp(
|
|
3264
|
+
(span.startTimeMs - minStart) / totalDuration * 100,
|
|
3265
|
+
0,
|
|
3266
|
+
100
|
|
3267
|
+
);
|
|
3268
|
+
if (spanLeft + minWidth > 100) {
|
|
3269
|
+
spanLeft = 100 - minWidth;
|
|
3270
|
+
}
|
|
3271
|
+
const spanWidth = clamp(
|
|
3272
|
+
span.durationMs / totalDuration * 100,
|
|
3273
|
+
minWidth,
|
|
3274
|
+
100 - spanLeft
|
|
3275
|
+
);
|
|
3276
|
+
const tooltip = buildTooltip(span, deps.escapeHtml);
|
|
3277
|
+
const durationLabel = formatDuration(span.durationMs);
|
|
3278
|
+
return ` <div class="trace-view-row">
|
|
3279
|
+
<div class="trace-view-name" style="padding-left: ${indent}px" title="${deps.escapeHtml(span.name)}">
|
|
3280
|
+
<span class="trace-view-status-dot trace-view-status-${span.status}"></span>
|
|
3281
|
+
${deps.escapeHtml(span.name)}
|
|
3282
|
+
</div>
|
|
3283
|
+
<div class="trace-view-bar-container">
|
|
3284
|
+
<div class="trace-view-bar trace-view-bar-${span.status}" style="left: ${spanLeft.toFixed(2)}%; width: ${spanWidth.toFixed(2)}%" title="${tooltip}">${durationLabel}</div>
|
|
3285
|
+
</div>
|
|
3286
|
+
</div>`;
|
|
3287
|
+
}).join("\n");
|
|
3288
|
+
const axisEnd = formatDuration(maxEnd - minStart);
|
|
3289
|
+
return `<div class="trace-view collapsed">
|
|
3290
|
+
<div class="trace-view-header" role="button" tabindex="0" aria-expanded="false">
|
|
3291
|
+
<span>Spans</span>
|
|
3292
|
+
<span class="trace-view-count">${flat.length}</span>
|
|
3293
|
+
<span class="chevron">▼</span>
|
|
3294
|
+
</div>
|
|
3295
|
+
<div class="trace-view-content">
|
|
3296
|
+
<div class="trace-view-axis">
|
|
3297
|
+
<span>0ms</span>
|
|
3298
|
+
<span>${axisEnd}</span>
|
|
3299
|
+
</div>
|
|
3300
|
+
${rows}
|
|
2984
3301
|
</div>
|
|
2985
3302
|
</div>`;
|
|
2986
3303
|
}
|
|
@@ -3117,6 +3434,7 @@ function createHtmlFormatter(options = {}) {
|
|
|
3117
3434
|
renderDocs,
|
|
3118
3435
|
renderErrorBox: (args, d) => renderErrorBox(args, d),
|
|
3119
3436
|
renderAttachments: (args, d) => renderAttachments(args, d),
|
|
3437
|
+
renderTraceView: (args, d) => renderTraceView(args, d),
|
|
3120
3438
|
embedScreenshots: opts.embedScreenshots
|
|
3121
3439
|
};
|
|
3122
3440
|
const featureDeps = {
|