inspector/clients/web/src/components/screens/LoggingScreen/LoggingScreen.stories.tsx
Cliff Hall a7178280f0
feat(export): wire History + Logs export JSON handlers (#1354) (#1367)
* feat(export): wire History + Logs export JSON handlers (#1354)

Replaces the `todoNoop` placeholders in App.tsx with real handlers that
serialize the current entries and trigger a browser download via the
existing `downloadJsonFile` helper.

- Adds `buildExportFilename(kind, serverId, now?)` next to the download
  helper. Produces sortable, filesystem-safe names like
  `inspector-history-alpha-2026-03-17T10-00-42.123Z.json` (URL-encodes
  server ids that contain slashes / spaces / colons, swaps `:` for `-`
  in the ISO timestamp so the file is safe on Windows).
- Wires `onExportHistory` (full MessageEntry list) and `onExportLogs`
  (the LogEntryData list the screen renders).
- Routes the existing Network export through the same filename helper
  for consistency.

Unit tests cover the filename builder, including the no-server-id
fallback, special-character encoding, and the default-`now` shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(export): tighten buildExportFilename signature + docs

- Introduce an `ExportKind = "history" | "logs" | "network"` union and
  use it as the type of the `kind` parameter. Typos like "hisotry" now
  fail at compile time and the supported export kinds are documented
  inline.
- Clarify the JSDoc: the segment is omitted when `serverId` is falsy
  (undefined OR empty string), matching the existing `serverId ? ... :
  undefined` check. New test pins the empty-string branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(logging): remove Copy All button from LogStreamPanel

Export now produces the same JSON the Copy All button used to dump to
the clipboard, so the button is redundant. History and Network panels
have no equivalent — dropping Copy All also brings Logs into parity.

Removes the prop from LogStreamPanel + LoggingScreen + InspectorView +
App.tsx, and updates the matching tests/stories. Tests now assert the
button is *not* in the document so a future re-introduction would have
to update the assertion deliberately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 19:06:28 -04:00

103 lines
2.3 KiB
TypeScript

import type { Meta, StoryObj } from "@storybook/react-vite";
import { fn } from "storybook/test";
import { LoggingScreen } from "./LoggingScreen";
import { mixedEntries } from "./LoggingScreen.fixtures";
import type { LogEntryData } from "../../elements/LogEntry/LogEntry";
const meta: Meta<typeof LoggingScreen> = {
title: "Screens/LoggingScreen",
component: LoggingScreen,
parameters: { layout: "fullscreen" },
args: {
currentLevel: "info",
onSetLevel: fn(),
onClear: fn(),
onExport: fn(),
autoScroll: true,
onToggleAutoScroll: fn(),
},
};
export default meta;
type Story = StoryObj<typeof LoggingScreen>;
export const Empty: Story = {
args: {
entries: [],
},
};
export const WithEntries: Story = {
args: {
entries: mixedEntries,
},
};
const allLevelEntries: LogEntryData[] = [
{
receivedAt: new Date("2026-03-17T10:00:01Z"),
params: {
level: "debug",
data: "Resolving transport handler for stdio connection",
logger: "transport",
},
},
{
receivedAt: new Date("2026-03-17T10:00:02Z"),
params: { level: "info", data: "MCP session initialized successfully" },
},
{
receivedAt: new Date("2026-03-17T10:00:03Z"),
params: {
level: "notice",
data: "Server capabilities negotiated: tools, resources, prompts",
logger: "session",
},
},
{
receivedAt: new Date("2026-03-17T10:00:04Z"),
params: {
level: "warning",
data: "Rate limit approaching: 85% of quota used",
logger: "ratelimit",
},
},
{
receivedAt: new Date("2026-03-17T10:00:05Z"),
params: {
level: "error",
data: "Tool execution failed: timeout after 30s",
logger: "tools",
},
},
{
receivedAt: new Date("2026-03-17T10:00:06Z"),
params: {
level: "critical",
data: "Database connection pool exhausted",
logger: "db",
},
},
{
receivedAt: new Date("2026-03-17T10:00:07Z"),
params: {
level: "alert",
data: "Memory usage exceeds 95% threshold",
logger: "system",
},
},
{
receivedAt: new Date("2026-03-17T10:00:08Z"),
params: {
level: "emergency",
data: "System unresponsive - initiating graceful shutdown",
logger: "system",
},
},
];
export const MixedLevels: Story = {
args: {
entries: allLevelEntries,
},
};