sunpeak 0.19.1 → 0.19.4
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 +6 -3
- package/bin/commands/new.mjs +3 -1
- package/bin/commands/test.mjs +107 -46
- package/bin/lib/inspect/inspect-config.d.mts +4 -0
- package/bin/lib/inspect/inspect-config.mjs +2 -0
- package/bin/lib/test/base-config.mjs +16 -1
- package/bin/lib/test/test-config.d.mts +22 -0
- package/bin/lib/test/test-config.mjs +2 -0
- package/bin/lib/test/test-fixtures.d.mts +34 -1
- package/bin/lib/test/test-fixtures.mjs +43 -0
- 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 +134 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +71 -62
- package/dist/index.js.map +1 -1
- package/dist/inspector/index.cjs +1 -1
- package/dist/inspector/index.js +1 -1
- package/dist/{inspector-Cdo5BK2D.js → inspector-Bp9jrHIu.js} +218 -80
- package/dist/inspector-Bp9jrHIu.js.map +1 -0
- package/dist/{inspector-8nPV2A-z.cjs → inspector-Cvq3yjNL.cjs} +219 -81
- package/dist/inspector-Cvq3yjNL.cjs.map +1 -0
- package/dist/mcp/index.cjs +235 -138
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +228 -132
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/production-server.d.ts +31 -0
- package/dist/{protocol-C7kTcBr_.cjs → protocol-C8pFDmcy.cjs} +8194 -8187
- package/dist/protocol-C8pFDmcy.cjs.map +1 -0
- package/dist/{protocol-BfAACnv0.js → protocol-CRqiPTLT.js} +8186 -8185
- package/dist/protocol-CRqiPTLT.js.map +1 -0
- package/dist/{use-app-CfP9VypY.js → use-app-Ck5kR1Sf.js} +193 -93
- package/dist/use-app-Ck5kR1Sf.js.map +1 -0
- package/dist/{use-app-CzcYw1Kz.cjs → use-app-DHYiev3D.cjs} +253 -147
- package/dist/use-app-DHYiev3D.cjs.map +1 -0
- package/package.json +2 -2
- package/template/README.md +6 -3
- package/template/dist/albums/albums.html +15 -15
- package/template/dist/albums/albums.json +1 -1
- package/template/dist/carousel/carousel.html +19 -19
- package/template/dist/carousel/carousel.json +1 -1
- package/template/dist/map/map.html +14 -14
- package/template/dist/map/map.json +1 -1
- package/template/dist/review/review.html +11 -11
- package/template/dist/review/review.json +1 -1
- package/template/node_modules/.vite/deps/_metadata.json +3 -3
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +192 -91
- 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 +231 -92
- 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 +208 -105
- package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
- package/template/node_modules/.vite-mcp/deps/_metadata.json +24 -24
- package/template/node_modules/.vite-mcp/deps/{protocol-B_qKkui_.js → protocol-BqGB4zBx.js} +45 -45
- package/template/node_modules/.vite-mcp/deps/protocol-BqGB4zBx.js.map +1 -0
- package/template/package.json +5 -3
- package/template/test-results/.last-run.json +4 -0
- package/template/tests/e2e/visual.spec.ts +36 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-chatgpt-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-claude-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-chatgpt-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-claude-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-chatgpt-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-chatgpt-linux.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-claude-darwin.png +0 -0
- package/template/tests/e2e/visual.spec.ts-snapshots/albums-page-light-claude-linux.png +0 -0
- package/dist/inspector-8nPV2A-z.cjs.map +0 -1
- package/dist/inspector-Cdo5BK2D.js.map +0 -1
- package/dist/protocol-BfAACnv0.js.map +0 -1
- package/dist/protocol-C7kTcBr_.cjs.map +0 -1
- package/dist/use-app-CfP9VypY.js.map +0 -1
- package/dist/use-app-CzcYw1Kz.cjs.map +0 -1
- package/template/node_modules/.vite-mcp/deps/protocol-B_qKkui_.js.map +0 -1
package/README.md
CHANGED
|
@@ -107,10 +107,13 @@ sunpeak new
|
|
|
107
107
|
| Command | Description |
|
|
108
108
|
| ------------------------------------- | ------------------------------------------- |
|
|
109
109
|
| `sunpeak inspect --server <url\|cmd>` | Inspect any MCP server in the inspector |
|
|
110
|
-
| `sunpeak test` | Run e2e tests
|
|
111
|
-
| `sunpeak test
|
|
112
|
-
| `sunpeak test --
|
|
110
|
+
| `sunpeak test` | Run unit + e2e tests |
|
|
111
|
+
| `sunpeak test --unit` | Run unit tests only (Vitest) |
|
|
112
|
+
| `sunpeak test --e2e` | Run e2e tests only (Playwright) |
|
|
113
|
+
| `sunpeak test --visual` | Run e2e tests with visual regression |
|
|
114
|
+
| `sunpeak test --visual --update` | Update visual regression baselines |
|
|
113
115
|
| `sunpeak test --live` | Run live tests against real hosts |
|
|
116
|
+
| `sunpeak test init` | Scaffold test infrastructure into a project |
|
|
114
117
|
|
|
115
118
|
**App framework** (for sunpeak projects):
|
|
116
119
|
|
package/bin/commands/new.mjs
CHANGED
|
@@ -176,7 +176,9 @@ export async function init(projectName, resourcesArg, deps = defaultDeps) {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
// Skip framework-internal test files (dev overlay tests are for sunpeak development, not user projects)
|
|
179
|
-
|
|
179
|
+
// Skip visual.spec.ts — it references specific resources and serves as a template/example.
|
|
180
|
+
// Users should write their own visual tests for their selected resources.
|
|
181
|
+
if ((src.includes('/tests/e2e/') || src.includes('/tests/live/')) && (name.startsWith('dev-') || name === 'visual.spec.ts')) {
|
|
180
182
|
return false;
|
|
181
183
|
}
|
|
182
184
|
|
package/bin/commands/test.mjs
CHANGED
|
@@ -5,11 +5,18 @@ import { join } from 'path';
|
|
|
5
5
|
/**
|
|
6
6
|
* sunpeak test — Run MCP server tests.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* sunpeak test init
|
|
10
|
-
* sunpeak test --unit
|
|
11
|
-
* sunpeak test --
|
|
12
|
-
* sunpeak test
|
|
8
|
+
* No flags: Run unit + e2e tests
|
|
9
|
+
* sunpeak test init Scaffold test infrastructure
|
|
10
|
+
* sunpeak test --unit Run unit tests (vitest)
|
|
11
|
+
* sunpeak test --e2e Run e2e tests (Playwright)
|
|
12
|
+
* sunpeak test --live Run live tests against real hosts
|
|
13
|
+
* sunpeak test --visual Run e2e tests with visual regression comparison
|
|
14
|
+
* sunpeak test --visual --update Update visual regression baselines
|
|
15
|
+
* sunpeak test [pattern] Pass through to the relevant runner
|
|
16
|
+
*
|
|
17
|
+
* Flags are additive: --unit --e2e --live runs all three.
|
|
18
|
+
* --visual implies --e2e and enables screenshot comparison.
|
|
19
|
+
* --update implies --visual.
|
|
13
20
|
*/
|
|
14
21
|
export async function runTest(args) {
|
|
15
22
|
// Handle `sunpeak test init` subcommand
|
|
@@ -20,58 +27,112 @@ export async function runTest(args) {
|
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
const isUnit = args.includes('--unit');
|
|
30
|
+
const isE2e = args.includes('--e2e');
|
|
23
31
|
const isLive = args.includes('--live');
|
|
24
|
-
|
|
32
|
+
let isVisual = args.includes('--visual');
|
|
33
|
+
const isUpdate = args.includes('--update');
|
|
34
|
+
const filteredArgs = args.filter(
|
|
35
|
+
(a) => !['--unit', '--e2e', '--live', '--visual', '--update'].includes(a)
|
|
36
|
+
);
|
|
25
37
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
// --update implies --visual (no point updating without enabling visual)
|
|
39
|
+
if (isUpdate) isVisual = true;
|
|
40
|
+
|
|
41
|
+
const hasAnyScope = isUnit || isE2e || isLive || isVisual;
|
|
42
|
+
|
|
43
|
+
// When extra args are present (file patterns, etc.) and no scope flags given,
|
|
44
|
+
// default to e2e only — passing Playwright file patterns to vitest would fail.
|
|
45
|
+
const hasExtraArgs = filteredArgs.length > 0;
|
|
46
|
+
|
|
47
|
+
// Determine which suites to run.
|
|
48
|
+
// No scope flags → unit + e2e (unless extra args narrow to e2e).
|
|
49
|
+
// --visual implies e2e.
|
|
50
|
+
const runUnit = hasAnyScope ? isUnit : !hasExtraArgs;
|
|
51
|
+
const runE2e = hasAnyScope ? (isE2e || isVisual) : true;
|
|
52
|
+
const runLive = isLive;
|
|
53
|
+
|
|
54
|
+
const results = [];
|
|
55
|
+
|
|
56
|
+
if (runUnit) {
|
|
57
|
+
const code = await runChild('pnpm', ['exec', 'vitest', 'run', ...filteredArgs]);
|
|
58
|
+
results.push({ suite: 'unit', code });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (runE2e) {
|
|
62
|
+
const code = await runPlaywright(filteredArgs, {
|
|
63
|
+
configCandidates: [
|
|
64
|
+
'playwright.config.ts',
|
|
65
|
+
'playwright.config.js',
|
|
66
|
+
'sunpeak.config.ts',
|
|
67
|
+
'sunpeak.config.js',
|
|
68
|
+
],
|
|
69
|
+
visual: isVisual,
|
|
70
|
+
updateSnapshots: isVisual && isUpdate,
|
|
31
71
|
});
|
|
32
|
-
|
|
33
|
-
return;
|
|
72
|
+
results.push({ suite: 'e2e', code });
|
|
34
73
|
}
|
|
35
74
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
75
|
+
if (runLive) {
|
|
76
|
+
const code = await runPlaywright(filteredArgs, {
|
|
77
|
+
configCandidates: [
|
|
78
|
+
'tests/live/playwright.config.ts',
|
|
79
|
+
'tests/live/playwright.config.js',
|
|
80
|
+
],
|
|
81
|
+
configRequired: true,
|
|
82
|
+
configErrorMessage: 'No live test config found at tests/live/playwright.config.ts',
|
|
83
|
+
});
|
|
84
|
+
results.push({ suite: 'live', code });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Exit with the first non-zero code, or 0 if all passed
|
|
88
|
+
const failed = results.find((r) => r.code !== 0);
|
|
89
|
+
process.exit(failed ? failed.code : 0);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Spawn a child process and return its exit code.
|
|
94
|
+
*/
|
|
95
|
+
function runChild(command, args, env) {
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
const child = spawn(command, args, {
|
|
98
|
+
stdio: 'inherit',
|
|
99
|
+
env: { ...process.env, ...env },
|
|
100
|
+
});
|
|
101
|
+
child.on('error', () => resolve(1));
|
|
102
|
+
child.on('exit', (code) => resolve(code ?? 1));
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Run Playwright and return the exit code.
|
|
108
|
+
*/
|
|
109
|
+
function runPlaywright(args, options = {}) {
|
|
110
|
+
const {
|
|
111
|
+
configCandidates = [],
|
|
112
|
+
configRequired = false,
|
|
113
|
+
configErrorMessage,
|
|
114
|
+
visual = false,
|
|
115
|
+
updateSnapshots = false,
|
|
116
|
+
} = options;
|
|
117
|
+
|
|
118
|
+
const config = findConfig(configCandidates);
|
|
119
|
+
|
|
120
|
+
if (!config && configRequired) {
|
|
121
|
+
console.error(configErrorMessage);
|
|
122
|
+
return Promise.resolve(1);
|
|
61
123
|
}
|
|
62
124
|
|
|
63
|
-
const
|
|
125
|
+
const configArgs = config ? ['--config', config] : [];
|
|
126
|
+
const extraArgs = updateSnapshots ? ['--update-snapshots'] : [];
|
|
127
|
+
|
|
128
|
+
return runChild(
|
|
64
129
|
'pnpm',
|
|
65
|
-
['exec', 'playwright', 'test', ...configArgs, ...
|
|
130
|
+
['exec', 'playwright', 'test', ...configArgs, ...extraArgs, ...args],
|
|
66
131
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
...process.env,
|
|
70
|
-
SUNPEAK_DEV_OVERLAY: process.env.SUNPEAK_DEV_OVERLAY ?? 'false',
|
|
71
|
-
},
|
|
132
|
+
SUNPEAK_DEV_OVERLAY: process.env.SUNPEAK_DEV_OVERLAY ?? 'false',
|
|
133
|
+
...(visual ? { SUNPEAK_VISUAL: 'true' } : {}),
|
|
72
134
|
}
|
|
73
135
|
);
|
|
74
|
-
child.on('exit', (code) => process.exit(code ?? 1));
|
|
75
136
|
}
|
|
76
137
|
|
|
77
138
|
function findConfig(candidates) {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { VisualConfig } from '../test/test-config.d.mts';
|
|
2
|
+
|
|
1
3
|
export interface InspectConfigOptions {
|
|
2
4
|
/** MCP server URL or stdio command string (required) */
|
|
3
5
|
server: string;
|
|
@@ -11,6 +13,8 @@ export interface InspectConfigOptions {
|
|
|
11
13
|
name?: string;
|
|
12
14
|
/** Additional Playwright `use` options */
|
|
13
15
|
use?: Record<string, unknown>;
|
|
16
|
+
/** Visual regression testing configuration */
|
|
17
|
+
visual?: VisualConfig;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
/**
|
|
@@ -36,6 +36,7 @@ export function defineInspectConfig(options) {
|
|
|
36
36
|
hosts = ['chatgpt', 'claude'],
|
|
37
37
|
name,
|
|
38
38
|
use: userUse,
|
|
39
|
+
visual,
|
|
39
40
|
} = options;
|
|
40
41
|
|
|
41
42
|
if (!server) {
|
|
@@ -60,6 +61,7 @@ export function defineInspectConfig(options) {
|
|
|
60
61
|
testDir,
|
|
61
62
|
port,
|
|
62
63
|
use: userUse,
|
|
64
|
+
visual,
|
|
63
65
|
webServer: {
|
|
64
66
|
command,
|
|
65
67
|
healthUrl: `http://localhost:${port}/health`,
|
|
@@ -17,7 +17,10 @@ import { getPortSync } from '../get-port.mjs';
|
|
|
17
17
|
* @param {string} [options.globalSetup] - Global setup file path
|
|
18
18
|
* @returns {import('@playwright/test').PlaywrightTestConfig}
|
|
19
19
|
*/
|
|
20
|
-
export function createBaseConfig({ hosts, testDir, webServer, port, use, globalSetup }) {
|
|
20
|
+
export function createBaseConfig({ hosts, testDir, webServer, port, use, globalSetup, visual }) {
|
|
21
|
+
// Separate snapshot path from other visual options passed to expect.toHaveScreenshot
|
|
22
|
+
const { snapshotPathTemplate, ...toHaveScreenshotDefaults } = visual ?? {};
|
|
23
|
+
|
|
21
24
|
return {
|
|
22
25
|
...(globalSetup ? { globalSetup } : {}),
|
|
23
26
|
testDir,
|
|
@@ -27,6 +30,18 @@ export function createBaseConfig({ hosts, testDir, webServer, port, use, globalS
|
|
|
27
30
|
// Limit workers to avoid overwhelming the double-iframe sandbox proxy.
|
|
28
31
|
workers: process.env.CI ? 1 : 2,
|
|
29
32
|
reporter: 'list',
|
|
33
|
+
// Only override snapshot path when visual config is provided, to avoid
|
|
34
|
+
// changing Playwright's default for projects that don't use visual testing.
|
|
35
|
+
...(visual
|
|
36
|
+
? {
|
|
37
|
+
snapshotPathTemplate:
|
|
38
|
+
snapshotPathTemplate ??
|
|
39
|
+
'{testDir}/__screenshots__/{projectName}/{testFilePath}/{arg}{ext}',
|
|
40
|
+
}
|
|
41
|
+
: {}),
|
|
42
|
+
...(Object.keys(toHaveScreenshotDefaults).length > 0
|
|
43
|
+
? { expect: { toHaveScreenshot: toHaveScreenshotDefaults } }
|
|
44
|
+
: {}),
|
|
30
45
|
use: {
|
|
31
46
|
baseURL: `http://localhost:${port}`,
|
|
32
47
|
trace: 'on-first-retry',
|
|
@@ -14,6 +14,26 @@ export interface ServerConfig {
|
|
|
14
14
|
env?: Record<string, string>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Visual regression testing configuration.
|
|
19
|
+
*
|
|
20
|
+
* All fields except `snapshotPathTemplate` are forwarded to Playwright's
|
|
21
|
+
* `expect.toHaveScreenshot` config. See Playwright docs for the full set
|
|
22
|
+
* of options (threshold, maxDiffPixelRatio, maxDiffPixels, animations, etc.).
|
|
23
|
+
*/
|
|
24
|
+
export interface VisualConfig {
|
|
25
|
+
/** Snapshot directory path template. Default: '{testDir}/__screenshots__/{projectName}/{testFilePath}/{arg}{ext}'. */
|
|
26
|
+
snapshotPathTemplate?: string;
|
|
27
|
+
/** Pixel comparison threshold (0-1). */
|
|
28
|
+
threshold?: number;
|
|
29
|
+
/** Maximum allowed ratio of differing pixels (0-1). */
|
|
30
|
+
maxDiffPixelRatio?: number;
|
|
31
|
+
/** Absolute count of allowed different pixels. */
|
|
32
|
+
maxDiffPixels?: number;
|
|
33
|
+
/** Any other Playwright toHaveScreenshot options applied as project-wide defaults. */
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
|
|
17
37
|
/**
|
|
18
38
|
* Configuration options for sunpeak test config.
|
|
19
39
|
*/
|
|
@@ -33,6 +53,8 @@ export interface TestConfigOptions {
|
|
|
33
53
|
globalSetup?: string;
|
|
34
54
|
/** Additional Playwright `use` options. */
|
|
35
55
|
use?: Record<string, unknown>;
|
|
56
|
+
/** Visual regression testing configuration. */
|
|
57
|
+
visual?: VisualConfig;
|
|
36
58
|
}
|
|
37
59
|
|
|
38
60
|
/**
|
|
@@ -41,6 +41,7 @@ export function defineConfig(options = {}) {
|
|
|
41
41
|
simulationsDir,
|
|
42
42
|
globalSetup,
|
|
43
43
|
use: userUse,
|
|
44
|
+
visual,
|
|
44
45
|
} = options;
|
|
45
46
|
|
|
46
47
|
const { port, sandboxPort } = resolvePorts();
|
|
@@ -67,6 +68,7 @@ export function defineConfig(options = {}) {
|
|
|
67
68
|
port,
|
|
68
69
|
use: userUse,
|
|
69
70
|
globalSetup,
|
|
71
|
+
visual,
|
|
70
72
|
webServer: {
|
|
71
73
|
command,
|
|
72
74
|
healthUrl: `http://localhost:${port}/health`,
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Page,
|
|
3
|
+
FrameLocator,
|
|
4
|
+
Locator,
|
|
5
|
+
TestType,
|
|
6
|
+
Expect,
|
|
7
|
+
PageAssertionsToHaveScreenshotOptions,
|
|
8
|
+
} from '@playwright/test';
|
|
2
9
|
|
|
3
10
|
/**
|
|
4
11
|
* Result from calling an MCP tool via the inspector.
|
|
@@ -31,6 +38,22 @@ export interface CallToolOptions {
|
|
|
31
38
|
[key: string]: unknown;
|
|
32
39
|
}
|
|
33
40
|
|
|
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
|
+
export interface ScreenshotOptions extends PageAssertionsToHaveScreenshotOptions {
|
|
51
|
+
/** What to screenshot: 'app' (inner iframe content) or 'page' (full inspector). Default: 'app'. */
|
|
52
|
+
target?: 'app' | 'page';
|
|
53
|
+
/** Specific locator to screenshot instead of the default target. */
|
|
54
|
+
element?: Locator;
|
|
55
|
+
}
|
|
56
|
+
|
|
34
57
|
/**
|
|
35
58
|
* MCP test fixture for testing MCP servers via the inspector.
|
|
36
59
|
*/
|
|
@@ -66,6 +89,16 @@ export interface McpFixture {
|
|
|
66
89
|
|
|
67
90
|
/** Change the display mode via the sidebar buttons. */
|
|
68
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>;
|
|
69
102
|
}
|
|
70
103
|
|
|
71
104
|
/**
|
|
@@ -180,6 +180,49 @@ const test = base.extend({
|
|
|
180
180
|
// Wait for display mode transition
|
|
181
181
|
await page.waitForTimeout(500);
|
|
182
182
|
},
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Take a screenshot and compare against a baseline.
|
|
186
|
+
* Only performs the comparison when visual testing is enabled
|
|
187
|
+
* (`sunpeak test --visual`). Silently skips otherwise, so tests
|
|
188
|
+
* that include screenshot() calls still pass during normal runs.
|
|
189
|
+
*
|
|
190
|
+
* Accepts all Playwright toHaveScreenshot() options (threshold,
|
|
191
|
+
* maxDiffPixelRatio, maxDiffPixels, mask, animations, caret,
|
|
192
|
+
* fullPage, clip, scale, stylePath, etc.) and passes them through.
|
|
193
|
+
*
|
|
194
|
+
* @param {string} [name] - Snapshot name (auto-generated from test title if omitted)
|
|
195
|
+
* @param {Object} [options] - Screenshot and comparison options
|
|
196
|
+
* @param {'app' | 'page'} [options.target='app'] - What to screenshot
|
|
197
|
+
* @param {import('@playwright/test').Locator} [options.element] - Specific locator to screenshot
|
|
198
|
+
*/
|
|
199
|
+
async screenshot(name, options = {}) {
|
|
200
|
+
if (process.env.SUNPEAK_VISUAL !== 'true') return;
|
|
201
|
+
|
|
202
|
+
// Support screenshot(options) without a name
|
|
203
|
+
if (typeof name === 'object' && name !== null) {
|
|
204
|
+
options = name;
|
|
205
|
+
name = undefined;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const { target = 'app', element, ...playwrightOptions } = options;
|
|
209
|
+
|
|
210
|
+
let locator;
|
|
211
|
+
if (element) {
|
|
212
|
+
locator = element;
|
|
213
|
+
} else if (target === 'page') {
|
|
214
|
+
locator = page.locator('#root');
|
|
215
|
+
} else {
|
|
216
|
+
locator = page.frameLocator('iframe').frameLocator('iframe').locator('body');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const fullName = name && !name.endsWith('.png') ? `${name}.png` : name;
|
|
220
|
+
const args = fullName
|
|
221
|
+
? [fullName, playwrightOptions]
|
|
222
|
+
: [playwrightOptions];
|
|
223
|
+
|
|
224
|
+
await expect(locator).toHaveScreenshot(...args);
|
|
225
|
+
},
|
|
183
226
|
};
|
|
184
227
|
|
|
185
228
|
await use(fixture);
|
package/dist/chatgpt/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../chunk-9hOWP6kD.cjs");
|
|
3
|
-
const require_inspector = require("../inspector-
|
|
3
|
+
const require_inspector = require("../inspector-Cvq3yjNL.cjs");
|
|
4
4
|
const require_inspector_url = require("../inspector-url-C3LTKgXt.cjs");
|
|
5
5
|
const require_discovery = require("../discovery-Clu4uHp1.cjs");
|
|
6
6
|
//#region src/chatgpt/index.ts
|
package/dist/chatgpt/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __exportAll } from "../chunk-D6g4UhsZ.js";
|
|
2
|
-
import { _ as McpAppHost, d as ThemeProvider, f as useThemeContext, g as extractResourceCSP, h as IframeResource, n as resolveServerToolResult, t as Inspector, v as SCREEN_WIDTHS } from "../inspector-
|
|
2
|
+
import { _ as McpAppHost, d as ThemeProvider, f as useThemeContext, g as extractResourceCSP, h as IframeResource, n as resolveServerToolResult, t as Inspector, v as SCREEN_WIDTHS } from "../inspector-Bp9jrHIu.js";
|
|
3
3
|
import { t as createInspectorUrl } from "../inspector-url-CyQcuBI9.js";
|
|
4
4
|
import { c as toPascalCase, i as findResourceKey, n as extractSimulationKey, r as findResourceDirs, s as getComponentName, t as extractResourceKey } from "../discovery-Cgoegt62.js";
|
|
5
5
|
//#region src/chatgpt/index.ts
|
package/dist/claude/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../chunk-9hOWP6kD.cjs");
|
|
3
|
-
const require_inspector = require("../inspector-
|
|
3
|
+
const require_inspector = require("../inspector-Cvq3yjNL.cjs");
|
|
4
4
|
exports.Inspector = require_inspector.Inspector;
|
package/dist/claude/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Inspector } from "../inspector-
|
|
1
|
+
import { t as Inspector } from "../inspector-Bp9jrHIu.js";
|
|
2
2
|
export { Inspector };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-9hOWP6kD.cjs");
|
|
3
|
-
const require_use_app = require("../../use-app-
|
|
3
|
+
const require_use_app = require("../../use-app-DHYiev3D.cjs");
|
|
4
4
|
let react = require("react");
|
|
5
5
|
//#region src/host/chatgpt/openai-types.ts
|
|
6
6
|
/**
|