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.
Files changed (85) hide show
  1. package/README.md +2 -2
  2. package/bin/commands/inspect.mjs +361 -12
  3. package/bin/commands/test-init.mjs +190 -118
  4. package/bin/commands/test.mjs +12 -1
  5. package/bin/lib/eval/eval-runner.mjs +7 -1
  6. package/bin/lib/inspect/inspect-config.mjs +17 -2
  7. package/bin/lib/inspect/inspect-server.d.mts +32 -0
  8. package/bin/lib/inspect/inspect-server.mjs +11 -0
  9. package/bin/lib/live/live-config.d.mts +10 -0
  10. package/bin/lib/live/live-config.mjs +34 -2
  11. package/bin/lib/resolve-bin.mjs +39 -0
  12. package/bin/lib/test/base-config.mjs +6 -3
  13. package/bin/lib/test/matchers.mjs +2 -2
  14. package/bin/lib/test/test-config.mjs +19 -8
  15. package/bin/lib/test/test-fixtures.d.mts +52 -92
  16. package/bin/lib/test/test-fixtures.mjs +174 -147
  17. package/dist/chatgpt/index.cjs +1 -1
  18. package/dist/chatgpt/index.js +1 -1
  19. package/dist/claude/index.cjs +1 -1
  20. package/dist/claude/index.js +1 -1
  21. package/dist/host/chatgpt/index.cjs +1 -1
  22. package/dist/host/chatgpt/index.js +1 -1
  23. package/dist/index.cjs +4 -4
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +3 -3
  26. package/dist/index.js.map +1 -1
  27. package/dist/inspector/index.cjs +1 -1
  28. package/dist/inspector/index.js +1 -1
  29. package/dist/{inspector-D5DckQuU.js → inspector-BBDa5yCm.js} +57 -23
  30. package/dist/inspector-BBDa5yCm.js.map +1 -0
  31. package/dist/{inspector-jY9O18z9.cjs → inspector-DAA1Wiyh.cjs} +58 -24
  32. package/dist/inspector-DAA1Wiyh.cjs.map +1 -0
  33. package/dist/lib/discovery-cli.cjs +1 -1
  34. package/dist/mcp/index.cjs +22 -25
  35. package/dist/mcp/index.cjs.map +1 -1
  36. package/dist/mcp/index.js +19 -22
  37. package/dist/mcp/index.js.map +1 -1
  38. package/dist/{use-app-Bfargfa3.js → use-app-Cr0auUa1.js} +2 -2
  39. package/dist/{use-app-Bfargfa3.js.map → use-app-Cr0auUa1.js.map} +1 -1
  40. package/dist/{use-app-CbsBEmwv.cjs → use-app-DPkj5Jp_.cjs} +2 -2
  41. package/dist/{use-app-CbsBEmwv.cjs.map → use-app-DPkj5Jp_.cjs.map} +1 -1
  42. package/package.json +17 -11
  43. package/template/dist/albums/albums.html +4 -4
  44. package/template/dist/albums/albums.json +1 -1
  45. package/template/dist/carousel/carousel.html +4 -4
  46. package/template/dist/carousel/carousel.json +1 -1
  47. package/template/dist/map/map.html +6 -6
  48. package/template/dist/map/map.json +1 -1
  49. package/template/dist/review/review.html +4 -4
  50. package/template/dist/review/review.json +1 -1
  51. package/template/node_modules/.bin/vite +2 -2
  52. package/template/node_modules/.bin/vitest +2 -2
  53. package/template/node_modules/.vite/deps/_metadata.json +4 -4
  54. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +1 -1
  55. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
  56. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +1 -1
  57. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
  58. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +1 -1
  59. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
  60. package/template/node_modules/.vite-mcp/deps/@testing-library_react.js +4 -4
  61. package/template/node_modules/.vite-mcp/deps/@testing-library_react.js.map +1 -1
  62. package/template/node_modules/.vite-mcp/deps/_metadata.json +33 -33
  63. package/template/node_modules/.vite-mcp/deps/{client-CU1wWud4.js → client-B_5CX--u.js} +7 -7
  64. package/template/node_modules/.vite-mcp/deps/{client-CU1wWud4.js.map → client-B_5CX--u.js.map} +1 -1
  65. package/template/node_modules/.vite-mcp/deps/embla-carousel-react.js +1 -1
  66. package/template/node_modules/.vite-mcp/deps/embla-carousel-react.js.map +1 -1
  67. package/template/node_modules/.vite-mcp/deps/react-dom.js +3 -3
  68. package/template/node_modules/.vite-mcp/deps/react-dom.js.map +1 -1
  69. package/template/node_modules/.vite-mcp/deps/react-dom_client.js +1 -1
  70. package/template/node_modules/.vite-mcp/deps/react.js +3 -3
  71. package/template/node_modules/.vite-mcp/deps/react.js.map +1 -1
  72. package/template/node_modules/.vite-mcp/deps/react_jsx-dev-runtime.js +2 -2
  73. package/template/node_modules/.vite-mcp/deps/react_jsx-dev-runtime.js.map +1 -1
  74. package/template/node_modules/.vite-mcp/deps/react_jsx-runtime.js +2 -2
  75. package/template/node_modules/.vite-mcp/deps/react_jsx-runtime.js.map +1 -1
  76. package/template/node_modules/.vite-mcp/deps/vitest.js +1024 -622
  77. package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
  78. package/template/package.json +6 -6
  79. package/template/tests/e2e/albums.spec.ts +24 -52
  80. package/template/tests/e2e/carousel.spec.ts +36 -58
  81. package/template/tests/e2e/map.spec.ts +35 -56
  82. package/template/tests/e2e/review.spec.ts +56 -85
  83. package/template/tests/e2e/visual.spec.ts +14 -12
  84. package/dist/inspector-D5DckQuU.js.map +0 -1
  85. package/dist/inspector-jY9O18z9.cjs.map +0 -1
@@ -28,16 +28,16 @@
28
28
  "@testing-library/jest-dom": "^6.9.1",
29
29
  "@testing-library/react": "^16.3.2",
30
30
  "@testing-library/user-event": "^14.6.1",
31
- "@types/node": "^25.5.2",
31
+ "@types/node": "^25.6.0",
32
32
  "@types/react": "^19.2.14",
33
33
  "@types/react-dom": "^19.2.3",
34
34
  "@vitejs/plugin-react": "^6.0.1",
35
- "happy-dom": "^18.0.1",
36
- "react": "^19.2.4",
37
- "react-dom": "^19.2.4",
35
+ "happy-dom": "^20.8.9",
36
+ "react": "^19.2.5",
37
+ "react-dom": "^19.2.5",
38
38
  "tailwindcss": "^4.2.2",
39
39
  "typescript": "^5.9.3",
40
- "vite": "^8.0.3",
41
- "vitest": "^4.1.2"
40
+ "vite": "^8.0.8",
41
+ "vitest": "^4.1.4"
42
42
  }
43
43
  }
@@ -1,7 +1,7 @@
1
1
  import { test, expect } from 'sunpeak/test';
2
2
 
3
- test('should render album cards with correct styles', async ({ mcp }) => {
4
- const result = await mcp.callTool('show-albums');
3
+ test('should render album cards with correct styles', async ({ inspector }) => {
4
+ const result = await inspector.renderTool('show-albums');
5
5
  const app = result.app();
6
6
 
7
7
  const albumCard = app.locator('button:has-text("Summer Slice")');
@@ -15,8 +15,8 @@ test('should render album cards with correct styles', async ({ mcp }) => {
15
15
  expect(styles.borderRadius).toBe('12px');
16
16
  });
17
17
 
18
- test('should have album image with correct aspect ratio', async ({ mcp }) => {
19
- const result = await mcp.callTool('show-albums');
18
+ test('should have album image with correct aspect ratio', async ({ inspector }) => {
19
+ const result = await inspector.renderTool('show-albums');
20
20
  const app = result.app();
21
21
 
22
22
  const imageContainer = app.locator('button:has-text("Summer Slice") .aspect-\\[4\\/3\\]');
@@ -30,8 +30,8 @@ test('should have album image with correct aspect ratio', async ({ mcp }) => {
30
30
  expect(styles.overflow).toBe('hidden');
31
31
  });
32
32
 
33
- test('should render album cards in dark mode', async ({ mcp }) => {
34
- const result = await mcp.callTool('show-albums', {}, { theme: 'dark' });
33
+ test('should render album cards in dark mode', async ({ inspector }) => {
34
+ const result = await inspector.renderTool('show-albums', undefined, { theme: 'dark' });
35
35
  const app = result.app();
36
36
 
37
37
  const albumTitle = app.locator('button:has-text("Summer Slice") div').first();
@@ -43,44 +43,16 @@ test('should render album cards in dark mode', async ({ mcp }) => {
43
43
  expect(titleStyles.color).toBeTruthy();
44
44
  });
45
45
 
46
- test('should show empty state with Run button in prod tools mode', async ({ mcp }) => {
47
- await mcp.openTool('show-albums', { theme: 'dark' });
48
-
49
- await expect(mcp.page.locator('text=Press Run to call the tool')).toBeVisible();
50
- await expect(mcp.page.locator('button:has-text("Run")')).toBeVisible();
51
- await expect(mcp.page.locator('iframe')).not.toBeAttached();
52
- });
53
-
54
- test('should have themed empty state colors in light mode', async ({ mcp }) => {
55
- await mcp.openTool('show-albums', { theme: 'light' });
56
-
57
- const emptyState = mcp.page.locator('text=Press Run to call the tool');
58
- await expect(emptyState).toBeVisible();
59
-
60
- const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
61
- const [r, g, b] = color.match(/\d+/g)!.map(Number);
62
- expect(r + g + b).toBeLessThan(600);
63
- });
64
-
65
- test('should have themed empty state colors in dark mode', async ({ mcp }) => {
66
- await mcp.openTool('show-albums', { theme: 'dark' });
67
-
68
- const emptyState = mcp.page.locator('text=Press Run to call the tool');
69
- await expect(emptyState).toBeVisible();
70
-
71
- const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
72
- const [r, g, b] = color.match(/\d+/g)!.map(Number);
73
- expect(r + g + b).toBeGreaterThan(200);
74
- });
75
-
76
- test('should activate prod resources mode without errors', async ({ mcp }) => {
77
- await mcp.callTool('show-albums', {}, { theme: 'dark', prodResources: true });
78
- const root = mcp.page.locator('#root');
46
+ test('should activate prod resources mode without errors', async ({ inspector }) => {
47
+ await inspector.renderTool('show-albums', undefined, { theme: 'dark', prodResources: true });
48
+ const root = inspector.page.locator('#root');
79
49
  await expect(root).not.toBeEmpty();
80
50
  });
81
51
 
82
- test('should render correctly in fullscreen', async ({ mcp }) => {
83
- const result = await mcp.callTool('show-albums', {}, { displayMode: 'fullscreen' });
52
+ test('should render correctly in fullscreen', async ({ inspector }) => {
53
+ const result = await inspector.renderTool('show-albums', undefined, {
54
+ displayMode: 'fullscreen',
55
+ });
84
56
  const app = result.app();
85
57
 
86
58
  const albumCard = app.locator('button:has-text("Summer Slice")');
@@ -94,22 +66,22 @@ test('should render correctly in fullscreen', async ({ mcp }) => {
94
66
  expect(styles.borderRadius).toBe('12px');
95
67
  });
96
68
 
97
- test('should preserve content when switching to fullscreen', async ({ mcp }) => {
98
- const result = await mcp.callTool('show-albums', {}, { theme: 'dark' });
69
+ test('should render content in fullscreen mode', async ({ inspector }) => {
70
+ const result = await inspector.renderTool('show-albums', undefined, {
71
+ theme: 'dark',
72
+ displayMode: 'fullscreen',
73
+ });
99
74
  const app = result.app();
100
75
  await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible();
101
-
102
- await mcp.setDisplayMode('fullscreen');
103
- await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible({ timeout: 5000 });
104
76
  });
105
77
 
106
- test('should preserve content when switching to PiP', async ({ mcp }) => {
107
- test.skip(mcp.host === 'claude', 'Claude does not support PiP');
78
+ test('should render content in PiP mode', async ({ inspector }) => {
79
+ test.skip(inspector.host === 'claude', 'Claude does not support PiP');
108
80
 
109
- const result = await mcp.callTool('show-albums', {}, { theme: 'dark' });
81
+ const result = await inspector.renderTool('show-albums', undefined, {
82
+ theme: 'dark',
83
+ displayMode: 'pip',
84
+ });
110
85
  const app = result.app();
111
86
  await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible();
112
-
113
- await mcp.setDisplayMode('pip');
114
- await expect(app.locator('button:has-text("Summer Slice")')).toBeVisible({ timeout: 5000 });
115
87
  });
@@ -1,7 +1,7 @@
1
1
  import { test, expect } from 'sunpeak/test';
2
2
 
3
- test('should render carousel cards with correct styles', async ({ mcp }) => {
4
- const result = await mcp.callTool('show-carousel');
3
+ test('should render carousel cards with correct styles', async ({ inspector }) => {
4
+ const result = await inspector.renderTool('show-carousel');
5
5
  const app = result.app();
6
6
 
7
7
  const card = app.locator('.rounded-2xl').first();
@@ -15,8 +15,8 @@ test('should render carousel cards with correct styles', async ({ mcp }) => {
15
15
  expect(styles.cursor).toBe('pointer');
16
16
  });
17
17
 
18
- test('should have card with border styling', async ({ mcp }) => {
19
- const result = await mcp.callTool('show-carousel');
18
+ test('should have card with border styling', async ({ inspector }) => {
19
+ const result = await inspector.renderTool('show-carousel');
20
20
  const app = result.app();
21
21
 
22
22
  const card = app.locator('.rounded-2xl.border').first();
@@ -30,8 +30,8 @@ test('should have card with border styling', async ({ mcp }) => {
30
30
  expect(styles.borderStyle).toBe('solid');
31
31
  });
32
32
 
33
- test('should have interactive buttons', async ({ mcp }) => {
34
- const result = await mcp.callTool('show-carousel');
33
+ test('should have interactive buttons', async ({ inspector }) => {
34
+ const result = await inspector.renderTool('show-carousel');
35
35
  const app = result.app();
36
36
 
37
37
  const visitButton = app.locator('button:has-text("Visit")').first();
@@ -43,51 +43,23 @@ test('should have interactive buttons', async ({ mcp }) => {
43
43
  expect(styles.cursor).toBe('pointer');
44
44
  });
45
45
 
46
- test('should show empty state with Run button in prod tools mode', async ({ mcp }) => {
47
- await mcp.openTool('show-carousel', { theme: 'dark' });
48
-
49
- await expect(mcp.page.locator('text=Press Run to call the tool')).toBeVisible();
50
- await expect(mcp.page.locator('button:has-text("Run")')).toBeVisible();
51
- await expect(mcp.page.locator('iframe')).not.toBeAttached();
52
- });
53
-
54
- test('should have themed empty state colors in light mode', async ({ mcp }) => {
55
- await mcp.openTool('show-carousel', { theme: 'light' });
56
-
57
- const emptyState = mcp.page.locator('text=Press Run to call the tool');
58
- await expect(emptyState).toBeVisible();
59
-
60
- const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
61
- const [r, g, b] = color.match(/\d+/g)!.map(Number);
62
- expect(r + g + b).toBeLessThan(600);
63
- });
64
-
65
- test('should have themed empty state colors in dark mode', async ({ mcp }) => {
66
- await mcp.openTool('show-carousel', { theme: 'dark' });
67
-
68
- const emptyState = mcp.page.locator('text=Press Run to call the tool');
69
- await expect(emptyState).toBeVisible();
70
-
71
- const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
72
- const [r, g, b] = color.match(/\d+/g)!.map(Number);
73
- expect(r + g + b).toBeGreaterThan(200);
74
- });
75
-
76
- test('should activate prod resources mode without errors', async ({ mcp }) => {
77
- await mcp.callTool('show-carousel', {}, { theme: 'dark', prodResources: true });
78
- const root = mcp.page.locator('#root');
46
+ test('should activate prod resources mode without errors', async ({ inspector }) => {
47
+ await inspector.renderTool('show-carousel', undefined, { theme: 'dark', prodResources: true });
48
+ const root = inspector.page.locator('#root');
79
49
  await expect(root).not.toBeEmpty();
80
50
  });
81
51
 
82
- test('should render correctly in fullscreen', async ({ mcp }) => {
83
- await mcp.callTool('show-carousel', {}, { displayMode: 'fullscreen' });
84
- await mcp.page.waitForLoadState('networkidle');
85
- const root = mcp.page.locator('#root');
52
+ test('should render correctly in fullscreen', async ({ inspector }) => {
53
+ await inspector.renderTool('show-carousel', undefined, { displayMode: 'fullscreen' });
54
+ await inspector.page.waitForLoadState('networkidle');
55
+ const root = inspector.page.locator('#root');
86
56
  await expect(root).not.toBeEmpty();
87
57
  });
88
58
 
89
- test('should show detail view with place info in fullscreen', async ({ mcp }) => {
90
- const result = await mcp.callTool('show-carousel', {}, { displayMode: 'fullscreen' });
59
+ test('should show detail view with place info in fullscreen', async ({ inspector }) => {
60
+ const result = await inspector.renderTool('show-carousel', undefined, {
61
+ displayMode: 'fullscreen',
62
+ });
91
63
  const app = result.app();
92
64
 
93
65
  const card = app.locator('.rounded-2xl').first();
@@ -99,8 +71,10 @@ test('should show detail view with place info in fullscreen', async ({ mcp }) =>
99
71
  await expect(app.locator('text=Tips')).toBeVisible();
100
72
  });
101
73
 
102
- test('should show detail view when Learn More is clicked', async ({ mcp }) => {
103
- const result = await mcp.callTool('show-carousel', {}, { displayMode: 'fullscreen' });
74
+ test('should show detail view when Learn More is clicked', async ({ inspector }) => {
75
+ const result = await inspector.renderTool('show-carousel', undefined, {
76
+ displayMode: 'fullscreen',
77
+ });
104
78
  const app = result.app();
105
79
 
106
80
  const learnMore = app.locator('button:has-text("Learn More")').first();
@@ -111,8 +85,10 @@ test('should show detail view when Learn More is clicked', async ({ mcp }) => {
111
85
  await expect(app.locator('text=Address')).toBeVisible();
112
86
  });
113
87
 
114
- test('should not have a back button in detail view', async ({ mcp }) => {
115
- const result = await mcp.callTool('show-carousel', {}, { displayMode: 'fullscreen' });
88
+ test('should not have a back button in detail view', async ({ inspector }) => {
89
+ const result = await inspector.renderTool('show-carousel', undefined, {
90
+ displayMode: 'fullscreen',
91
+ });
116
92
  const app = result.app();
117
93
 
118
94
  const card = app.locator('.rounded-2xl').first();
@@ -124,8 +100,10 @@ test('should not have a back button in detail view', async ({ mcp }) => {
124
100
  await expect(backButton).not.toBeAttached();
125
101
  });
126
102
 
127
- test('should center the hero image without stretching', async ({ mcp }) => {
128
- const result = await mcp.callTool('show-carousel', {}, { displayMode: 'fullscreen' });
103
+ test('should center the hero image without stretching', async ({ inspector }) => {
104
+ const result = await inspector.renderTool('show-carousel', undefined, {
105
+ displayMode: 'fullscreen',
106
+ });
129
107
  const app = result.app();
130
108
 
131
109
  const card = app.locator('.rounded-2xl').first();
@@ -140,8 +118,8 @@ test('should center the hero image without stretching', async ({ mcp }) => {
140
118
  expect(styles.justifyContent).toBe('center');
141
119
  });
142
120
 
143
- test('should render carousel in dark mode with correct styles', async ({ mcp }) => {
144
- const result = await mcp.callTool('show-carousel', {}, { theme: 'dark' });
121
+ test('should render carousel in dark mode with correct styles', async ({ inspector }) => {
122
+ const result = await inspector.renderTool('show-carousel', undefined, { theme: 'dark' });
145
123
  const app = result.app();
146
124
 
147
125
  const card = app.locator('.rounded-2xl').first();
@@ -155,8 +133,8 @@ test('should render carousel in dark mode with correct styles', async ({ mcp })
155
133
  expect(styles.cursor).toBe('pointer');
156
134
  });
157
135
 
158
- test('should have appropriate dark mode styling', async ({ mcp }) => {
159
- const result = await mcp.callTool('show-carousel', {}, { theme: 'dark' });
136
+ test('should have appropriate dark mode styling', async ({ inspector }) => {
137
+ const result = await inspector.renderTool('show-carousel', undefined, { theme: 'dark' });
160
138
  const app = result.app();
161
139
 
162
140
  const card = app.locator('.rounded-2xl.border').first();
@@ -170,13 +148,13 @@ test('should have appropriate dark mode styling', async ({ mcp }) => {
170
148
  expect(styles.borderStyle).toBe('solid');
171
149
  });
172
150
 
173
- test('should load without console errors in dark mode', async ({ mcp }) => {
151
+ test('should load without console errors in dark mode', async ({ inspector }) => {
174
152
  const errors: string[] = [];
175
- mcp.page.on('console', (msg) => {
153
+ inspector.page.on('console', (msg) => {
176
154
  if (msg.type() === 'error') errors.push(msg.text());
177
155
  });
178
156
 
179
- const result = await mcp.callTool('show-carousel', {}, { theme: 'dark' });
157
+ const result = await inspector.renderTool('show-carousel', undefined, { theme: 'dark' });
180
158
  const app = result.app();
181
159
  await expect(app.locator('.rounded-2xl').first()).toBeVisible();
182
160
 
@@ -1,7 +1,7 @@
1
1
  import { test, expect } from 'sunpeak/test';
2
2
 
3
- test('should render map container with correct styles', async ({ mcp }) => {
4
- const result = await mcp.callTool('show-map');
3
+ test('should render map container with correct styles', async ({ inspector }) => {
4
+ const result = await inspector.renderTool('show-map');
5
5
  const app = result.app();
6
6
 
7
7
  const mapContainer = app.locator('.antialiased.w-full.overflow-hidden').first();
@@ -13,8 +13,8 @@ test('should render map container with correct styles', async ({ mcp }) => {
13
13
  expect(styles.overflow).toBe('hidden');
14
14
  });
15
15
 
16
- test('should have rounded border in inline mode', async ({ mcp }) => {
17
- const result = await mcp.callTool('show-map', {}, { displayMode: 'inline' });
16
+ test('should have rounded border in inline mode', async ({ inspector }) => {
17
+ const result = await inspector.renderTool('show-map', undefined, { displayMode: 'inline' });
18
18
  const app = result.app();
19
19
 
20
20
  const innerContainer = app.locator('.border.rounded-2xl').first();
@@ -26,8 +26,8 @@ test('should have rounded border in inline mode', async ({ mcp }) => {
26
26
  expect(parseInt(styles.borderRadius)).toBeGreaterThanOrEqual(16);
27
27
  });
28
28
 
29
- test('should have fullscreen expand button in inline mode', async ({ mcp }) => {
30
- const result = await mcp.callTool('show-map', {}, { displayMode: 'inline' });
29
+ test('should have fullscreen expand button in inline mode', async ({ inspector }) => {
30
+ const result = await inspector.renderTool('show-map', undefined, { displayMode: 'inline' });
31
31
  const app = result.app();
32
32
 
33
33
  const expandButton = app.locator('button[aria-label="Enter fullscreen"]');
@@ -41,13 +41,13 @@ test('should have fullscreen expand button in inline mode', async ({ mcp }) => {
41
41
  expect(styles.position).toBe('absolute');
42
42
  });
43
43
 
44
- test('should load without console errors in light mode', async ({ mcp }) => {
44
+ test('should load without console errors in light mode', async ({ inspector }) => {
45
45
  const errors: string[] = [];
46
- mcp.page.on('console', (msg) => {
46
+ inspector.page.on('console', (msg) => {
47
47
  if (msg.type() === 'error') errors.push(msg.text());
48
48
  });
49
49
 
50
- const result = await mcp.callTool('show-map');
50
+ const result = await inspector.renderTool('show-map');
51
51
  const app = result.app();
52
52
  await expect(app.locator('.antialiased.w-full.overflow-hidden').first()).toBeVisible({
53
53
  timeout: 10000,
@@ -63,52 +63,25 @@ test('should load without console errors in light mode', async ({ mcp }) => {
63
63
  expect(unexpectedErrors).toHaveLength(0);
64
64
  });
65
65
 
66
- test('should show empty state with Run button in prod tools mode', async ({ mcp }) => {
67
- await mcp.openTool('show-map', { theme: 'dark' });
68
-
69
- await expect(mcp.page.locator('text=Press Run to call the tool')).toBeVisible();
70
- await expect(mcp.page.locator('button:has-text("Run")')).toBeVisible();
71
- await expect(mcp.page.locator('iframe')).not.toBeAttached();
72
- });
73
-
74
- test('should have themed empty state colors in light mode', async ({ mcp }) => {
75
- await mcp.openTool('show-map', { theme: 'light' });
76
-
77
- const emptyState = mcp.page.locator('text=Press Run to call the tool');
78
- await expect(emptyState).toBeVisible();
79
-
80
- const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
81
- const [r, g, b] = color.match(/\d+/g)!.map(Number);
82
- expect(r + g + b).toBeLessThan(600);
83
- });
84
-
85
- test('should have themed empty state colors in dark mode', async ({ mcp }) => {
86
- await mcp.openTool('show-map', { theme: 'dark' });
87
-
88
- const emptyState = mcp.page.locator('text=Press Run to call the tool');
89
- await expect(emptyState).toBeVisible();
90
-
91
- const color = await emptyState.evaluate((el) => window.getComputedStyle(el).color);
92
- const [r, g, b] = color.match(/\d+/g)!.map(Number);
93
- expect(r + g + b).toBeGreaterThan(200);
94
- });
95
-
96
- test('should activate prod resources mode without errors', async ({ mcp }) => {
97
- await mcp.callTool('show-map', {}, { theme: 'dark', prodResources: true });
98
- const root = mcp.page.locator('#root');
66
+ test('should activate prod resources mode without errors', async ({ inspector }) => {
67
+ await inspector.renderTool('show-map', undefined, { theme: 'dark', prodResources: true });
68
+ const root = inspector.page.locator('#root');
99
69
  await expect(root).not.toBeEmpty();
100
70
  });
101
71
 
102
- test('should render map in dark mode', async ({ mcp }) => {
103
- const result = await mcp.callTool('show-map', {}, { theme: 'dark' });
72
+ test('should render map in dark mode', async ({ inspector }) => {
73
+ const result = await inspector.renderTool('show-map', undefined, { theme: 'dark' });
104
74
  const app = result.app();
105
75
  await expect(app.locator('.antialiased.w-full.overflow-hidden').first()).toBeVisible({
106
76
  timeout: 10000,
107
77
  });
108
78
  });
109
79
 
110
- test('should have appropriate border color in dark mode', async ({ mcp }) => {
111
- const result = await mcp.callTool('show-map', {}, { theme: 'dark', displayMode: 'inline' });
80
+ test('should have appropriate border color in dark mode', async ({ inspector }) => {
81
+ const result = await inspector.renderTool('show-map', undefined, {
82
+ theme: 'dark',
83
+ displayMode: 'inline',
84
+ });
112
85
  const app = result.app();
113
86
 
114
87
  const innerContainer = app.locator('.border.rounded-2xl').first();
@@ -120,13 +93,13 @@ test('should have appropriate border color in dark mode', async ({ mcp }) => {
120
93
  expect(styles.borderColor).toBeTruthy();
121
94
  });
122
95
 
123
- test('should load without console errors in dark mode', async ({ mcp }) => {
96
+ test('should load without console errors in dark mode', async ({ inspector }) => {
124
97
  const errors: string[] = [];
125
- mcp.page.on('console', (msg) => {
98
+ inspector.page.on('console', (msg) => {
126
99
  if (msg.type() === 'error') errors.push(msg.text());
127
100
  });
128
101
 
129
- const result = await mcp.callTool('show-map', {}, { theme: 'dark' });
102
+ const result = await inspector.renderTool('show-map', undefined, { theme: 'dark' });
130
103
  const app = result.app();
131
104
  await expect(app.locator('.antialiased.w-full.overflow-hidden').first()).toBeVisible({
132
105
  timeout: 10000,
@@ -142,8 +115,10 @@ test('should load without console errors in dark mode', async ({ mcp }) => {
142
115
  expect(unexpectedErrors).toHaveLength(0);
143
116
  });
144
117
 
145
- test('should not have rounded border in fullscreen mode', async ({ mcp }) => {
146
- const result = await mcp.callTool('show-map', {}, { displayMode: 'fullscreen' });
118
+ test('should not have rounded border in fullscreen mode', async ({ inspector }) => {
119
+ const result = await inspector.renderTool('show-map', undefined, {
120
+ displayMode: 'fullscreen',
121
+ });
147
122
  const app = result.app();
148
123
 
149
124
  const innerContainer = app.locator('.rounded-none.border-0').first();
@@ -155,8 +130,10 @@ test('should not have rounded border in fullscreen mode', async ({ mcp }) => {
155
130
  expect(styles.borderRadius).toBe('0px');
156
131
  });
157
132
 
158
- test('should not show fullscreen button in fullscreen mode', async ({ mcp }) => {
159
- const result = await mcp.callTool('show-map', {}, { displayMode: 'fullscreen' });
133
+ test('should not show fullscreen button in fullscreen mode', async ({ inspector }) => {
134
+ const result = await inspector.renderTool('show-map', undefined, {
135
+ displayMode: 'fullscreen',
136
+ });
160
137
  const app = result.app();
161
138
 
162
139
  await expect(app.locator('.antialiased.w-full.overflow-hidden').first()).toBeVisible({
@@ -165,10 +142,12 @@ test('should not show fullscreen button in fullscreen mode', async ({ mcp }) =>
165
142
  await expect(app.locator('button[aria-label="Enter fullscreen"]')).not.toBeVisible();
166
143
  });
167
144
 
168
- test('should show suggestion chips in fullscreen on desktop', async ({ mcp }) => {
169
- await mcp.page.setViewportSize({ width: 1024, height: 768 });
145
+ test('should show suggestion chips in fullscreen on desktop', async ({ inspector }) => {
146
+ await inspector.page.setViewportSize({ width: 1024, height: 768 });
170
147
 
171
- const result = await mcp.callTool('show-map', {}, { displayMode: 'fullscreen' });
148
+ const result = await inspector.renderTool('show-map', undefined, {
149
+ displayMode: 'fullscreen',
150
+ });
172
151
  const app = result.app();
173
152
 
174
153
  await expect(app.locator('.antialiased.w-full.overflow-hidden').first()).toBeVisible({