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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { test, expect } from 'sunpeak/test';
|
|
2
2
|
|
|
3
|
-
test('should render review title with correct styles', async ({
|
|
4
|
-
const result = await
|
|
3
|
+
test('should render review title with correct styles', async ({ inspector }) => {
|
|
4
|
+
const result = await inspector.renderTool('review-diff');
|
|
5
5
|
const app = result.app();
|
|
6
6
|
|
|
7
7
|
const title = app.locator('h1:has-text("Refactor Authentication Module")');
|
|
@@ -13,8 +13,8 @@ test('should render review title with correct styles', async ({ mcp }) => {
|
|
|
13
13
|
expect(parseInt(styles.fontWeight)).toBeGreaterThanOrEqual(600);
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
test('should render change items with type-specific styling', async ({
|
|
17
|
-
const result = await
|
|
16
|
+
test('should render change items with type-specific styling', async ({ inspector }) => {
|
|
17
|
+
const result = await inspector.renderTool('review-diff');
|
|
18
18
|
const app = result.app();
|
|
19
19
|
|
|
20
20
|
const changeItem = app.locator('li').first();
|
|
@@ -27,8 +27,8 @@ test('should render change items with type-specific styling', async ({ mcp }) =>
|
|
|
27
27
|
expect(styles.backgroundColor).not.toBe('rgba(0, 0, 0, 0)');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
test('should have interactive apply and cancel buttons', async ({
|
|
31
|
-
const result = await
|
|
30
|
+
test('should have interactive apply and cancel buttons', async ({ inspector }) => {
|
|
31
|
+
const result = await inspector.renderTool('review-diff');
|
|
32
32
|
const app = result.app();
|
|
33
33
|
|
|
34
34
|
const applyButton = app.locator('button:has-text("Apply Changes")');
|
|
@@ -40,8 +40,8 @@ test('should have interactive apply and cancel buttons', async ({ mcp }) => {
|
|
|
40
40
|
expect(await cancelButton.evaluate((el) => window.getComputedStyle(el).cursor)).toBe('pointer');
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
test('should have expand fullscreen button in inline mode', async ({
|
|
44
|
-
const result = await
|
|
43
|
+
test('should have expand fullscreen button in inline mode', async ({ inspector }) => {
|
|
44
|
+
const result = await inspector.renderTool('review-diff', undefined, { displayMode: 'inline' });
|
|
45
45
|
const app = result.app();
|
|
46
46
|
|
|
47
47
|
const expandButton = app.locator('button[aria-label="Enter fullscreen"]');
|
|
@@ -49,50 +49,20 @@ test('should have expand fullscreen button in inline mode', async ({ mcp }) => {
|
|
|
49
49
|
expect(await expandButton.evaluate((el) => window.getComputedStyle(el).cursor)).toBe('pointer');
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
test('should
|
|
53
|
-
await
|
|
54
|
-
|
|
55
|
-
await expect(mcp.page.locator('text=Press Run to call the tool')).toBeVisible();
|
|
56
|
-
await expect(mcp.page.locator('button:has-text("Run")')).toBeVisible();
|
|
57
|
-
await expect(mcp.page.locator('iframe')).not.toBeAttached();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('should have themed empty state colors in light mode', async ({ mcp }) => {
|
|
61
|
-
await mcp.openTool('review-diff', { theme: 'light' });
|
|
62
|
-
|
|
63
|
-
const emptyState = mcp.page.locator('text=Press Run to call the tool');
|
|
64
|
-
await expect(emptyState).toBeVisible();
|
|
65
|
-
|
|
66
|
-
const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
|
|
67
|
-
const [r, g, b] = color.match(/\d+/g)!.map(Number);
|
|
68
|
-
expect(r + g + b).toBeLessThan(600);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test('should have themed empty state colors in dark mode', async ({ mcp }) => {
|
|
72
|
-
await mcp.openTool('review-diff', { theme: 'dark' });
|
|
73
|
-
|
|
74
|
-
const emptyState = mcp.page.locator('text=Press Run to call the tool');
|
|
75
|
-
await expect(emptyState).toBeVisible();
|
|
76
|
-
|
|
77
|
-
const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
|
|
78
|
-
const [r, g, b] = color.match(/\d+/g)!.map(Number);
|
|
79
|
-
expect(r + g + b).toBeGreaterThan(200);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
test('should activate prod resources mode without errors', async ({ mcp }) => {
|
|
83
|
-
await mcp.callTool('review-diff', {}, { theme: 'dark', prodResources: true });
|
|
84
|
-
const root = mcp.page.locator('#root');
|
|
52
|
+
test('should activate prod resources mode without errors', async ({ inspector }) => {
|
|
53
|
+
await inspector.renderTool('review-diff', undefined, { theme: 'dark', prodResources: true });
|
|
54
|
+
const root = inspector.page.locator('#root');
|
|
85
55
|
await expect(root).not.toBeEmpty();
|
|
86
56
|
});
|
|
87
57
|
|
|
88
|
-
test('should render review title in dark mode', async ({
|
|
89
|
-
const result = await
|
|
58
|
+
test('should render review title in dark mode', async ({ inspector }) => {
|
|
59
|
+
const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
|
|
90
60
|
const app = result.app();
|
|
91
61
|
await expect(app.locator('h1:has-text("Refactor Authentication Module")')).toBeVisible();
|
|
92
62
|
});
|
|
93
63
|
|
|
94
|
-
test('should have appropriate text colors in dark mode', async ({
|
|
95
|
-
const result = await
|
|
64
|
+
test('should have appropriate text colors in dark mode', async ({ inspector }) => {
|
|
65
|
+
const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
|
|
96
66
|
const app = result.app();
|
|
97
67
|
|
|
98
68
|
const title = app.locator('h1').first();
|
|
@@ -104,19 +74,19 @@ test('should have appropriate text colors in dark mode', async ({ mcp }) => {
|
|
|
104
74
|
expect(styles.color).toBeTruthy();
|
|
105
75
|
});
|
|
106
76
|
|
|
107
|
-
test('should render change items in dark mode', async ({
|
|
108
|
-
const result = await
|
|
77
|
+
test('should render change items in dark mode', async ({ inspector }) => {
|
|
78
|
+
const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
|
|
109
79
|
const app = result.app();
|
|
110
80
|
await expect(app.locator('li').first()).toBeVisible();
|
|
111
81
|
});
|
|
112
82
|
|
|
113
|
-
test('should load without console errors in dark mode', async ({
|
|
83
|
+
test('should load without console errors in dark mode', async ({ inspector }) => {
|
|
114
84
|
const errors: string[] = [];
|
|
115
|
-
|
|
85
|
+
inspector.page.on('console', (msg) => {
|
|
116
86
|
if (msg.type() === 'error') errors.push(msg.text());
|
|
117
87
|
});
|
|
118
88
|
|
|
119
|
-
const result = await
|
|
89
|
+
const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
|
|
120
90
|
const app = result.app();
|
|
121
91
|
await expect(app.locator('h1').first()).toBeVisible();
|
|
122
92
|
|
|
@@ -130,40 +100,41 @@ test('should load without console errors in dark mode', async ({ mcp }) => {
|
|
|
130
100
|
expect(unexpectedErrors).toHaveLength(0);
|
|
131
101
|
});
|
|
132
102
|
|
|
133
|
-
test('should not show fullscreen button in fullscreen mode', async ({
|
|
134
|
-
const result = await
|
|
103
|
+
test('should not show fullscreen button in fullscreen mode', async ({ inspector }) => {
|
|
104
|
+
const result = await inspector.renderTool('review-diff', undefined, {
|
|
105
|
+
displayMode: 'fullscreen',
|
|
106
|
+
});
|
|
135
107
|
const app = result.app();
|
|
136
108
|
|
|
137
109
|
await expect(app.locator('h1').first()).toBeVisible();
|
|
138
110
|
await expect(app.locator('button[aria-label="Enter fullscreen"]')).not.toBeVisible();
|
|
139
111
|
});
|
|
140
112
|
|
|
141
|
-
test('should render content in fullscreen mode', async ({
|
|
142
|
-
const result = await
|
|
143
|
-
'
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
);
|
|
113
|
+
test('should render content in fullscreen mode', async ({ inspector }) => {
|
|
114
|
+
const result = await inspector.renderTool('review-diff', undefined, {
|
|
115
|
+
theme: 'dark',
|
|
116
|
+
displayMode: 'fullscreen',
|
|
117
|
+
});
|
|
147
118
|
const app = result.app();
|
|
148
119
|
|
|
149
|
-
await expect(
|
|
120
|
+
await expect(inspector.page.locator('#root')).not.toBeEmpty();
|
|
150
121
|
await expect(app.locator('h1')).toBeVisible();
|
|
151
122
|
});
|
|
152
123
|
|
|
153
|
-
test('should render post review in light mode', async ({
|
|
154
|
-
await
|
|
155
|
-
await
|
|
156
|
-
await expect(
|
|
124
|
+
test('should render post review in light mode', async ({ inspector }) => {
|
|
125
|
+
await inspector.renderTool('review-post');
|
|
126
|
+
await inspector.page.waitForLoadState('networkidle');
|
|
127
|
+
await expect(inspector.page.locator('#root')).not.toBeEmpty();
|
|
157
128
|
});
|
|
158
129
|
|
|
159
|
-
test('should render post review in dark mode', async ({
|
|
160
|
-
await
|
|
161
|
-
await
|
|
162
|
-
await expect(
|
|
130
|
+
test('should render post review in dark mode', async ({ inspector }) => {
|
|
131
|
+
await inspector.renderTool('review-post', undefined, { theme: 'dark' });
|
|
132
|
+
await inspector.page.waitForLoadState('networkidle');
|
|
133
|
+
await expect(inspector.page.locator('#root')).not.toBeEmpty();
|
|
163
134
|
});
|
|
164
135
|
|
|
165
|
-
test('should show server success message when confirming post', async ({
|
|
166
|
-
const result = await
|
|
136
|
+
test('should show server success message when confirming post', async ({ inspector }) => {
|
|
137
|
+
const result = await inspector.renderTool('review-post', undefined, { theme: 'dark' });
|
|
167
138
|
const app = result.app();
|
|
168
139
|
|
|
169
140
|
const publishButton = app.locator('button:has-text("Publish")');
|
|
@@ -174,8 +145,8 @@ test('should show server success message when confirming post', async ({ mcp })
|
|
|
174
145
|
await expect(app.locator('text=Publishing post...')).toBeVisible({ timeout: 10000 });
|
|
175
146
|
});
|
|
176
147
|
|
|
177
|
-
test('should show server cancel message when rejecting post', async ({
|
|
178
|
-
const result = await
|
|
148
|
+
test('should show server cancel message when rejecting post', async ({ inspector }) => {
|
|
149
|
+
const result = await inspector.renderTool('review-post', undefined, { theme: 'dark' });
|
|
179
150
|
const app = result.app();
|
|
180
151
|
|
|
181
152
|
const cancelButton = app.locator('button:has-text("Cancel")');
|
|
@@ -185,20 +156,20 @@ test('should show server cancel message when rejecting post', async ({ mcp }) =>
|
|
|
185
156
|
await expect(app.locator('text=Cancelled.')).toBeVisible({ timeout: 10000 });
|
|
186
157
|
});
|
|
187
158
|
|
|
188
|
-
test('should render purchase review in light mode', async ({
|
|
189
|
-
await
|
|
190
|
-
await
|
|
191
|
-
await expect(
|
|
159
|
+
test('should render purchase review in light mode', async ({ inspector }) => {
|
|
160
|
+
await inspector.renderTool('review-purchase');
|
|
161
|
+
await inspector.page.waitForLoadState('networkidle');
|
|
162
|
+
await expect(inspector.page.locator('#root')).not.toBeEmpty();
|
|
192
163
|
});
|
|
193
164
|
|
|
194
|
-
test('should render purchase review in dark mode', async ({
|
|
195
|
-
await
|
|
196
|
-
await
|
|
197
|
-
await expect(
|
|
165
|
+
test('should render purchase review in dark mode', async ({ inspector }) => {
|
|
166
|
+
await inspector.renderTool('review-purchase', undefined, { theme: 'dark' });
|
|
167
|
+
await inspector.page.waitForLoadState('networkidle');
|
|
168
|
+
await expect(inspector.page.locator('#root')).not.toBeEmpty();
|
|
198
169
|
});
|
|
199
170
|
|
|
200
|
-
test('should show loading then result when placing order', async ({
|
|
201
|
-
const result = await
|
|
171
|
+
test('should show loading then result when placing order', async ({ inspector }) => {
|
|
172
|
+
const result = await inspector.renderTool('review-purchase');
|
|
202
173
|
const app = result.app();
|
|
203
174
|
|
|
204
175
|
const placeOrderButton = app.locator('button:has-text("Place Order")');
|
|
@@ -209,8 +180,8 @@ test('should show loading then result when placing order', async ({ mcp }) => {
|
|
|
209
180
|
await expect(app.locator('text=Completed.')).toBeVisible({ timeout: 10000 });
|
|
210
181
|
});
|
|
211
182
|
|
|
212
|
-
test('should confirm review-diff and show server success', async ({
|
|
213
|
-
const result = await
|
|
183
|
+
test('should confirm review-diff and show server success', async ({ inspector }) => {
|
|
184
|
+
const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
|
|
214
185
|
const app = result.app();
|
|
215
186
|
|
|
216
187
|
const applyButton = app.locator('button:has-text("Apply Changes")');
|
|
@@ -221,8 +192,8 @@ test('should confirm review-diff and show server success', async ({ mcp }) => {
|
|
|
221
192
|
await expect(app.locator('text=Completed.')).toBeVisible({ timeout: 10000 });
|
|
222
193
|
});
|
|
223
194
|
|
|
224
|
-
test('should cancel review-diff and show server cancelled', async ({
|
|
225
|
-
const result = await
|
|
195
|
+
test('should cancel review-diff and show server cancelled', async ({ inspector }) => {
|
|
196
|
+
const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
|
|
226
197
|
const app = result.app();
|
|
227
198
|
|
|
228
199
|
const cancelButton = app.locator('button:has-text("Cancel")');
|
|
@@ -3,34 +3,36 @@ import { test, expect } from 'sunpeak/test';
|
|
|
3
3
|
// Visual regression tests. Screenshot comparisons only run with `sunpeak test --visual`.
|
|
4
4
|
// Update baselines with `sunpeak test --visual --update`.
|
|
5
5
|
|
|
6
|
-
test('albums renders correctly in light mode', async ({
|
|
7
|
-
const result = await
|
|
6
|
+
test('albums renders correctly in light mode', async ({ inspector }) => {
|
|
7
|
+
const result = await inspector.renderTool('show-albums', undefined, { theme: 'light' });
|
|
8
8
|
const app = result.app();
|
|
9
9
|
await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible();
|
|
10
10
|
|
|
11
|
-
await
|
|
11
|
+
await result.screenshot('albums-light');
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
test('albums renders correctly in dark mode', async ({
|
|
15
|
-
const result = await
|
|
14
|
+
test('albums renders correctly in dark mode', async ({ inspector }) => {
|
|
15
|
+
const result = await inspector.renderTool('show-albums', undefined, { theme: 'dark' });
|
|
16
16
|
const app = result.app();
|
|
17
17
|
await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible();
|
|
18
18
|
|
|
19
|
-
await
|
|
19
|
+
await result.screenshot('albums-dark');
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
test('albums renders correctly in fullscreen', async ({
|
|
23
|
-
const result = await
|
|
22
|
+
test('albums renders correctly in fullscreen', async ({ inspector }) => {
|
|
23
|
+
const result = await inspector.renderTool('show-albums', undefined, {
|
|
24
|
+
displayMode: 'fullscreen',
|
|
25
|
+
});
|
|
24
26
|
const app = result.app();
|
|
25
27
|
await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible();
|
|
26
28
|
|
|
27
|
-
await
|
|
29
|
+
await result.screenshot('albums-fullscreen');
|
|
28
30
|
});
|
|
29
31
|
|
|
30
|
-
test('full page renders correctly', async ({
|
|
31
|
-
const result = await
|
|
32
|
+
test('full page renders correctly', async ({ inspector }) => {
|
|
33
|
+
const result = await inspector.renderTool('show-albums', undefined, { theme: 'light' });
|
|
32
34
|
const app = result.app();
|
|
33
35
|
await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible();
|
|
34
36
|
|
|
35
|
-
await
|
|
37
|
+
await result.screenshot('albums-page-light', { target: 'page', maxDiffPixelRatio: 0.02 });
|
|
36
38
|
});
|