sunpeak 0.19.12 → 0.20.1
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 +321 -6
- package/bin/commands/test-init.mjs +100 -39
- package/bin/commands/test.mjs +6 -0
- package/bin/lib/inspect/inspect-config.mjs +16 -1
- package/bin/lib/inspect/inspect-server.d.mts +32 -0
- package/bin/lib/inspect/inspect-server.mjs +11 -0
- package/bin/lib/resolve-bin.mjs +39 -0
- package/bin/lib/test/base-config.mjs +3 -2
- package/bin/lib/test/matchers.mjs +2 -2
- package/bin/lib/test/test-config.mjs +18 -7
- 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
package/bin/commands/test.mjs
CHANGED
|
@@ -70,6 +70,9 @@ export async function runTest(args) {
|
|
|
70
70
|
'playwright.config.js',
|
|
71
71
|
'sunpeak.config.ts',
|
|
72
72
|
'sunpeak.config.js',
|
|
73
|
+
// Fallback for non-JS projects: tests/sunpeak/ self-contained directory
|
|
74
|
+
'tests/sunpeak/playwright.config.ts',
|
|
75
|
+
'tests/sunpeak/playwright.config.js',
|
|
73
76
|
],
|
|
74
77
|
visual: isVisual,
|
|
75
78
|
updateSnapshots: isVisual && isUpdate,
|
|
@@ -82,6 +85,9 @@ export async function runTest(args) {
|
|
|
82
85
|
configCandidates: [
|
|
83
86
|
'tests/live/playwright.config.ts',
|
|
84
87
|
'tests/live/playwright.config.js',
|
|
88
|
+
// Fallback for non-JS projects: tests/sunpeak/ self-contained directory
|
|
89
|
+
'tests/sunpeak/live/playwright.config.ts',
|
|
90
|
+
'tests/sunpeak/live/playwright.config.js',
|
|
85
91
|
],
|
|
86
92
|
configRequired: true,
|
|
87
93
|
configErrorMessage: 'No live test config found at tests/live/playwright.config.ts',
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* and external servers.
|
|
16
16
|
*/
|
|
17
17
|
import { createBaseConfig, resolvePorts } from '../test/base-config.mjs';
|
|
18
|
+
import { resolveSunpeakBin } from '../resolve-bin.mjs';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Create a complete Playwright config for testing an external MCP server.
|
|
@@ -26,6 +27,9 @@ import { createBaseConfig, resolvePorts } from '../test/base-config.mjs';
|
|
|
26
27
|
* @param {string[]} [options.hosts=['chatgpt', 'claude']] - Host shells to test
|
|
27
28
|
* @param {string} [options.name] - App name in inspector chrome
|
|
28
29
|
* @param {Object} [options.use] - Additional Playwright `use` options
|
|
30
|
+
* @param {number} [options.timeout] - Server startup timeout in ms (default: 60000)
|
|
31
|
+
* @param {Record<string, string>} [options.env] - Environment variables for stdio servers
|
|
32
|
+
* @param {string} [options.cwd] - Working directory for stdio servers
|
|
29
33
|
* @returns {import('@playwright/test').PlaywrightTestConfig}
|
|
30
34
|
*/
|
|
31
35
|
export function defineInspectConfig(options) {
|
|
@@ -37,6 +41,9 @@ export function defineInspectConfig(options) {
|
|
|
37
41
|
name,
|
|
38
42
|
use: userUse,
|
|
39
43
|
visual,
|
|
44
|
+
timeout,
|
|
45
|
+
env,
|
|
46
|
+
cwd,
|
|
40
47
|
} = options;
|
|
41
48
|
|
|
42
49
|
if (!server) {
|
|
@@ -49,8 +56,15 @@ export function defineInspectConfig(options) {
|
|
|
49
56
|
const serverArg = server.includes(' ') ? `"${server}"` : server;
|
|
50
57
|
const command = [
|
|
51
58
|
`SUNPEAK_SANDBOX_PORT=${sandboxPort}`,
|
|
52
|
-
|
|
59
|
+
`${resolveSunpeakBin()} inspect`,
|
|
53
60
|
`--server ${serverArg}`,
|
|
61
|
+
...(env
|
|
62
|
+
? Object.entries(env).map(([k, v]) => {
|
|
63
|
+
const pair = `${k}=${v}`;
|
|
64
|
+
return pair.includes(' ') ? `--env "${pair}"` : `--env ${pair}`;
|
|
65
|
+
})
|
|
66
|
+
: []),
|
|
67
|
+
...(cwd ? [cwd.includes(' ') ? `--cwd "${cwd}"` : `--cwd ${cwd}`] : []),
|
|
54
68
|
...(simulationsDir ? [`--simulations ${simulationsDir}`] : []),
|
|
55
69
|
`--port ${port}`,
|
|
56
70
|
...(name ? [`--name "${name}"`] : []),
|
|
@@ -62,6 +76,7 @@ export function defineInspectConfig(options) {
|
|
|
62
76
|
port,
|
|
63
77
|
use: userUse,
|
|
64
78
|
visual,
|
|
79
|
+
timeout,
|
|
65
80
|
webServer: {
|
|
66
81
|
command,
|
|
67
82
|
healthUrl: `http://localhost:${port}/health`,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Start the sunpeak inspector server programmatically.
|
|
3
|
+
*
|
|
4
|
+
* Connects to the provided MCP server, discovers tools and resources,
|
|
5
|
+
* and serves the inspector UI on the specified port.
|
|
6
|
+
*/
|
|
7
|
+
export function inspectServer(opts: {
|
|
8
|
+
/** MCP server URL or stdio command. */
|
|
9
|
+
server: string;
|
|
10
|
+
/** Path to simulation fixtures directory. */
|
|
11
|
+
simulationsDir?: string | null;
|
|
12
|
+
/** Dev server port (default: 3000). */
|
|
13
|
+
port?: number;
|
|
14
|
+
/** App name in inspector chrome. */
|
|
15
|
+
name?: string;
|
|
16
|
+
/** Existing sandbox server URL (skips creating one). */
|
|
17
|
+
sandboxUrl?: string;
|
|
18
|
+
/** If true, show framework-only controls (Prod Resources). */
|
|
19
|
+
frameworkMode?: boolean;
|
|
20
|
+
/** Initial prod resources state. */
|
|
21
|
+
defaultProdResources?: boolean;
|
|
22
|
+
/** Project directory for serving /dist/ files (prod resources). */
|
|
23
|
+
projectRoot?: string | null;
|
|
24
|
+
/** Whether to open browser (default: !CI). */
|
|
25
|
+
open?: boolean;
|
|
26
|
+
/** Additional cleanup callback on exit. */
|
|
27
|
+
onCleanup?: () => Promise<void>;
|
|
28
|
+
/** Extra environment variables for stdio server processes. */
|
|
29
|
+
env?: Record<string, string>;
|
|
30
|
+
/** Working directory for stdio server processes. */
|
|
31
|
+
cwd?: string;
|
|
32
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic entry point for the sunpeak inspector server.
|
|
3
|
+
*
|
|
4
|
+
* Allows frameworks to start the inspector from their own CLI without
|
|
5
|
+
* shelling out to the `sunpeak inspect` command.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { inspectServer } from 'sunpeak/inspect';
|
|
9
|
+
* await inspectServer({ server: 'http://localhost:8000/mcp', port: 3000 });
|
|
10
|
+
*/
|
|
11
|
+
export { inspectServer } from '../../commands/inspect.mjs';
|
|
@@ -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
|
|
|
@@ -52,7 +53,7 @@ export function createBaseConfig({ hosts, testDir, webServer, port, use, globalS
|
|
|
52
53
|
command: webServer.command,
|
|
53
54
|
url: webServer.healthUrl,
|
|
54
55
|
reuseExistingServer: !process.env.CI,
|
|
55
|
-
timeout: 60_000,
|
|
56
|
+
timeout: timeout ?? 60_000,
|
|
56
57
|
},
|
|
57
58
|
};
|
|
58
59
|
}
|
|
@@ -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,6 +73,7 @@ export function defineConfig(options = {}) {
|
|
|
69
73
|
use: userUse,
|
|
70
74
|
globalSetup,
|
|
71
75
|
visual,
|
|
76
|
+
timeout,
|
|
72
77
|
webServer: {
|
|
73
78
|
command,
|
|
74
79
|
healthUrl: `http://localhost:${port}/health`,
|
|
@@ -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
|
}>;
|