@@ -35,30 +35,92 @@ const SLOW_SERVERS: Record<string, number> = {
3535 threejs : 2000 , // Three.js WebGL initialization
3636} ;
3737
38- // Server configurations (key is used for screenshot filenames, name is the MCP server name)
39- const SERVERS = [
40- { key : "integration" , name : "Integration Test Server" } ,
41- { key : "basic-preact" , name : "Basic MCP App Server (Preact)" } ,
42- { key : "basic-react" , name : "Basic MCP App Server (React)" } ,
43- { key : "basic-solid" , name : "Basic MCP App Server (Solid)" } ,
44- { key : "basic-svelte" , name : "Basic MCP App Server (Svelte)" } ,
45- { key : "basic-vanillajs" , name : "Basic MCP App Server (Vanilla JS)" } ,
46- { key : "basic-vue" , name : "Basic MCP App Server (Vue)" } ,
47- { key : "budget-allocator" , name : "Budget Allocator Server" } ,
48- { key : "cohort-heatmap" , name : "Cohort Heatmap Server" } ,
49- { key : "customer-segmentation" , name : "Customer Segmentation Server" } ,
50- { key : "map-server" , name : "Map Server" } ,
51- { key : "pdf-server" , name : "PDF Server" } ,
52- { key : "qr-server" , name : "QR Code Server" } ,
53- { key : "scenario-modeler" , name : "SaaS Scenario Modeler" } ,
54- { key : "shadertoy" , name : "ShaderToy Server" } ,
55- { key : "sheet-music" , name : "Sheet Music Server" } ,
56- { key : "system-monitor" , name : "System Monitor Server" } ,
57- { key : "threejs" , name : "Three.js Server" } ,
58- { key : "transcript" , name : "Transcript Server" } ,
59- { key : "wiki-explorer" , name : "Wiki Explorer" } ,
38+ // Servers to skip in CI (require special resources like GPU, large ML models)
39+ const SKIP_SERVERS = new Set < string > ( [
40+ // None currently - say-server widget works without TTS model for screenshots
41+ ] ) ;
42+
43+ // Optional: filter to a single example via EXAMPLE env var (folder name)
44+ const EXAMPLE_FILTER = process . env . EXAMPLE ;
45+
46+ // Server configurations (key is used for screenshot filenames, name is the MCP server name, dir is the folder name)
47+ const ALL_SERVERS = [
48+ {
49+ key : "integration" ,
50+ name : "Integration Test Server" ,
51+ dir : "integration-server" ,
52+ } ,
53+ {
54+ key : "basic-preact" ,
55+ name : "Basic MCP App Server (Preact)" ,
56+ dir : "basic-server-preact" ,
57+ } ,
58+ {
59+ key : "basic-react" ,
60+ name : "Basic MCP App Server (React)" ,
61+ dir : "basic-server-react" ,
62+ } ,
63+ {
64+ key : "basic-solid" ,
65+ name : "Basic MCP App Server (Solid)" ,
66+ dir : "basic-server-solid" ,
67+ } ,
68+ {
69+ key : "basic-svelte" ,
70+ name : "Basic MCP App Server (Svelte)" ,
71+ dir : "basic-server-svelte" ,
72+ } ,
73+ {
74+ key : "basic-vanillajs" ,
75+ name : "Basic MCP App Server (Vanilla JS)" ,
76+ dir : "basic-server-vanillajs" ,
77+ } ,
78+ {
79+ key : "basic-vue" ,
80+ name : "Basic MCP App Server (Vue)" ,
81+ dir : "basic-server-vue" ,
82+ } ,
83+ {
84+ key : "budget-allocator" ,
85+ name : "Budget Allocator Server" ,
86+ dir : "budget-allocator-server" ,
87+ } ,
88+ {
89+ key : "cohort-heatmap" ,
90+ name : "Cohort Heatmap Server" ,
91+ dir : "cohort-heatmap-server" ,
92+ } ,
93+ {
94+ key : "customer-segmentation" ,
95+ name : "Customer Segmentation Server" ,
96+ dir : "customer-segmentation-server" ,
97+ } ,
98+ { key : "map-server" , name : "Map Server" , dir : "map-server" } ,
99+ { key : "pdf-server" , name : "PDF Server" , dir : "pdf-server" } ,
100+ { key : "qr-server" , name : "QR Code Server" , dir : "qr-server" } ,
101+ { key : "say-server" , name : "Say Demo" , dir : "say-server" } ,
102+ {
103+ key : "scenario-modeler" ,
104+ name : "SaaS Scenario Modeler" ,
105+ dir : "scenario-modeler-server" ,
106+ } ,
107+ { key : "shadertoy" , name : "ShaderToy Server" , dir : "shadertoy-server" } ,
108+ { key : "sheet-music" , name : "Sheet Music Server" , dir : "sheet-music-server" } ,
109+ {
110+ key : "system-monitor" ,
111+ name : "System Monitor Server" ,
112+ dir : "system-monitor-server" ,
113+ } ,
114+ { key : "threejs" , name : "Three.js Server" , dir : "threejs-server" } ,
115+ { key : "transcript" , name : "Transcript Server" , dir : "transcript-server" } ,
116+ { key : "wiki-explorer" , name : "Wiki Explorer" , dir : "wiki-explorer-server" } ,
60117] ;
61118
119+ // Filter servers if EXAMPLE is specified
120+ const SERVERS = EXAMPLE_FILTER
121+ ? ALL_SERVERS . filter ( ( s ) => s . dir === EXAMPLE_FILTER )
122+ : ALL_SERVERS ;
123+
62124/**
63125 * Helper to get the app frame locator (nested: sandbox > app)
64126 */
@@ -129,12 +191,23 @@ test.describe("Host UI", () => {
129191
130192// Define tests for each server using forEach to avoid for-loop issues
131193SERVERS . forEach ( ( server ) => {
194+ // Skip servers that require special resources (GPU, large ML models)
195+ const shouldSkip = SKIP_SERVERS . has ( server . key ) ;
196+
132197 test . describe ( server . name , ( ) => {
133198 test ( "loads app UI" , async ( { page } ) => {
199+ if ( shouldSkip ) {
200+ test . skip ( ) ;
201+ return ;
202+ }
134203 await loadServer ( page , server . name ) ;
135204 } ) ;
136205
137206 test ( "screenshot matches golden" , async ( { page } ) => {
207+ if ( shouldSkip ) {
208+ test . skip ( ) ;
209+ return ;
210+ }
138211 await loadServer ( page , server . name ) ;
139212
140213 // Some servers (WebGL, tile-based) need extra stabilization time
@@ -153,12 +226,20 @@ SERVERS.forEach((server) => {
153226} ) ;
154227
155228// Interaction tests for integration server (tests all SDK communication APIs)
156- const integrationServer = SERVERS . find ( ( s ) => s . key === "integration" ) ! ;
229+ // Only run if integration-server is included (either no filter or EXAMPLE=integration-server)
230+ const integrationServer = SERVERS . find ( ( s ) => s . key === "integration" ) ;
231+ const integrationServerName =
232+ integrationServer ?. name ?? "Integration Test Server" ;
233+
234+ test . describe ( `Integration Test Server - Interactions` , ( ) => {
235+ test . skip (
236+ ( ) => ! integrationServer ,
237+ "Skipped: integration-server not in EXAMPLE filter" ,
238+ ) ;
157239
158- test . describe ( `${ integrationServer . name } - Interactions` , ( ) => {
159240 test ( "Send Message button triggers host callback" , async ( { page } ) => {
160241 const logs = captureHostLogs ( page ) ;
161- await loadServer ( page , integrationServer . name ) ;
242+ await loadServer ( page , integrationServerName ) ;
162243
163244 const appFrame = getAppFrame ( page ) ;
164245 await appFrame . locator ( 'button:has-text("Send Message")' ) . click ( ) ;
@@ -171,7 +252,7 @@ test.describe(`${integrationServer.name} - Interactions`, () => {
171252
172253 test ( "Send Log button triggers host callback" , async ( { page } ) => {
173254 const logs = captureHostLogs ( page ) ;
174- await loadServer ( page , integrationServer . name ) ;
255+ await loadServer ( page , integrationServerName ) ;
175256
176257 const appFrame = getAppFrame ( page ) ;
177258 await appFrame . locator ( 'button:has-text("Send Log")' ) . click ( ) ;
@@ -185,7 +266,7 @@ test.describe(`${integrationServer.name} - Interactions`, () => {
185266
186267 test ( "Open Link button triggers host callback" , async ( { page } ) => {
187268 const logs = captureHostLogs ( page ) ;
188- await loadServer ( page , integrationServer . name ) ;
269+ await loadServer ( page , integrationServerName ) ;
189270
190271 const appFrame = getAppFrame ( page ) ;
191272 await appFrame . locator ( 'button:has-text("Open Link")' ) . click ( ) ;
0 commit comments