test(vscode): add marketplace screenshot stories for MCP and Modes tabs

Extend the existing marketplace visual regression tests with 10 new
stories covering the MCP servers and Modes tabs. Each tab type now has
stories for: list with items, list with installed items, empty state,
single card not installed, and single card installed.
This commit is contained in:
kiloconnect[bot]
2026-03-17 16:49:53 +00:00
parent ac0a3ae997
commit 7c6d2eb3e0
@@ -10,7 +10,12 @@ import type { Meta, StoryObj } from "storybook-solidjs-vite"
import { StoryProviders } from "./StoryProviders"
import { MarketplaceListView } from "../components/marketplace/MarketplaceListView"
import { ItemCard } from "../components/marketplace/ItemCard"
import type { SkillMarketplaceItem, MarketplaceInstalledMetadata } from "../types/marketplace"
import type {
SkillMarketplaceItem,
McpMarketplaceItem,
ModeMarketplaceItem,
MarketplaceInstalledMetadata,
} from "../types/marketplace"
import "../components/marketplace/marketplace.css"
const meta: Meta = {
@@ -98,13 +103,160 @@ const MOCK_SKILLS: SkillMarketplaceItem[] = [
},
]
const MOCK_MCPS: McpMarketplaceItem[] = [
{
type: "mcp",
id: "github-mcp",
name: "GitHub",
description:
"Interact with GitHub repositories, issues, and pull requests. Search code, manage branches, and automate workflows.",
url: "https://github.com/modelcontextprotocol/servers/tree/main/src/github",
content:
'{ "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } }',
parameters: [{ name: "GitHub Token", key: "GITHUB_TOKEN", placeholder: "ghp_xxxxxxxxxxxx" }],
author: "Anthropic",
tags: ["version-control", "development"],
},
{
type: "mcp",
id: "postgres-mcp",
name: "PostgreSQL",
description: "Query and manage PostgreSQL databases. Run SQL, inspect schemas, and manage connections.",
url: "https://github.com/modelcontextprotocol/servers/tree/main/src/postgres",
content: [
{
name: "npx",
content:
'{ "command": "npx", "args": ["-y", "@modelcontextprotocol/server-postgres", "${CONNECTION_STRING}"] }',
parameters: [
{ name: "Connection String", key: "CONNECTION_STRING", placeholder: "postgresql://user:pass@localhost/db" },
],
},
{
name: "Docker",
content:
'{ "command": "docker", "args": ["run", "--rm", "-e", "CONNECTION_STRING=${CONNECTION_STRING}", "mcp/postgres"] }',
parameters: [
{ name: "Connection String", key: "CONNECTION_STRING", placeholder: "postgresql://user:pass@localhost/db" },
],
prerequisites: ["Docker must be installed and running"],
},
],
author: "Anthropic",
tags: ["database", "sql"],
},
{
type: "mcp",
id: "filesystem-mcp",
name: "Filesystem",
description: "Read, write, and manage files on the local filesystem with configurable access controls.",
url: "https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem",
content: '{ "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "${ALLOWED_DIR}"] }',
parameters: [{ name: "Allowed Directory", key: "ALLOWED_DIR", placeholder: "/path/to/directory" }],
tags: ["filesystem", "development"],
},
{
type: "mcp",
id: "slack-mcp",
name: "Slack",
description: "Send and receive messages, manage channels, and search conversations in Slack workspaces.",
url: "https://github.com/modelcontextprotocol/servers/tree/main/src/slack",
content:
'{ "command": "npx", "args": ["-y", "@modelcontextprotocol/server-slack"], "env": { "SLACK_TOKEN": "${SLACK_TOKEN}" } }',
parameters: [{ name: "Slack Bot Token", key: "SLACK_TOKEN", placeholder: "xoxb-xxxxxxxxxxxx" }],
author: "Anthropic",
tags: ["communication", "productivity"],
},
{
type: "mcp",
id: "brave-search-mcp",
name: "Brave Search",
description: "Search the web using the Brave Search API for real-time information retrieval.",
url: "https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search",
content:
'{ "command": "npx", "args": ["-y", "@modelcontextprotocol/server-brave-search"], "env": { "BRAVE_API_KEY": "${BRAVE_API_KEY}" } }',
parameters: [{ name: "API Key", key: "BRAVE_API_KEY", placeholder: "BSA-xxxxxxxxxxxx" }],
tags: ["search", "web"],
},
{
type: "mcp",
id: "puppeteer-mcp",
name: "Puppeteer",
description: "Automate browser interactions, take screenshots, and scrape web pages using headless Chrome.",
url: "https://github.com/modelcontextprotocol/servers/tree/main/src/puppeteer",
content: '{ "command": "npx", "args": ["-y", "@modelcontextprotocol/server-puppeteer"] }',
prerequisites: ["Chrome or Chromium must be installed"],
tags: ["browser", "automation", "web"],
},
]
const MOCK_MODES: ModeMarketplaceItem[] = [
{
type: "mode",
id: "architect",
name: "Architect",
description:
"High-level system design and planning. Focuses on architecture decisions, component boundaries, and technical specifications without writing implementation code.",
content: "name: Architect\nroleDefinition: You are a software architect...\ngroups:\n - read\n",
author: "Kilo",
tags: ["planning", "design"],
},
{
type: "mode",
id: "reviewer",
name: "Code Reviewer",
description:
"Reviews code for bugs, security issues, and best practices. Provides actionable feedback with specific line references.",
content: "name: Code Reviewer\nroleDefinition: You are a code reviewer...\ngroups:\n - read\n",
author: "Kilo",
tags: ["review", "quality"],
},
{
type: "mode",
id: "docs-writer",
name: "Documentation Writer",
description: "Generates and maintains documentation including READMEs, API docs, and inline code comments.",
content: "name: Documentation Writer\nroleDefinition: You write documentation...\ngroups:\n - read\n - edit\n",
tags: ["documentation", "writing"],
},
{
type: "mode",
id: "tdd",
name: "Test-Driven Developer",
description:
"Follows strict TDD methodology: write failing tests first, implement minimum code to pass, then refactor.",
content:
"name: Test-Driven Developer\nroleDefinition: You follow TDD...\ngroups:\n - read\n - edit\n - command\n",
author: "Community",
tags: ["testing", "methodology"],
},
{
type: "mode",
id: "debug",
name: "Debugger",
description: "Systematically diagnoses and fixes bugs. Uses logs, stack traces, and bisection to isolate issues.",
content: "name: Debugger\nroleDefinition: You are a debugger...\ngroups:\n - read\n - command\n",
tags: ["debugging", "troubleshooting"],
},
]
const EMPTY_METADATA: MarketplaceInstalledMetadata = { project: {}, global: {} }
const PARTIAL_INSTALLED: MarketplaceInstalledMetadata = {
const PARTIAL_INSTALLED_SKILLS: MarketplaceInstalledMetadata = {
project: { "nextjs-developer": { type: "skill" } },
global: { "python-data-science": { type: "skill" } },
}
const PARTIAL_INSTALLED_MCPS: MarketplaceInstalledMetadata = {
project: { "github-mcp": { type: "mcp" } },
global: { "postgres-mcp": { type: "mcp" } },
}
const PARTIAL_INSTALLED_MODES: MarketplaceInstalledMetadata = {
project: { architect: { type: "mode" } },
global: { reviewer: { type: "mode" } },
}
const noop = () => {}
// ---------------------------------------------------------------------------
@@ -138,7 +290,7 @@ export const SkillsTabWithInstalled: Story = {
<div style={{ width: "420px", height: "700px", overflow: "auto", padding: "12px" }}>
<MarketplaceListView
items={MOCK_SKILLS}
metadata={PARTIAL_INSTALLED}
metadata={PARTIAL_INSTALLED_SKILLS}
fetching={false}
type="skill"
searchPlaceholder="Search skills..."
@@ -196,7 +348,7 @@ export const InstalledSkillCard: Story = {
<div style={{ width: "420px", padding: "12px" }}>
<ItemCard
item={MOCK_SKILLS[0]}
metadata={PARTIAL_INSTALLED}
metadata={PARTIAL_INSTALLED_SKILLS}
displayName={MOCK_SKILLS[0].displayName}
linkUrl={MOCK_SKILLS[0].githubUrl}
onInstall={noop}
@@ -206,3 +358,187 @@ export const InstalledSkillCard: Story = {
</StoryProviders>
),
}
// ---------------------------------------------------------------------------
// MCP Stories
// ---------------------------------------------------------------------------
export const McpTabWithItems: Story = {
name: "MCP tab — with items",
render: () => (
<StoryProviders>
<div style={{ width: "420px", height: "700px", overflow: "auto", padding: "12px" }}>
<MarketplaceListView
items={MOCK_MCPS}
metadata={EMPTY_METADATA}
fetching={false}
type="mcp"
searchPlaceholder="Search MCP servers..."
emptyMessage="No MCP servers found"
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
export const McpTabWithInstalled: Story = {
name: "MCP tab — some installed",
render: () => (
<StoryProviders>
<div style={{ width: "420px", height: "700px", overflow: "auto", padding: "12px" }}>
<MarketplaceListView
items={MOCK_MCPS}
metadata={PARTIAL_INSTALLED_MCPS}
fetching={false}
type="mcp"
searchPlaceholder="Search MCP servers..."
emptyMessage="No MCP servers found"
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
export const McpTabEmpty: Story = {
name: "MCP tab — empty state",
render: () => (
<StoryProviders>
<div style={{ width: "420px", height: "400px", overflow: "auto", padding: "12px" }}>
<MarketplaceListView
items={[]}
metadata={EMPTY_METADATA}
fetching={false}
type="mcp"
searchPlaceholder="Search MCP servers..."
emptyMessage="No MCP servers found"
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
export const SingleMcpCard: Story = {
name: "ItemCard — single MCP not installed",
render: () => (
<StoryProviders>
<div style={{ width: "420px", padding: "12px" }}>
<ItemCard
item={MOCK_MCPS[0]}
metadata={EMPTY_METADATA}
linkUrl={MOCK_MCPS[0].url}
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
export const InstalledMcpCard: Story = {
name: "ItemCard — installed MCP",
render: () => (
<StoryProviders>
<div style={{ width: "420px", padding: "12px" }}>
<ItemCard
item={MOCK_MCPS[0]}
metadata={PARTIAL_INSTALLED_MCPS}
linkUrl={MOCK_MCPS[0].url}
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
// ---------------------------------------------------------------------------
// Mode Stories
// ---------------------------------------------------------------------------
export const ModesTabWithItems: Story = {
name: "Modes tab — with items",
render: () => (
<StoryProviders>
<div style={{ width: "420px", height: "700px", overflow: "auto", padding: "12px" }}>
<MarketplaceListView
items={MOCK_MODES}
metadata={EMPTY_METADATA}
fetching={false}
type="mode"
searchPlaceholder="Search modes..."
emptyMessage="No modes found"
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
export const ModesTabWithInstalled: Story = {
name: "Modes tab — some installed",
render: () => (
<StoryProviders>
<div style={{ width: "420px", height: "700px", overflow: "auto", padding: "12px" }}>
<MarketplaceListView
items={MOCK_MODES}
metadata={PARTIAL_INSTALLED_MODES}
fetching={false}
type="mode"
searchPlaceholder="Search modes..."
emptyMessage="No modes found"
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
export const ModesTabEmpty: Story = {
name: "Modes tab — empty state",
render: () => (
<StoryProviders>
<div style={{ width: "420px", height: "400px", overflow: "auto", padding: "12px" }}>
<MarketplaceListView
items={[]}
metadata={EMPTY_METADATA}
fetching={false}
type="mode"
searchPlaceholder="Search modes..."
emptyMessage="No modes found"
onInstall={noop}
onRemove={noop}
/>
</div>
</StoryProviders>
),
}
export const SingleModeCard: Story = {
name: "ItemCard — single mode not installed",
render: () => (
<StoryProviders>
<div style={{ width: "420px", padding: "12px" }}>
<ItemCard item={MOCK_MODES[0]} metadata={EMPTY_METADATA} onInstall={noop} onRemove={noop} />
</div>
</StoryProviders>
),
}
export const InstalledModeCard: Story = {
name: "ItemCard — installed mode",
render: () => (
<StoryProviders>
<div style={{ width: "420px", padding: "12px" }}>
<ItemCard item={MOCK_MODES[0]} metadata={PARTIAL_INSTALLED_MODES} onInstall={noop} onRemove={noop} />
</div>
</StoryProviders>
),
}