sunpeak 0.19.12 → 0.20.2
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/README.md +2 -2
- package/bin/commands/inspect.mjs +361 -12
- package/bin/commands/test-init.mjs +190 -118
- package/bin/commands/test.mjs +12 -1
- package/bin/lib/eval/eval-runner.mjs +7 -1
- package/bin/lib/inspect/inspect-config.mjs +17 -2
- package/bin/lib/inspect/inspect-server.d.mts +32 -0
- package/bin/lib/inspect/inspect-server.mjs +11 -0
- package/bin/lib/live/live-config.d.mts +10 -0
- package/bin/lib/live/live-config.mjs +34 -2
- package/bin/lib/resolve-bin.mjs +39 -0
- package/bin/lib/test/base-config.mjs +6 -3
- package/bin/lib/test/matchers.mjs +2 -2
- package/bin/lib/test/test-config.mjs +19 -8
- package/bin/lib/test/test-fixtures.d.mts +52 -92
- package/bin/lib/test/test-fixtures.mjs +174 -147
- package/dist/chatgpt/index.cjs +1 -1
- package/dist/chatgpt/index.js +1 -1
- package/dist/claude/index.cjs +1 -1
- package/dist/claude/index.js +1 -1
- package/dist/host/chatgpt/index.cjs +1 -1
- package/dist/host/chatgpt/index.js +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.cjs +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/{inspector-D5DckQuU.js → inspector-BBDa5yCm.js} +57 -23
- package/dist/inspector-BBDa5yCm.js.map +1 -0
- package/dist/{inspector-jY9O18z9.cjs → inspector-DAA1Wiyh.cjs} +58 -24
- package/dist/inspector-DAA1Wiyh.cjs.map +1 -0
- package/dist/lib/discovery-cli.cjs +1 -1
- package/dist/mcp/index.cjs +22 -25
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +19 -22
- package/dist/mcp/index.js.map +1 -1
- package/dist/{use-app-Bfargfa3.js → use-app-Cr0auUa1.js} +2 -2
- package/dist/{use-app-Bfargfa3.js.map → use-app-Cr0auUa1.js.map} +1 -1
- package/dist/{use-app-CbsBEmwv.cjs → use-app-DPkj5Jp_.cjs} +2 -2
- package/dist/{use-app-CbsBEmwv.cjs.map → use-app-DPkj5Jp_.cjs.map} +1 -1
- package/package.json +17 -11
- package/template/dist/albums/albums.html +4 -4
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +4 -4
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +6 -6
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +4 -4
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.bin/vite +2 -2
- package/template/node_modules/.bin/vitest +2 -2
- package/template/node_modules/.vite/deps/_metadata.json +4 -4
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +1 -1
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/@testing-library_react.js +4 -4
- package/template/node_modules/.vite-mcp/deps/@testing-library_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/_metadata.json +33 -33
- package/template/node_modules/.vite-mcp/deps/{client-CU1wWud4.js → client-B_5CX--u.js} +7 -7
- package/template/node_modules/.vite-mcp/deps/{client-CU1wWud4.js.map → client-B_5CX--u.js.map} +1 -1
- package/template/node_modules/.vite-mcp/deps/embla-carousel-react.js +1 -1
- package/template/node_modules/.vite-mcp/deps/embla-carousel-react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/react-dom.js +3 -3
- package/template/node_modules/.vite-mcp/deps/react-dom.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/react-dom_client.js +1 -1
- package/template/node_modules/.vite-mcp/deps/react.js +3 -3
- package/template/node_modules/.vite-mcp/deps/react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/react_jsx-dev-runtime.js +2 -2
- package/template/node_modules/.vite-mcp/deps/react_jsx-dev-runtime.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/react_jsx-runtime.js +2 -2
- package/template/node_modules/.vite-mcp/deps/react_jsx-runtime.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/vitest.js +1024 -622
- package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
- package/template/package.json +6 -6
- package/template/tests/e2e/albums.spec.ts +24 -52
- package/template/tests/e2e/carousel.spec.ts +36 -58
- package/template/tests/e2e/map.spec.ts +35 -56
- package/template/tests/e2e/review.spec.ts +56 -85
- package/template/tests/e2e/visual.spec.ts +14 -12
- package/dist/inspector-D5DckQuU.js.map +0 -1
- package/dist/inspector-jY9O18z9.cjs.map +0 -1
|
@@ -11,6 +11,7 @@ import { join, dirname } from 'path';
|
|
|
11
11
|
import { fileURLToPath } from 'url';
|
|
12
12
|
import { ANTI_BOT_ARGS, CHROME_USER_AGENT } from './utils.mjs';
|
|
13
13
|
import { getPortSync } from '../get-port.mjs';
|
|
14
|
+
import { resolveSunpeakBin } from '../resolve-bin.mjs';
|
|
14
15
|
|
|
15
16
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
17
|
const GLOBAL_SETUP_PATH = join(__dirname, 'global-setup.mjs');
|
|
@@ -34,6 +35,10 @@ const GLOBAL_SETUP_PATH = join(__dirname, 'global-setup.mjs');
|
|
|
34
35
|
* @param {string[]} [options.permissions] - Browser permissions to grant (e.g., ['geolocation'])
|
|
35
36
|
* @param {boolean} [options.devOverlay=true] - Show the dev overlay (resource timestamp + tool timing) in resources
|
|
36
37
|
* @param {Object} [options.use] - Additional Playwright `use` options (merged with defaults)
|
|
38
|
+
* @param {Object} [options.server] - External MCP server config (omit for sunpeak projects)
|
|
39
|
+
* @param {string} [options.server.url] - Server URL (e.g., 'http://localhost:8000/mcp')
|
|
40
|
+
* @param {string} [options.server.command] - Server start command
|
|
41
|
+
* @param {string[]} [options.server.args] - Command arguments
|
|
37
42
|
*/
|
|
38
43
|
export function createLiveConfig(hostOptions, options = {}) {
|
|
39
44
|
const { hostId, authFileName } = hostOptions;
|
|
@@ -49,6 +54,7 @@ export function createLiveConfig(hostOptions, options = {}) {
|
|
|
49
54
|
geolocation,
|
|
50
55
|
permissions,
|
|
51
56
|
use: userUse,
|
|
57
|
+
server,
|
|
52
58
|
} = options;
|
|
53
59
|
|
|
54
60
|
const resolvedAuthDir = authDir || join(testDir, '.auth');
|
|
@@ -91,10 +97,36 @@ export function createLiveConfig(hostOptions, options = {}) {
|
|
|
91
97
|
},
|
|
92
98
|
],
|
|
93
99
|
webServer: {
|
|
94
|
-
command:
|
|
95
|
-
url: `http://
|
|
100
|
+
command: buildLiveWebServerCommand({ server, vitePort, devOverlay }),
|
|
101
|
+
url: `http://127.0.0.1:${vitePort}/health`,
|
|
96
102
|
reuseExistingServer: !process.env.CI,
|
|
97
103
|
timeout: 60_000,
|
|
98
104
|
},
|
|
99
105
|
};
|
|
100
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Build the webServer command for live tests.
|
|
110
|
+
* Uses `sunpeak inspect` for external servers, `pnpm dev` for sunpeak projects.
|
|
111
|
+
*/
|
|
112
|
+
function buildLiveWebServerCommand({ server, vitePort, devOverlay }) {
|
|
113
|
+
const sandboxPort = getPortSync(24680);
|
|
114
|
+
const envPrefix = `SUNPEAK_LIVE_TEST=1 SUNPEAK_SANDBOX_PORT=${sandboxPort}${devOverlay ? '' : ' SUNPEAK_DEV_OVERLAY=false'}`;
|
|
115
|
+
|
|
116
|
+
if (server) {
|
|
117
|
+
// External MCP server — launch sunpeak inspect
|
|
118
|
+
const bin = resolveSunpeakBin();
|
|
119
|
+
if (server.url) {
|
|
120
|
+
return `${envPrefix} ${bin} inspect --server ${server.url} --port ${vitePort}`;
|
|
121
|
+
}
|
|
122
|
+
if (server.command) {
|
|
123
|
+
const cmd = server.args
|
|
124
|
+
? `${server.command} ${server.args.join(' ')}`
|
|
125
|
+
: server.command;
|
|
126
|
+
return `${envPrefix} ${bin} inspect --server "${cmd}" --port ${vitePort}`;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// sunpeak framework project — use pnpm dev
|
|
131
|
+
return `${envPrefix} pnpm dev -- --prod-resources --port ${vitePort}`;
|
|
132
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the sunpeak CLI binary path.
|
|
3
|
+
*
|
|
4
|
+
* When sunpeak is installed as a local dependency (e.g., in tests/sunpeak/
|
|
5
|
+
* for non-JS projects), the bare `sunpeak` command won't be on PATH.
|
|
6
|
+
* This utility checks for the local .bin entry first, then falls back
|
|
7
|
+
* to the bare command name for global installs.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { join, dirname } from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Find the sunpeak binary, preferring the local node_modules/.bin entry.
|
|
15
|
+
*
|
|
16
|
+
* Checks in order:
|
|
17
|
+
* 1. process.cwd() (works when running from the test directory directly)
|
|
18
|
+
* 2. The directory containing this file's package (works when the config is
|
|
19
|
+
* loaded from a parent directory, e.g., `sunpeak test` run from project root
|
|
20
|
+
* with config at tests/sunpeak/playwright.config.ts)
|
|
21
|
+
*
|
|
22
|
+
* @returns {string} Path to the sunpeak binary, or bare 'sunpeak' as fallback
|
|
23
|
+
*/
|
|
24
|
+
export function resolveSunpeakBin() {
|
|
25
|
+
// Check cwd first (covers `cd tests/sunpeak && sunpeak test`)
|
|
26
|
+
const cwdBin = join(process.cwd(), 'node_modules', '.bin', 'sunpeak');
|
|
27
|
+
if (existsSync(cwdBin)) return cwdBin;
|
|
28
|
+
|
|
29
|
+
// Check the directory containing this module's package, which is the
|
|
30
|
+
// sunpeak package root. Walk up from bin/lib/ to find node_modules/.bin/.
|
|
31
|
+
// This covers running from a parent dir (e.g., project root) where sunpeak
|
|
32
|
+
// is installed in a subdirectory (tests/sunpeak/node_modules/sunpeak/).
|
|
33
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
34
|
+
const pkgRoot = join(__dirname, '..', '..');
|
|
35
|
+
const pkgBin = join(pkgRoot, '..', '.bin', 'sunpeak');
|
|
36
|
+
if (existsSync(pkgBin)) return pkgBin;
|
|
37
|
+
|
|
38
|
+
return 'sunpeak';
|
|
39
|
+
}
|
|
@@ -15,9 +15,10 @@ import { getPortSync } from '../get-port.mjs';
|
|
|
15
15
|
* @param {number} options.port - Inspector port
|
|
16
16
|
* @param {Object} [options.use] - Additional Playwright `use` options
|
|
17
17
|
* @param {string} [options.globalSetup] - Global setup file path
|
|
18
|
+
* @param {number} [options.timeout] - WebServer startup timeout in ms (default: 60000)
|
|
18
19
|
* @returns {import('@playwright/test').PlaywrightTestConfig}
|
|
19
20
|
*/
|
|
20
|
-
export function createBaseConfig({ hosts, testDir, webServer, port, use, globalSetup, visual }) {
|
|
21
|
+
export function createBaseConfig({ hosts, testDir, webServer, port, use, globalSetup, visual, timeout }) {
|
|
21
22
|
// Separate snapshot path from other visual options passed to expect.toHaveScreenshot
|
|
22
23
|
const { snapshotPathTemplate, ...toHaveScreenshotDefaults } = visual ?? {};
|
|
23
24
|
|
|
@@ -43,7 +44,9 @@ export function createBaseConfig({ hosts, testDir, webServer, port, use, globalS
|
|
|
43
44
|
? { expect: { toHaveScreenshot: toHaveScreenshotDefaults } }
|
|
44
45
|
: {}),
|
|
45
46
|
use: {
|
|
46
|
-
|
|
47
|
+
// Use 127.0.0.1 instead of localhost to avoid IPv4/IPv6 resolution
|
|
48
|
+
// ambiguity that causes ECONNREFUSED flakes on macOS.
|
|
49
|
+
baseURL: `http://127.0.0.1:${port}`,
|
|
47
50
|
trace: 'on-first-retry',
|
|
48
51
|
...use,
|
|
49
52
|
},
|
|
@@ -52,7 +55,7 @@ export function createBaseConfig({ hosts, testDir, webServer, port, use, globalS
|
|
|
52
55
|
command: webServer.command,
|
|
53
56
|
url: webServer.healthUrl,
|
|
54
57
|
reuseExistingServer: !process.env.CI,
|
|
55
|
-
timeout: 60_000,
|
|
58
|
+
timeout: timeout ?? 60_000,
|
|
56
59
|
},
|
|
57
60
|
};
|
|
58
61
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP-native custom matchers for Playwright's expect.
|
|
3
3
|
*
|
|
4
|
-
* These matchers operate on
|
|
5
|
-
*
|
|
4
|
+
* These matchers operate on tool results from mcp.callTool() or
|
|
5
|
+
* InspectorResult from inspector.renderTool().
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import { existsSync, readFileSync } from 'fs';
|
|
19
19
|
import { join } from 'path';
|
|
20
20
|
import { createBaseConfig, resolvePorts } from './base-config.mjs';
|
|
21
|
+
import { resolveSunpeakBin } from '../resolve-bin.mjs';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* @param {Object} [options]
|
|
@@ -26,11 +27,13 @@ import { createBaseConfig, resolvePorts } from './base-config.mjs';
|
|
|
26
27
|
* @param {string[]} [options.server.args] - Command arguments
|
|
27
28
|
* @param {string} [options.server.url] - HTTP server URL (alternative to command)
|
|
28
29
|
* @param {Record<string, string>} [options.server.env] - Environment variables
|
|
30
|
+
* @param {string} [options.server.cwd] - Working directory for the server process
|
|
29
31
|
* @param {string[]} [options.hosts] - Host shells to test (default: ['chatgpt', 'claude'])
|
|
30
32
|
* @param {string} [options.testDir] - Test directory
|
|
31
33
|
* @param {string} [options.simulationsDir] - Simulations directory for mock data
|
|
32
34
|
* @param {string} [options.globalSetup] - Global setup file path
|
|
33
35
|
* @param {Object} [options.use] - Additional Playwright `use` options
|
|
36
|
+
* @param {number} [options.timeout] - Server startup timeout in ms (default: 60000)
|
|
34
37
|
* @returns {import('@playwright/test').PlaywrightTestConfig}
|
|
35
38
|
*/
|
|
36
39
|
export function defineConfig(options = {}) {
|
|
@@ -42,6 +45,7 @@ export function defineConfig(options = {}) {
|
|
|
42
45
|
globalSetup,
|
|
43
46
|
use: userUse,
|
|
44
47
|
visual,
|
|
48
|
+
timeout,
|
|
45
49
|
} = options;
|
|
46
50
|
|
|
47
51
|
const { port, sandboxPort } = resolvePorts();
|
|
@@ -69,9 +73,10 @@ export function defineConfig(options = {}) {
|
|
|
69
73
|
use: userUse,
|
|
70
74
|
globalSetup,
|
|
71
75
|
visual,
|
|
76
|
+
timeout,
|
|
72
77
|
webServer: {
|
|
73
78
|
command,
|
|
74
|
-
healthUrl: `http://
|
|
79
|
+
healthUrl: `http://127.0.0.1:${port}/health`,
|
|
75
80
|
},
|
|
76
81
|
});
|
|
77
82
|
}
|
|
@@ -97,13 +102,7 @@ function detectSunpeakProject() {
|
|
|
97
102
|
function buildInspectCommand({ server, port, sandboxPort, simulationsDir }) {
|
|
98
103
|
const parts = [`SUNPEAK_SANDBOX_PORT=${sandboxPort}`];
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
for (const [key, value] of Object.entries(server.env)) {
|
|
102
|
-
parts.push(`${key}=${value}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
parts.push('sunpeak inspect');
|
|
105
|
+
parts.push(`${resolveSunpeakBin()} inspect`);
|
|
107
106
|
|
|
108
107
|
if (server.url) {
|
|
109
108
|
parts.push(`--server ${server.url}`);
|
|
@@ -115,6 +114,18 @@ function buildInspectCommand({ server, port, sandboxPort, simulationsDir }) {
|
|
|
115
114
|
parts.push(`--server "${cmd}"`);
|
|
116
115
|
}
|
|
117
116
|
|
|
117
|
+
// Pass environment variables as --env KEY=VALUE flags (stdio servers only).
|
|
118
|
+
if (server.env) {
|
|
119
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
120
|
+
const pair = `${key}=${value}`;
|
|
121
|
+
parts.push(pair.includes(' ') ? `--env "${pair}"` : `--env ${pair}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (server.cwd) {
|
|
126
|
+
parts.push(server.cwd.includes(' ') ? `--cwd "${server.cwd}"` : `--cwd ${server.cwd}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
118
129
|
if (simulationsDir) {
|
|
119
130
|
parts.push(`--simulations ${simulationsDir}`);
|
|
120
131
|
}
|
|
@@ -7,46 +7,40 @@ import type {
|
|
|
7
7
|
PageAssertionsToHaveScreenshotOptions,
|
|
8
8
|
} from '@playwright/test';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
// ── MCP Protocol Types ──
|
|
11
|
+
|
|
12
|
+
export interface Tool {
|
|
13
|
+
name: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
inputSchema: Record<string, unknown>;
|
|
16
|
+
title?: string;
|
|
17
|
+
annotations?: Record<string, unknown>;
|
|
18
|
+
_meta?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface Resource {
|
|
22
|
+
uri: string;
|
|
23
|
+
name: string;
|
|
24
|
+
mimeType?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
_meta?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CallToolResult {
|
|
30
|
+
content?: Array<{ type: string; text?: string; [key: string]: unknown }>;
|
|
17
31
|
structuredContent?: unknown;
|
|
18
|
-
|
|
19
|
-
isError: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Get a FrameLocator for the rendered resource UI.
|
|
22
|
-
* Handles the double-iframe traversal automatically.
|
|
23
|
-
*/
|
|
24
|
-
app(): FrameLocator;
|
|
32
|
+
isError?: boolean;
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
export interface CallToolOptions {
|
|
31
|
-
/** Color theme for the inspector. */
|
|
35
|
+
// ── sunpeak Inspector Types ──
|
|
36
|
+
|
|
37
|
+
export interface RenderToolOptions {
|
|
32
38
|
theme?: 'light' | 'dark';
|
|
33
|
-
/** Display mode for the resource. */
|
|
34
39
|
displayMode?: 'inline' | 'pip' | 'fullscreen';
|
|
35
|
-
|
|
36
|
-
prodResources?: boolean;
|
|
37
|
-
/** Additional inspector URL parameters. */
|
|
40
|
+
timeout?: number;
|
|
38
41
|
[key: string]: unknown;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
/**
|
|
42
|
-
* Options for screenshot().
|
|
43
|
-
*
|
|
44
|
-
* Extends Playwright's toHaveScreenshot() options with sunpeak-specific
|
|
45
|
-
* `target` and `element` fields. All standard Playwright options (threshold,
|
|
46
|
-
* maxDiffPixelRatio, maxDiffPixels, mask, maskColor, animations, caret,
|
|
47
|
-
* fullPage, clip, scale, stylePath, omitBackground, timeout, etc.)
|
|
48
|
-
* are passed through directly.
|
|
49
|
-
*/
|
|
50
44
|
export interface ScreenshotOptions extends PageAssertionsToHaveScreenshotOptions {
|
|
51
45
|
/** What to screenshot: 'app' (inner iframe content) or 'page' (full inspector). Default: 'app'. */
|
|
52
46
|
target?: 'app' | 'page';
|
|
@@ -54,76 +48,42 @@ export interface ScreenshotOptions extends PageAssertionsToHaveScreenshotOptions
|
|
|
54
48
|
element?: Locator;
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
export interface InspectorResult {
|
|
52
|
+
content: Array<{ type: string; text?: string; [key: string]: unknown }>;
|
|
53
|
+
structuredContent?: unknown;
|
|
54
|
+
isError: boolean;
|
|
55
|
+
source: 'fixture' | 'server';
|
|
56
|
+
app(): FrameLocator;
|
|
57
|
+
screenshot(options?: ScreenshotOptions): Promise<void>;
|
|
58
|
+
screenshot(name?: string, options?: ScreenshotOptions): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── Fixtures ──
|
|
62
|
+
|
|
63
|
+
/** MCP protocol fixture. Maps 1:1 to MCP protocol operations. */
|
|
60
64
|
export interface McpFixture {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
listTools(): Promise<Tool[]>;
|
|
66
|
+
callTool(name: string, input?: Record<string, unknown>): Promise<CallToolResult>;
|
|
67
|
+
listResources(): Promise<Resource[]>;
|
|
68
|
+
readResource(uri: string): Promise<string>;
|
|
69
|
+
}
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
callTool(
|
|
71
|
+
/** sunpeak inspector fixture. Renders tools in simulated host environments. */
|
|
72
|
+
export interface InspectorFixture {
|
|
73
|
+
host: string;
|
|
74
|
+
page: Page;
|
|
75
|
+
renderTool(
|
|
72
76
|
name: string,
|
|
73
77
|
input?: Record<string, unknown>,
|
|
74
|
-
options?:
|
|
75
|
-
): Promise<
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Navigate to a tool with no mock data ("Press Run" state).
|
|
79
|
-
*/
|
|
80
|
-
openTool(name: string, options?: { theme?: 'light' | 'dark' }): Promise<void>;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Click the Run button and return the rendered result.
|
|
84
|
-
*/
|
|
85
|
-
runTool(): Promise<ToolResult>;
|
|
86
|
-
|
|
87
|
-
/** Change the theme via the sidebar toggle. */
|
|
88
|
-
setTheme(theme: 'light' | 'dark'): Promise<void>;
|
|
89
|
-
|
|
90
|
-
/** Change the display mode via the sidebar buttons. */
|
|
91
|
-
setDisplayMode(mode: 'inline' | 'pip' | 'fullscreen'): Promise<void>;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Take a screenshot and compare against a baseline.
|
|
95
|
-
* Only performs the comparison when visual testing is enabled
|
|
96
|
-
* (`sunpeak test --visual`). Silently skips otherwise.
|
|
97
|
-
*
|
|
98
|
-
* @param name - Snapshot name (auto-generated from test title if omitted)
|
|
99
|
-
* @param options - Screenshot and comparison options
|
|
100
|
-
*/
|
|
101
|
-
screenshot(name?: string, options?: ScreenshotOptions): Promise<void>;
|
|
78
|
+
options?: RenderToolOptions
|
|
79
|
+
): Promise<InspectorResult>;
|
|
102
80
|
}
|
|
103
81
|
|
|
104
|
-
|
|
105
|
-
* Extended Playwright test with `mcp` fixture.
|
|
106
|
-
*/
|
|
107
|
-
export declare const test: TestType<{ mcp: McpFixture }, {}>;
|
|
82
|
+
export declare const test: TestType<{ mcp: McpFixture; inspector: InspectorFixture }, {}>;
|
|
108
83
|
|
|
109
|
-
/**
|
|
110
|
-
* Extended Playwright expect with MCP-native matchers.
|
|
111
|
-
*/
|
|
112
84
|
export declare const expect: Expect<{
|
|
113
|
-
/**
|
|
114
|
-
* Assert that a tool result is an error.
|
|
115
|
-
*/
|
|
116
85
|
toBeError(): void;
|
|
117
|
-
/**
|
|
118
|
-
* Assert that any content item's text contains the given string.
|
|
119
|
-
*/
|
|
120
86
|
toHaveTextContent(text: string): void;
|
|
121
|
-
/**
|
|
122
|
-
* Assert that structuredContent matches the expected shape.
|
|
123
|
-
*/
|
|
124
87
|
toHaveStructuredContent(shape: unknown): void;
|
|
125
|
-
/**
|
|
126
|
-
* Assert that content array contains an item of the given type.
|
|
127
|
-
*/
|
|
128
88
|
toHaveContentType(type: string): void;
|
|
129
89
|
}>;
|