import type { Meta, StoryObj } from "@storybook/vue3-vite"; import { expect, userEvent, within } from "storybook/test"; import Waterfall from "./Waterfall.vue"; import type { TelemetryRecord, TraceNode } from "@/lib/telemetry"; const env = (messageId: string, causationId: string) => ({ messageId, causationId, correlationId: "c-9f8e", }); const t = (ms: number) => new Date(Date.UTC(2026, 0, 1, 0, 0, 0, ms)).toISOString(); function node(record: TelemetryRecord, children: TraceNode[] = []): TraceNode { return { record, children }; } const forest: TraceNode[] = [ node( { kind: "action.dispatched", name: "orders.place", ts: t(0), durationMs: 8, envelope: env("m1", "m1"), }, [ node( { kind: "query.executed", name: "orders.lookup", ts: t(8), durationMs: 120, envelope: env("m2", "m1"), }, [ node({ kind: "event.published", name: "orders.looked-up", ts: t(128), durationMs: 2, envelope: env("m4", "m2"), }), ], ), node({ kind: "action.failed", name: "orders.charge", ts: t(10), durationMs: 40, error: { name: "E", message: "declined" }, envelope: env("m3", "m1"), }), ], ), ]; const meta: Meta = { title: "Flow/Waterfall", component: Waterfall, tags: ["autodocs"], render: (args) => ({ components: { Waterfall }, setup: () => ({ args }), template: `
`, }), }; export default meta; type Story = StoryObj; export const Default: Story = { args: { forest }, play: async ({ canvasElement }) => { const c = within(canvasElement); await expect(c.getAllByTestId("waterfall-row")).toHaveLength(4); // The failed span is present and the critical path is highlighted. await expect(canvasElement.querySelector('[data-failed="true"]')).toBeTruthy(); await expect(canvasElement.querySelector('[data-critical="true"]')).toBeTruthy(); // Clicking a row selects it. await userEvent.click(c.getAllByTestId("waterfall-row")[1]!); }, }; export const Replaying: Story = { args: { forest, reveal: 2 }, };