sunpeak 0.20.51 → 0.20.56

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 (67) hide show
  1. package/bin/commands/inspect.mjs +122 -17
  2. package/bin/lib/sandbox-server.mjs +34 -5
  3. package/bin/lib/test/base-config.mjs +8 -1
  4. package/dist/chatgpt/index.cjs +1 -1
  5. package/dist/chatgpt/index.js +1 -1
  6. package/dist/claude/index.cjs +1 -1
  7. package/dist/claude/index.js +1 -1
  8. package/dist/embed.css +2 -2
  9. package/dist/host/chatgpt/index.cjs +1 -1
  10. package/dist/host/chatgpt/index.js +1 -1
  11. package/dist/index.cjs +3 -3
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.js +3 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/inspector/index.cjs +1 -1
  16. package/dist/inspector/index.js +1 -1
  17. package/dist/{inspector-DQyl36w3.js → inspector-BYuRWH6c.js} +36 -7
  18. package/dist/inspector-BYuRWH6c.js.map +1 -0
  19. package/dist/{inspector-WPF8mKwk.cjs → inspector-CoBJOqh4.cjs} +36 -7
  20. package/dist/inspector-CoBJOqh4.cjs.map +1 -0
  21. package/dist/mcp/index.cjs +1 -1
  22. package/dist/mcp/index.cjs.map +1 -1
  23. package/dist/mcp/index.js +1 -1
  24. package/dist/mcp/index.js.map +1 -1
  25. package/dist/sandbox-proxy.html +34 -5
  26. package/dist/style.css +27 -27
  27. package/dist/{use-app-DzgUHmdH.cjs → use-app-DrKg-OJp.cjs} +2 -2
  28. package/dist/{use-app-DzgUHmdH.cjs.map → use-app-DrKg-OJp.cjs.map} +1 -1
  29. package/dist/{use-app-j3as_y6c.js → use-app-nZXXvUxc.js} +2 -2
  30. package/dist/{use-app-j3as_y6c.js.map → use-app-nZXXvUxc.js.map} +1 -1
  31. package/package.json +18 -18
  32. package/template/dist/albums/albums.html +1 -1
  33. package/template/dist/albums/albums.json +1 -1
  34. package/template/dist/carousel/carousel.html +1 -1
  35. package/template/dist/carousel/carousel.json +1 -1
  36. package/template/dist/map/map.html +536 -492
  37. package/template/dist/map/map.json +1 -1
  38. package/template/dist/review/review.html +1 -1
  39. package/template/dist/review/review.json +1 -1
  40. package/template/node_modules/.bin/vite +2 -2
  41. package/template/node_modules/.bin/vitest +2 -2
  42. package/template/node_modules/.vite/deps/_metadata.json +4 -4
  43. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js +1 -1
  44. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps.js.map +1 -1
  45. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js +1 -1
  46. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_app-bridge.js.map +1 -1
  47. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js +1 -1
  48. package/template/node_modules/.vite-mcp/deps/@modelcontextprotocol_ext-apps_react.js.map +1 -1
  49. package/template/node_modules/.vite-mcp/deps/_metadata.json +25 -25
  50. package/template/node_modules/.vite-mcp/deps/mapbox-gl.js +32928 -31943
  51. package/template/node_modules/.vite-mcp/deps/mapbox-gl.js.map +1 -1
  52. package/template/node_modules/.vite-mcp/deps/vitest.js +21 -21
  53. package/template/node_modules/.vite-mcp/deps/vitest.js.map +1 -1
  54. package/template/package.json +7 -7
  55. package/template/tests/e2e/albums.spec.ts +0 -26
  56. package/template/tests/e2e/carousel.spec.ts +7 -63
  57. package/template/tests/e2e/map.spec.ts +0 -28
  58. package/template/tests/e2e/review.spec.ts +8 -45
  59. package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-chatgpt-linux.png +0 -0
  60. package/template/tests/e2e/visual.spec.ts-snapshots/albums-dark-claude-linux.png +0 -0
  61. package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-chatgpt-linux.png +0 -0
  62. package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-darwin.png +0 -0
  63. package/template/tests/e2e/visual.spec.ts-snapshots/albums-fullscreen-claude-linux.png +0 -0
  64. package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-chatgpt-linux.png +0 -0
  65. package/template/tests/e2e/visual.spec.ts-snapshots/albums-light-claude-linux.png +0 -0
  66. package/dist/inspector-DQyl36w3.js.map +0 -1
  67. package/dist/inspector-WPF8mKwk.cjs.map +0 -1
@@ -18,27 +18,27 @@
18
18
  "clsx": "^2.1.1",
19
19
  "embla-carousel-react": "^8.6.0",
20
20
  "embla-carousel-wheel-gestures": "^8.1.0",
21
- "mapbox-gl": "^3.24.0",
21
+ "mapbox-gl": "^3.24.1",
22
22
  "sunpeak": "workspace:*",
23
23
  "tailwind-merge": "^3.6.0",
24
24
  "zod": "^4.4.3"
25
25
  },
26
26
  "devDependencies": {
27
- "@playwright/test": "^1.60.0",
28
- "@tailwindcss/vite": "^4.3.0",
27
+ "@playwright/test": "1.60.0",
28
+ "@tailwindcss/vite": "^4.3.1",
29
29
  "@testing-library/jest-dom": "^6.9.1",
30
30
  "@testing-library/react": "^16.3.2",
31
31
  "@testing-library/user-event": "^14.6.1",
32
- "@types/node": "^25.9.2",
32
+ "@types/node": "^26.0.0",
33
33
  "@types/react": "^19.2.17",
34
34
  "@types/react-dom": "^19.2.3",
35
35
  "@vitejs/plugin-react": "^6.0.2",
36
- "happy-dom": "^20.10.1",
36
+ "happy-dom": "^20.10.6",
37
37
  "react": "^19.2.7",
38
38
  "react-dom": "^19.2.7",
39
- "tailwindcss": "^4.3.0",
39
+ "tailwindcss": "^4.3.1",
40
40
  "typescript": "^6.0.3",
41
41
  "vite": "8.0.16",
42
- "vitest": "^4.1.8"
42
+ "vitest": "^4.1.9"
43
43
  }
44
44
  }
@@ -6,13 +6,6 @@ test('should render album cards with correct styles', async ({ inspector }) => {
6
6
 
7
7
  const albumCard = app.locator('button:has-text("Summer Slice")');
8
8
  await expect(albumCard).toBeVisible();
9
-
10
- const styles = await albumCard.evaluate((el) => {
11
- const computed = window.getComputedStyle(el);
12
- return { cursor: computed.cursor, borderRadius: computed.borderRadius };
13
- });
14
- expect(styles.cursor).toBe('pointer');
15
- expect(styles.borderRadius).toBe('12px');
16
9
  });
17
10
 
18
11
  test('should have album image with correct aspect ratio', async ({ inspector }) => {
@@ -21,13 +14,6 @@ test('should have album image with correct aspect ratio', async ({ inspector })
21
14
 
22
15
  const imageContainer = app.locator('button:has-text("Summer Slice") .aspect-\\[4\\/3\\]');
23
16
  await expect(imageContainer).toBeVisible();
24
-
25
- const styles = await imageContainer.evaluate((el) => {
26
- const computed = window.getComputedStyle(el);
27
- return { borderRadius: computed.borderRadius, overflow: computed.overflow };
28
- });
29
- expect(styles.borderRadius).toBe('12px');
30
- expect(styles.overflow).toBe('hidden');
31
17
  });
32
18
 
33
19
  test('should render album cards in dark mode', async ({ inspector }) => {
@@ -36,11 +22,6 @@ test('should render album cards in dark mode', async ({ inspector }) => {
36
22
 
37
23
  const albumTitle = app.locator('button:has-text("Summer Slice") div').first();
38
24
  await expect(albumTitle).toBeVisible();
39
-
40
- const titleStyles = await albumTitle.evaluate((el) => ({
41
- color: window.getComputedStyle(el).color,
42
- }));
43
- expect(titleStyles.color).toBeTruthy();
44
25
  });
45
26
 
46
27
  test('should activate prod resources mode without errors', async ({ inspector }) => {
@@ -57,13 +38,6 @@ test('should render correctly in fullscreen', async ({ inspector }) => {
57
38
 
58
39
  const albumCard = app.locator('button:has-text("Summer Slice")');
59
40
  await expect(albumCard).toBeVisible();
60
-
61
- const styles = await albumCard.evaluate((el) => ({
62
- cursor: window.getComputedStyle(el).cursor,
63
- borderRadius: window.getComputedStyle(el).borderRadius,
64
- }));
65
- expect(styles.cursor).toBe('pointer');
66
- expect(styles.borderRadius).toBe('12px');
67
41
  });
68
42
 
69
43
  test('should render content in fullscreen mode', async ({ inspector }) => {
@@ -6,13 +6,7 @@ test('should render carousel cards with correct styles', async ({ inspector }) =
6
6
 
7
7
  const card = app.locator('.rounded-2xl').first();
8
8
  await expect(card).toBeVisible();
9
-
10
- const styles = await card.evaluate((el) => {
11
- const computed = window.getComputedStyle(el);
12
- return { borderRadius: computed.borderRadius, cursor: computed.cursor };
13
- });
14
- expect(styles.borderRadius).toBe('16px');
15
- expect(styles.cursor).toBe('pointer');
9
+ await expect(card).toContainText('Lady Bird Lake');
16
10
  });
17
11
 
18
12
  test('should have card with border styling', async ({ inspector }) => {
@@ -21,13 +15,6 @@ test('should have card with border styling', async ({ inspector }) => {
21
15
 
22
16
  const card = app.locator('.rounded-2xl.border').first();
23
17
  await expect(card).toBeVisible();
24
-
25
- const styles = await card.evaluate((el) => {
26
- const computed = window.getComputedStyle(el);
27
- return { borderWidth: computed.borderWidth, borderStyle: computed.borderStyle };
28
- });
29
- expect(styles.borderWidth).toBe('1px');
30
- expect(styles.borderStyle).toBe('solid');
31
18
  });
32
19
 
33
20
  test('should have interactive buttons', async ({ inspector }) => {
@@ -35,12 +22,7 @@ test('should have interactive buttons', async ({ inspector }) => {
35
22
  const app = result.app();
36
23
 
37
24
  const visitButton = app.locator('button:has-text("Visit")').first();
38
- await expect(visitButton).toBeAttached();
39
-
40
- const styles = await visitButton.evaluate((el) => ({
41
- cursor: window.getComputedStyle(el).cursor,
42
- }));
43
- expect(styles.cursor).toBe('pointer');
25
+ await expect(visitButton).toBeVisible();
44
26
  });
45
27
 
46
28
  test('should activate prod resources mode without errors', async ({ inspector }) => {
@@ -50,10 +32,10 @@ test('should activate prod resources mode without errors', async ({ inspector })
50
32
  });
51
33
 
52
34
  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');
56
- await expect(root).not.toBeEmpty();
35
+ const result = await inspector.renderTool('show-carousel', undefined, {
36
+ displayMode: 'fullscreen',
37
+ });
38
+ await expect(result.app().locator('h2:has-text("Lady Bird Lake")')).toBeVisible();
57
39
  });
58
40
 
59
41
  test('should show detail view with place info in fullscreen', async ({ inspector }) => {
@@ -111,11 +93,7 @@ test('should center the hero image without stretching', async ({ inspector }) =>
111
93
  await card.click();
112
94
 
113
95
  await expect(app.locator('h1:has-text("Lady Bird Lake")')).toBeVisible({ timeout: 5000 });
114
- const imageContainer = app.locator('img').first().locator('..');
115
- const styles = await imageContainer.evaluate((el) => ({
116
- justifyContent: window.getComputedStyle(el).justifyContent,
117
- }));
118
- expect(styles.justifyContent).toBe('center');
96
+ await expect(app.locator('img[alt="Lady Bird Lake"]')).toBeVisible();
119
97
  });
120
98
 
121
99
  test('should render carousel in dark mode with correct styles', async ({ inspector }) => {
@@ -124,13 +102,6 @@ test('should render carousel in dark mode with correct styles', async ({ inspect
124
102
 
125
103
  const card = app.locator('.rounded-2xl').first();
126
104
  await expect(card).toBeVisible();
127
-
128
- const styles = await card.evaluate((el) => ({
129
- borderRadius: window.getComputedStyle(el).borderRadius,
130
- cursor: window.getComputedStyle(el).cursor,
131
- }));
132
- expect(styles.borderRadius).toBe('16px');
133
- expect(styles.cursor).toBe('pointer');
134
105
  });
135
106
 
136
107
  test('should have appropriate dark mode styling', async ({ inspector }) => {
@@ -139,31 +110,4 @@ test('should have appropriate dark mode styling', async ({ inspector }) => {
139
110
 
140
111
  const card = app.locator('.rounded-2xl.border').first();
141
112
  await expect(card).toBeVisible();
142
-
143
- const styles = await card.evaluate((el) => ({
144
- borderWidth: window.getComputedStyle(el).borderWidth,
145
- borderStyle: window.getComputedStyle(el).borderStyle,
146
- }));
147
- expect(styles.borderWidth).toBe('1px');
148
- expect(styles.borderStyle).toBe('solid');
149
- });
150
-
151
- test('should load without console errors in dark mode', async ({ inspector }) => {
152
- const errors: string[] = [];
153
- inspector.page.on('console', (msg) => {
154
- if (msg.type() === 'error') errors.push(msg.text());
155
- });
156
-
157
- const result = await inspector.renderTool('show-carousel', undefined, { theme: 'dark' });
158
- const app = result.app();
159
- await expect(app.locator('.rounded-2xl').first()).toBeVisible();
160
-
161
- const unexpectedErrors = errors.filter(
162
- (e) =>
163
- !e.includes('[IframeResource]') &&
164
- !e.includes('mcp') &&
165
- !e.includes('PostMessage') &&
166
- !e.includes('connect')
167
- );
168
- expect(unexpectedErrors).toHaveLength(0);
169
113
  });
@@ -6,11 +6,6 @@ test('should render map container with correct styles', async ({ inspector }) =>
6
6
 
7
7
  const mapContainer = app.locator('.antialiased.w-full.overflow-hidden').first();
8
8
  await expect(mapContainer).toBeVisible({ timeout: 10000 });
9
-
10
- const styles = await mapContainer.evaluate((el) => ({
11
- overflow: window.getComputedStyle(el).overflow,
12
- }));
13
- expect(styles.overflow).toBe('hidden');
14
9
  });
15
10
 
16
11
  test('should have rounded border in inline mode', async ({ inspector }) => {
@@ -19,11 +14,6 @@ test('should have rounded border in inline mode', async ({ inspector }) => {
19
14
 
20
15
  const innerContainer = app.locator('.border.rounded-2xl').first();
21
16
  await expect(innerContainer).toBeVisible({ timeout: 10000 });
22
-
23
- const styles = await innerContainer.evaluate((el) => ({
24
- borderRadius: window.getComputedStyle(el).borderRadius,
25
- }));
26
- expect(parseInt(styles.borderRadius)).toBeGreaterThanOrEqual(16);
27
17
  });
28
18
 
29
19
  test('should have fullscreen expand button in inline mode', async ({ inspector }) => {
@@ -32,13 +22,6 @@ test('should have fullscreen expand button in inline mode', async ({ inspector }
32
22
 
33
23
  const expandButton = app.locator('button[aria-label="Enter fullscreen"]');
34
24
  await expect(expandButton).toBeVisible({ timeout: 10000 });
35
-
36
- const styles = await expandButton.evaluate((el) => ({
37
- cursor: window.getComputedStyle(el).cursor,
38
- position: window.getComputedStyle(el).position,
39
- }));
40
- expect(styles.cursor).toBe('pointer');
41
- expect(styles.position).toBe('absolute');
42
25
  });
43
26
 
44
27
  test('should load without console errors in light mode', async ({ inspector }) => {
@@ -86,11 +69,6 @@ test('should have appropriate border color in dark mode', async ({ inspector })
86
69
 
87
70
  const innerContainer = app.locator('.border.rounded-2xl').first();
88
71
  await expect(innerContainer).toBeVisible({ timeout: 10000 });
89
-
90
- const styles = await innerContainer.evaluate((el) => ({
91
- borderColor: window.getComputedStyle(el).borderColor,
92
- }));
93
- expect(styles.borderColor).toBeTruthy();
94
72
  });
95
73
 
96
74
  test('should load without console errors in dark mode', async ({ inspector }) => {
@@ -123,11 +101,6 @@ test('should not have rounded border in fullscreen mode', async ({ inspector })
123
101
 
124
102
  const innerContainer = app.locator('.rounded-none.border-0').first();
125
103
  await expect(innerContainer).toBeVisible({ timeout: 10000 });
126
-
127
- const styles = await innerContainer.evaluate((el) => ({
128
- borderRadius: window.getComputedStyle(el).borderRadius,
129
- }));
130
- expect(styles.borderRadius).toBe('0px');
131
104
  });
132
105
 
133
106
  test('should not show fullscreen button in fullscreen mode', async ({ inspector }) => {
@@ -153,5 +126,4 @@ test('should show suggestion chips in fullscreen on desktop', async ({ inspector
153
126
  await expect(app.locator('.antialiased.w-full.overflow-hidden').first()).toBeVisible({
154
127
  timeout: 10000,
155
128
  });
156
- await expect(app.locator('button:has-text("Open now")')).toBeAttached({ timeout: 5000 });
157
129
  });
@@ -6,11 +6,6 @@ test('should render review title with correct styles', async ({ inspector }) =>
6
6
 
7
7
  const title = app.locator('h1:has-text("Refactor Authentication Module")');
8
8
  await expect(title).toBeVisible();
9
-
10
- const styles = await title.evaluate((el) => ({
11
- fontWeight: window.getComputedStyle(el).fontWeight,
12
- }));
13
- expect(parseInt(styles.fontWeight)).toBeGreaterThanOrEqual(600);
14
9
  });
15
10
 
16
11
  test('should render change items with type-specific styling', async ({ inspector }) => {
@@ -19,12 +14,6 @@ test('should render change items with type-specific styling', async ({ inspector
19
14
 
20
15
  const changeItem = app.locator('li').first();
21
16
  await expect(changeItem).toBeVisible();
22
-
23
- const styles = await changeItem.evaluate((el) => ({
24
- backgroundColor: window.getComputedStyle(el).backgroundColor,
25
- }));
26
- expect(styles.backgroundColor).toBeTruthy();
27
- expect(styles.backgroundColor).not.toBe('rgba(0, 0, 0, 0)');
28
17
  });
29
18
 
30
19
  test('should have interactive apply and cancel buttons', async ({ inspector }) => {
@@ -33,11 +22,9 @@ test('should have interactive apply and cancel buttons', async ({ inspector }) =
33
22
 
34
23
  const applyButton = app.locator('button:has-text("Apply Changes")');
35
24
  await expect(applyButton).toBeVisible();
36
- expect(await applyButton.evaluate((el) => window.getComputedStyle(el).cursor)).toBe('pointer');
37
25
 
38
26
  const cancelButton = app.locator('button:has-text("Cancel")');
39
27
  await expect(cancelButton).toBeVisible();
40
- expect(await cancelButton.evaluate((el) => window.getComputedStyle(el).cursor)).toBe('pointer');
41
28
  });
42
29
 
43
30
  test('should have expand fullscreen button in inline mode', async ({ inspector }) => {
@@ -46,7 +33,6 @@ test('should have expand fullscreen button in inline mode', async ({ inspector }
46
33
 
47
34
  const expandButton = app.locator('button[aria-label="Enter fullscreen"]');
48
35
  await expect(expandButton).toBeVisible();
49
- expect(await expandButton.evaluate((el) => window.getComputedStyle(el).cursor)).toBe('pointer');
50
36
  });
51
37
 
52
38
  test('should activate prod resources mode without errors', async ({ inspector }) => {
@@ -61,25 +47,6 @@ test('should render review title in dark mode', async ({ inspector }) => {
61
47
  await expect(app.locator('h1:has-text("Refactor Authentication Module")')).toBeVisible();
62
48
  });
63
49
 
64
- test('should have appropriate text colors in dark mode', async ({ inspector }) => {
65
- const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
66
- const app = result.app();
67
-
68
- const title = app.locator('h1').first();
69
- await expect(title).toBeVisible();
70
-
71
- const styles = await title.evaluate((el) => ({
72
- color: window.getComputedStyle(el).color,
73
- }));
74
- expect(styles.color).toBeTruthy();
75
- });
76
-
77
- test('should render change items in dark mode', async ({ inspector }) => {
78
- const result = await inspector.renderTool('review-diff', undefined, { theme: 'dark' });
79
- const app = result.app();
80
- await expect(app.locator('li').first()).toBeVisible();
81
- });
82
-
83
50
  test('should load without console errors in dark mode', async ({ inspector }) => {
84
51
  const errors: string[] = [];
85
52
  inspector.page.on('console', (msg) => {
@@ -122,15 +89,13 @@ test('should render content in fullscreen mode', async ({ inspector }) => {
122
89
  });
123
90
 
124
91
  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();
92
+ const result = await inspector.renderTool('review-post');
93
+ await expect(result.app().locator('h1').first()).toBeVisible();
128
94
  });
129
95
 
130
96
  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();
97
+ const result = await inspector.renderTool('review-post', undefined, { theme: 'dark' });
98
+ await expect(result.app().locator('h1').first()).toBeVisible();
134
99
  });
135
100
 
136
101
  test('should show server success message when confirming post', async ({ inspector }) => {
@@ -157,15 +122,13 @@ test('should show server cancel message when rejecting post', async ({ inspector
157
122
  });
158
123
 
159
124
  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();
125
+ const result = await inspector.renderTool('review-purchase');
126
+ await expect(result.app().locator('h1').first()).toBeVisible();
163
127
  });
164
128
 
165
129
  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();
130
+ const result = await inspector.renderTool('review-purchase', undefined, { theme: 'dark' });
131
+ await expect(result.app().locator('h1').first()).toBeVisible();
169
132
  });
170
133
 
171
134
  test('should show loading then result when placing order', async ({ inspector }) => {