sunpeak 0.14.3 → 0.15.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 +34 -30
- package/bin/commands/build.mjs +2 -1
- package/bin/commands/dev.mjs +72 -2
- package/dist/chatgpt/{conversation.d.ts → chatgpt-conversation.d.ts} +1 -1
- package/dist/chatgpt/chatgpt-host.d.ts +1 -0
- package/dist/chatgpt/globals.css +618 -6156
- package/dist/chatgpt/index.cjs +11 -8
- package/dist/chatgpt/index.cjs.map +1 -1
- package/dist/chatgpt/index.d.ts +10 -32
- package/dist/chatgpt/index.js +15 -12
- package/dist/chatgpt/index.js.map +1 -1
- package/dist/claude/claude-conversation.d.ts +23 -0
- package/dist/claude/claude-host.d.ts +1 -0
- package/dist/claude/index.cjs +5 -0
- package/dist/claude/index.cjs.map +1 -0
- package/dist/claude/index.d.ts +1 -0
- package/dist/claude/index.js +5 -0
- package/dist/claude/index.js.map +1 -0
- package/dist/{discovery-COZUnY6a.js → discovery-DzV3HLXs.js} +5 -5
- package/dist/{discovery-COZUnY6a.js.map → discovery-DzV3HLXs.js.map} +1 -1
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/use-app-tools.d.ts +44 -0
- package/dist/hooks/use-update-model-context.d.ts +29 -0
- package/dist/index-B0dxRJvS.cjs +42 -0
- package/dist/index-B0dxRJvS.cjs.map +1 -0
- package/dist/index-Ce_5ZIdJ.js +512 -0
- package/dist/index-Ce_5ZIdJ.js.map +1 -0
- package/dist/index-Cngntkp2.cjs +527 -0
- package/dist/index-Cngntkp2.cjs.map +1 -0
- package/dist/index-CutQgPzR.js +43 -0
- package/dist/index-CutQgPzR.js.map +1 -0
- package/dist/index.cjs +1705 -1647
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2732 -2675
- package/dist/index.js.map +1 -1
- package/dist/lib/default-style-variables.d.ts +2 -0
- package/dist/lib/discovery-cli.js +1 -1
- package/dist/mcp/index.cjs +86 -27
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.d.ts +3 -1
- package/dist/mcp/index.js +85 -26
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.d.ts +4 -3
- package/dist/mcp/types.d.ts +11 -0
- package/dist/platform/chatgpt/index.cjs +1 -1
- package/dist/platform/chatgpt/index.js +1 -1
- package/dist/platform/index.cjs +3 -0
- package/dist/platform/index.cjs.map +1 -1
- package/dist/platform/index.d.ts +3 -1
- package/dist/platform/index.js +3 -0
- package/dist/platform/index.js.map +1 -1
- package/dist/{protocol-BQCnIrc9.js → protocol-DFbsCx7E.js} +29 -29
- package/dist/{protocol-BQCnIrc9.js.map → protocol-DFbsCx7E.js.map} +1 -1
- package/dist/simulator/host-styles.d.ts +5 -0
- package/dist/simulator/hosts.d.ts +73 -0
- package/dist/{chatgpt → simulator}/iframe-resource.d.ts +27 -3
- package/dist/simulator/index.cjs +39 -0
- package/dist/simulator/index.cjs.map +1 -0
- package/dist/simulator/index.d.ts +18 -0
- package/dist/simulator/index.js +39 -0
- package/dist/simulator/index.js.map +1 -0
- package/dist/{chatgpt → simulator}/mcp-app-host.d.ts +8 -1
- package/dist/simulator/mock-openai-runtime.d.ts +20 -0
- package/dist/{chatgpt → simulator}/simulator-url.d.ts +8 -1
- package/dist/simulator/simulator.d.ts +12 -0
- package/dist/{chatgpt → simulator}/theme-provider.d.ts +3 -1
- package/dist/simulator/use-simulator-state.d.ts +91 -0
- package/dist/simulator-CxrtnguM.js +8764 -0
- package/dist/simulator-CxrtnguM.js.map +1 -0
- package/dist/simulator-DcfQBRXE.cjs +8779 -0
- package/dist/simulator-DcfQBRXE.cjs.map +1 -0
- package/dist/simulator-url-CuLqtnSS.js +48 -0
- package/dist/simulator-url-CuLqtnSS.js.map +1 -0
- package/dist/simulator-url-rgg_KYOg.cjs +47 -0
- package/dist/simulator-url-rgg_KYOg.cjs.map +1 -0
- package/dist/style.css +558 -6143
- package/dist/types/runtime.d.ts +1 -1
- package/dist/{use-app-D7kRAPSG.cjs → use-app-BnoSPiUT.cjs} +2 -1
- package/dist/{use-app-D7kRAPSG.cjs.map → use-app-BnoSPiUT.cjs.map} +1 -1
- package/dist/{use-app-Dvr4LKs2.js → use-app-D_TeaMFG.js} +4 -3
- package/dist/{use-app-Dvr4LKs2.js.map → use-app-D_TeaMFG.js.map} +1 -1
- package/package.json +18 -3
- package/template/.sunpeak/dev.tsx +4 -4
- package/template/.sunpeak/resource-loader.html +1 -1
- package/template/README.md +1 -1
- package/template/node_modules/.bin/nodemon +2 -2
- package/template/node_modules/.bin/playwright +2 -2
- package/template/node_modules/.bin/sunpeak +2 -2
- package/template/node_modules/.bin/tsc +2 -2
- package/template/node_modules/.bin/tsserver +2 -2
- package/template/node_modules/.bin/tsx +2 -2
- package/template/node_modules/.bin/vite +2 -2
- package/template/src/components/avatar.tsx +4 -1
- package/template/src/components/button.tsx +17 -20
- package/template/src/resources/albums/albums-resource.tsx +2 -3
- package/template/src/resources/albums/components/album-card.tsx +4 -2
- package/template/src/resources/albums/components/film-strip.test.tsx +2 -2
- package/template/src/resources/albums/components/film-strip.tsx +2 -2
- package/template/src/resources/albums/components/fullscreen-viewer.tsx +7 -5
- package/template/src/resources/carousel/carousel-resource.tsx +2 -3
- package/template/src/resources/carousel/components/card.test.tsx +3 -2
- package/template/src/resources/carousel/components/card.tsx +8 -4
- package/template/src/resources/map/components/map-view.tsx +1 -1
- package/template/src/resources/map/components/map.tsx +1 -1
- package/template/src/resources/map/components/place-card.tsx +8 -4
- package/template/src/resources/map/components/place-carousel.tsx +1 -1
- package/template/src/resources/map/components/place-inspector.tsx +15 -7
- package/template/src/resources/map/components/place-list.tsx +7 -4
- package/template/src/resources/map/map-resource.tsx +0 -2
- package/template/src/resources/review/review-resource.tsx +61 -27
- package/template/tests/e2e/albums.spec.ts +118 -102
- package/template/tests/e2e/carousel.spec.ts +103 -100
- package/template/tests/e2e/map.spec.ts +220 -181
- package/template/tests/e2e/review.spec.ts +224 -198
- package/dist/_commonjsHelpers-Bc2YnDe1.cjs +0 -8
- package/dist/_commonjsHelpers-Bc2YnDe1.cjs.map +0 -1
- package/dist/_commonjsHelpers-DWwsNxpa.js +0 -9
- package/dist/_commonjsHelpers-DWwsNxpa.js.map +0 -1
- package/dist/index-CJ3jfcjj.js +0 -15131
- package/dist/index-CJ3jfcjj.js.map +0 -1
- package/dist/index-Cdeg96So.cjs +0 -15147
- package/dist/index-Cdeg96So.cjs.map +0 -1
- /package/dist/{chatgpt → simulator}/simple-sidebar.d.ts +0 -0
- /package/dist/{chatgpt/chatgpt-simulator-types.d.ts → simulator/simulator-types.d.ts} +0 -0
|
@@ -17,9 +17,8 @@ export const resource: ResourceConfig = {
|
|
|
17
17
|
mimeType: 'text/html;profile=mcp-app',
|
|
18
18
|
_meta: {
|
|
19
19
|
ui: {
|
|
20
|
-
domain: 'https://sunpeak.ai',
|
|
21
20
|
csp: {
|
|
22
|
-
resourceDomains: ['https://cdn.sunpeak.ai'
|
|
21
|
+
resourceDomains: ['https://cdn.sunpeak.ai'],
|
|
23
22
|
},
|
|
24
23
|
},
|
|
25
24
|
},
|
|
@@ -150,16 +149,26 @@ function DetailsSection({ content }: { content: Detail[] }) {
|
|
|
150
149
|
<div
|
|
151
150
|
key={i}
|
|
152
151
|
className={`flex justify-between items-start gap-4 ${
|
|
153
|
-
detail.emphasis
|
|
152
|
+
detail.emphasis
|
|
153
|
+
? 'font-semibold pt-2 border-t border-[var(--color-border-tertiary)]'
|
|
154
|
+
: ''
|
|
154
155
|
}`}
|
|
155
156
|
>
|
|
156
157
|
<div className="flex-1 min-w-0">
|
|
157
|
-
<span
|
|
158
|
+
<span
|
|
159
|
+
className={
|
|
160
|
+
detail.emphasis
|
|
161
|
+
? 'text-[var(--color-text-primary)]'
|
|
162
|
+
: 'text-[var(--color-text-secondary)]'
|
|
163
|
+
}
|
|
164
|
+
>
|
|
158
165
|
{detail.label}
|
|
159
166
|
</span>
|
|
160
|
-
{detail.sublabel &&
|
|
167
|
+
{detail.sublabel && (
|
|
168
|
+
<p className="text-xs text-[var(--color-text-secondary)] mt-0.5">{detail.sublabel}</p>
|
|
169
|
+
)}
|
|
161
170
|
</div>
|
|
162
|
-
<span className="text-primary flex-shrink-0">{detail.value}</span>
|
|
171
|
+
<span className="text-[var(--color-text-primary)] flex-shrink-0">{detail.value}</span>
|
|
163
172
|
</div>
|
|
164
173
|
))}
|
|
165
174
|
</div>
|
|
@@ -170,7 +179,10 @@ function ItemsSection({ content }: { content: Item[] }) {
|
|
|
170
179
|
return (
|
|
171
180
|
<div className="space-y-3">
|
|
172
181
|
{content.map((item) => (
|
|
173
|
-
<div
|
|
182
|
+
<div
|
|
183
|
+
key={item.id}
|
|
184
|
+
className="flex items-center gap-3 p-2 rounded-lg bg-[var(--color-background-secondary)]"
|
|
185
|
+
>
|
|
174
186
|
{item.image && (
|
|
175
187
|
<img
|
|
176
188
|
src={item.image}
|
|
@@ -180,17 +192,23 @@ function ItemsSection({ content }: { content: Item[] }) {
|
|
|
180
192
|
)}
|
|
181
193
|
<div className="flex-1 min-w-0">
|
|
182
194
|
<div className="flex items-center gap-2">
|
|
183
|
-
<span className="text-sm font-medium text-primary truncate">
|
|
195
|
+
<span className="text-sm font-medium text-[var(--color-text-primary)] truncate">
|
|
196
|
+
{item.title}
|
|
197
|
+
</span>
|
|
184
198
|
{item.badge && (
|
|
185
|
-
<span className="px-1.5 py-0.5 text-xs rounded bg-primary text-
|
|
199
|
+
<span className="px-1.5 py-0.5 text-xs rounded bg-[var(--color-ring-primary)] text-white">
|
|
186
200
|
{item.badge}
|
|
187
201
|
</span>
|
|
188
202
|
)}
|
|
189
203
|
</div>
|
|
190
|
-
{item.subtitle &&
|
|
204
|
+
{item.subtitle && (
|
|
205
|
+
<p className="text-xs text-[var(--color-text-secondary)] truncate">{item.subtitle}</p>
|
|
206
|
+
)}
|
|
191
207
|
</div>
|
|
192
208
|
{item.value && (
|
|
193
|
-
<span className="text-sm font-medium text-primary flex-shrink-0">
|
|
209
|
+
<span className="text-sm font-medium text-[var(--color-text-primary)] flex-shrink-0">
|
|
210
|
+
{item.value}
|
|
211
|
+
</span>
|
|
194
212
|
)}
|
|
195
213
|
</div>
|
|
196
214
|
))}
|
|
@@ -206,7 +224,7 @@ function ChangesSection({ content }: { content: Change[] }) {
|
|
|
206
224
|
return (
|
|
207
225
|
<li
|
|
208
226
|
key={change.id}
|
|
209
|
-
className="rounded-lg border border-
|
|
227
|
+
className="rounded-lg border border-[var(--color-border-tertiary)] p-3"
|
|
210
228
|
style={{ backgroundColor: config.bg }}
|
|
211
229
|
>
|
|
212
230
|
<div className="flex items-start gap-3">
|
|
@@ -223,12 +241,16 @@ function ChangesSection({ content }: { content: Change[] }) {
|
|
|
223
241
|
</span>
|
|
224
242
|
<div className="flex-1 min-w-0">
|
|
225
243
|
{change.path && (
|
|
226
|
-
<code className="block text-xs text-secondary font-mono truncate mb-1">
|
|
244
|
+
<code className="block text-xs text-[var(--color-text-secondary)] font-mono truncate mb-1">
|
|
227
245
|
{change.path}
|
|
228
246
|
</code>
|
|
229
247
|
)}
|
|
230
248
|
<p className="text-sm text-[#000000]">{change.description}</p>
|
|
231
|
-
{change.details &&
|
|
249
|
+
{change.details && (
|
|
250
|
+
<p className="mt-1 text-xs text-[var(--color-text-secondary)]">
|
|
251
|
+
{change.details}
|
|
252
|
+
</p>
|
|
253
|
+
)}
|
|
232
254
|
</div>
|
|
233
255
|
</div>
|
|
234
256
|
</li>
|
|
@@ -240,24 +262,34 @@ function ChangesSection({ content }: { content: Change[] }) {
|
|
|
240
262
|
|
|
241
263
|
function PreviewSection({ content }: { content: string }) {
|
|
242
264
|
return (
|
|
243
|
-
<div className="p-4 rounded-lg bg-
|
|
244
|
-
<p className="text-sm text-primary whitespace-pre-wrap">{content}</p>
|
|
265
|
+
<div className="p-4 rounded-lg bg-[var(--color-background-secondary)] border border-[var(--color-border-tertiary)]">
|
|
266
|
+
<p className="text-sm text-[var(--color-text-primary)] whitespace-pre-wrap">{content}</p>
|
|
245
267
|
</div>
|
|
246
268
|
);
|
|
247
269
|
}
|
|
248
270
|
|
|
249
271
|
function SummarySection({ content }: { content: Detail[] }) {
|
|
250
272
|
return (
|
|
251
|
-
<div className="p-3 rounded-lg bg-
|
|
273
|
+
<div className="p-3 rounded-lg bg-[var(--color-background-secondary)] space-y-1">
|
|
252
274
|
{content.map((item, i) => (
|
|
253
275
|
<div
|
|
254
276
|
key={i}
|
|
255
277
|
className={`flex justify-between items-center ${
|
|
256
|
-
item.emphasis
|
|
278
|
+
item.emphasis
|
|
279
|
+
? 'font-semibold text-lg pt-2 border-t border-[var(--color-border-tertiary)] mt-2'
|
|
280
|
+
: 'text-sm'
|
|
257
281
|
}`}
|
|
258
282
|
>
|
|
259
|
-
<span
|
|
260
|
-
|
|
283
|
+
<span
|
|
284
|
+
className={
|
|
285
|
+
item.emphasis
|
|
286
|
+
? 'text-[var(--color-text-primary)]'
|
|
287
|
+
: 'text-[var(--color-text-secondary)]'
|
|
288
|
+
}
|
|
289
|
+
>
|
|
290
|
+
{item.label}
|
|
291
|
+
</span>
|
|
292
|
+
<span className="text-[var(--color-text-primary)]">{item.value}</span>
|
|
261
293
|
</div>
|
|
262
294
|
))}
|
|
263
295
|
</div>
|
|
@@ -285,7 +317,7 @@ function SectionRenderer({ section }: { section: Section }) {
|
|
|
285
317
|
return (
|
|
286
318
|
<div className="space-y-2">
|
|
287
319
|
{section.title && (
|
|
288
|
-
<h2 className="text-sm font-medium text-secondary uppercase tracking-wide">
|
|
320
|
+
<h2 className="text-sm font-medium text-[var(--color-text-secondary)] uppercase tracking-wide">
|
|
289
321
|
{section.title}
|
|
290
322
|
</h2>
|
|
291
323
|
)}
|
|
@@ -395,11 +427,13 @@ export function ReviewResource() {
|
|
|
395
427
|
return (
|
|
396
428
|
<SafeArea className="flex flex-col">
|
|
397
429
|
{/* Header */}
|
|
398
|
-
<div className="px-4 pt-4 pb-3 border-b border-
|
|
430
|
+
<div className="px-4 pt-4 pb-3 border-b border-[var(--color-border-tertiary)]">
|
|
399
431
|
<div className="flex items-start justify-between gap-2">
|
|
400
432
|
<div className="flex-1 min-w-0">
|
|
401
|
-
<h1 className="text-xl font-semibold text-primary">{data.title}</h1>
|
|
402
|
-
{data.description &&
|
|
433
|
+
<h1 className="text-xl font-semibold text-[var(--color-text-primary)]">{data.title}</h1>
|
|
434
|
+
{data.description && (
|
|
435
|
+
<p className="mt-1 text-sm text-[var(--color-text-secondary)]">{data.description}</p>
|
|
436
|
+
)}
|
|
403
437
|
</div>
|
|
404
438
|
{!isFullscreen && (
|
|
405
439
|
<Button
|
|
@@ -431,7 +465,7 @@ export function ReviewResource() {
|
|
|
431
465
|
{sections.length === 0 ? (
|
|
432
466
|
// Note: Apps cannot distinguish between "still loading" and "empty response".
|
|
433
467
|
// We show a loading state as the optimistic assumption.
|
|
434
|
-
<div className="flex items-center justify-center gap-2 py-8 text-secondary">
|
|
468
|
+
<div className="flex items-center justify-center gap-2 py-8 text-[var(--color-text-secondary)]">
|
|
435
469
|
<div className="w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin" />
|
|
436
470
|
<span>Loading...</span>
|
|
437
471
|
</div>
|
|
@@ -441,7 +475,7 @@ export function ReviewResource() {
|
|
|
441
475
|
</div>
|
|
442
476
|
|
|
443
477
|
{/* Footer with Actions */}
|
|
444
|
-
<div className="px-4 py-3 border-t border-
|
|
478
|
+
<div className="px-4 py-3 border-t border-[var(--color-border-tertiary)] bg-[var(--color-background-primary)]">
|
|
445
479
|
{decision === null ? (
|
|
446
480
|
<div className="flex gap-3">
|
|
447
481
|
<Button
|
|
@@ -475,7 +509,7 @@ export function ReviewResource() {
|
|
|
475
509
|
</span>
|
|
476
510
|
</div>
|
|
477
511
|
{state.decidedAt && (
|
|
478
|
-
<span className="text-xs text-secondary">
|
|
512
|
+
<span className="text-xs text-[var(--color-text-secondary)]">
|
|
479
513
|
{new Date(state.decidedAt).toLocaleString()}
|
|
480
514
|
</span>
|
|
481
515
|
)}
|
|
@@ -1,125 +1,141 @@
|
|
|
1
1
|
import { test, expect } from '@playwright/test';
|
|
2
2
|
import { createSimulatorUrl } from 'sunpeak/chatgpt';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
4
|
+
const hosts = ['chatgpt', 'claude'] as const;
|
|
5
|
+
|
|
6
|
+
for (const host of hosts) {
|
|
7
|
+
test.describe(`Albums Resource [${host}]`, () => {
|
|
8
|
+
test.describe('Light Mode', () => {
|
|
9
|
+
test('should render album cards with correct styles', async ({ page }) => {
|
|
10
|
+
await page.goto(createSimulatorUrl({ simulation: 'albums-show', theme: 'light', host }));
|
|
11
|
+
|
|
12
|
+
const iframe = page.frameLocator('iframe');
|
|
13
|
+
const albumCard = iframe.locator('button:has-text("Summer Slice")');
|
|
14
|
+
await expect(albumCard).toBeVisible();
|
|
15
|
+
|
|
16
|
+
// Verify album card unique styles
|
|
17
|
+
const styles = await albumCard.evaluate((el) => {
|
|
18
|
+
const computed = window.getComputedStyle(el);
|
|
19
|
+
return {
|
|
20
|
+
cursor: computed.cursor,
|
|
21
|
+
borderRadius: computed.borderRadius,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
expect(styles.cursor).toBe('pointer');
|
|
26
|
+
expect(styles.borderRadius).toBe('12px'); // rounded-xl
|
|
20
27
|
});
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
test('should have album image with correct aspect ratio', async ({ page }) => {
|
|
30
|
+
await page.goto(createSimulatorUrl({ simulation: 'albums-show', theme: 'light', host }));
|
|
31
|
+
|
|
32
|
+
const iframe = page.frameLocator('iframe');
|
|
33
|
+
const albumImage = iframe.locator('button:has-text("Summer Slice") img').first();
|
|
34
|
+
await expect(albumImage).toBeVisible();
|
|
35
|
+
|
|
36
|
+
// Verify aspect-[4/3] container
|
|
37
|
+
const imageContainer = iframe.locator(
|
|
38
|
+
'button:has-text("Summer Slice") .aspect-\\[4\\/3\\]'
|
|
39
|
+
);
|
|
40
|
+
await expect(imageContainer).toBeVisible();
|
|
41
|
+
|
|
42
|
+
const containerStyles = await imageContainer.evaluate((el) => {
|
|
43
|
+
const computed = window.getComputedStyle(el);
|
|
44
|
+
return {
|
|
45
|
+
borderRadius: computed.borderRadius,
|
|
46
|
+
overflow: computed.overflow,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(containerStyles.borderRadius).toBe('12px'); // rounded-xl
|
|
51
|
+
expect(containerStyles.overflow).toBe('hidden');
|
|
52
|
+
});
|
|
24
53
|
});
|
|
25
54
|
|
|
26
|
-
test('
|
|
27
|
-
|
|
55
|
+
test.describe('Dark Mode', () => {
|
|
56
|
+
test('should render album cards with correct styles', async ({ page }) => {
|
|
57
|
+
await page.goto(createSimulatorUrl({ simulation: 'albums-show', theme: 'dark', host }));
|
|
28
58
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
59
|
+
const iframe = page.frameLocator('iframe');
|
|
60
|
+
const albumCard = iframe.locator('button:has-text("Summer Slice")');
|
|
61
|
+
await expect(albumCard).toBeVisible();
|
|
32
62
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
63
|
+
const styles = await albumCard.evaluate((el) => {
|
|
64
|
+
const computed = window.getComputedStyle(el);
|
|
65
|
+
return {
|
|
66
|
+
cursor: computed.cursor,
|
|
67
|
+
borderRadius: computed.borderRadius,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
36
70
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
borderRadius: computed.borderRadius,
|
|
41
|
-
overflow: computed.overflow,
|
|
42
|
-
};
|
|
71
|
+
expect(styles.cursor).toBe('pointer');
|
|
72
|
+
expect(styles.borderRadius).toBe('12px'); // rounded-xl
|
|
43
73
|
});
|
|
44
74
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
48
|
-
});
|
|
75
|
+
test('should have text with appropriate contrast', async ({ page }) => {
|
|
76
|
+
await page.goto(createSimulatorUrl({ simulation: 'albums-show', theme: 'dark', host }));
|
|
49
77
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
const iframe = page.frameLocator('iframe');
|
|
79
|
+
const albumTitle = iframe.locator('button:has-text("Summer Slice") div').first();
|
|
80
|
+
await expect(albumTitle).toBeVisible();
|
|
53
81
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
82
|
+
// In dark mode, text should be light colored for contrast
|
|
83
|
+
const titleStyles = await albumTitle.evaluate((el) => {
|
|
84
|
+
const computed = window.getComputedStyle(el);
|
|
85
|
+
return {
|
|
86
|
+
color: computed.color,
|
|
87
|
+
};
|
|
88
|
+
});
|
|
57
89
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
cursor: computed.cursor,
|
|
62
|
-
borderRadius: computed.borderRadius,
|
|
63
|
-
};
|
|
90
|
+
// Verify the text color exists (should be a light color in dark mode)
|
|
91
|
+
expect(titleStyles.color).toBeTruthy();
|
|
64
92
|
});
|
|
65
|
-
|
|
66
|
-
expect(styles.cursor).toBe('pointer');
|
|
67
|
-
expect(styles.borderRadius).toBe('12px'); // rounded-xl
|
|
68
93
|
});
|
|
69
94
|
|
|
70
|
-
test('
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
95
|
+
test.describe('Fullscreen Mode', () => {
|
|
96
|
+
test('should render correctly in fullscreen displayMode', async ({ page }) => {
|
|
97
|
+
await page.goto(
|
|
98
|
+
createSimulatorUrl({
|
|
99
|
+
simulation: 'albums-show',
|
|
100
|
+
theme: 'light',
|
|
101
|
+
displayMode: 'fullscreen',
|
|
102
|
+
host,
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Wait for content to load
|
|
107
|
+
await page.waitForLoadState('networkidle');
|
|
108
|
+
|
|
109
|
+
// The root container should be present
|
|
110
|
+
const root = page.locator('#root');
|
|
111
|
+
await expect(root).not.toBeEmpty();
|
|
83
112
|
});
|
|
84
113
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const iframe = page.frameLocator('iframe');
|
|
110
|
-
const albumCard = iframe.locator('button:has-text("Summer Slice")');
|
|
111
|
-
await expect(albumCard).toBeVisible();
|
|
112
|
-
|
|
113
|
-
const styles = await albumCard.evaluate((el) => {
|
|
114
|
-
const computed = window.getComputedStyle(el);
|
|
115
|
-
return {
|
|
116
|
-
cursor: computed.cursor,
|
|
117
|
-
borderRadius: computed.borderRadius,
|
|
118
|
-
};
|
|
114
|
+
test('should maintain album card styles in fullscreen', async ({ page }) => {
|
|
115
|
+
await page.goto(
|
|
116
|
+
createSimulatorUrl({
|
|
117
|
+
simulation: 'albums-show',
|
|
118
|
+
theme: 'dark',
|
|
119
|
+
displayMode: 'fullscreen',
|
|
120
|
+
host,
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const iframe = page.frameLocator('iframe');
|
|
125
|
+
const albumCard = iframe.locator('button:has-text("Summer Slice")');
|
|
126
|
+
await expect(albumCard).toBeVisible();
|
|
127
|
+
|
|
128
|
+
const styles = await albumCard.evaluate((el) => {
|
|
129
|
+
const computed = window.getComputedStyle(el);
|
|
130
|
+
return {
|
|
131
|
+
cursor: computed.cursor,
|
|
132
|
+
borderRadius: computed.borderRadius,
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
expect(styles.cursor).toBe('pointer');
|
|
137
|
+
expect(styles.borderRadius).toBe('12px');
|
|
119
138
|
});
|
|
120
|
-
|
|
121
|
-
expect(styles.cursor).toBe('pointer');
|
|
122
|
-
expect(styles.borderRadius).toBe('12px');
|
|
123
139
|
});
|
|
124
140
|
});
|
|
125
|
-
}
|
|
141
|
+
}
|