1- import  {  test ,  expect ,  Page  }  from  '@playwright/test' ; 
2- 
3- // Helper functions 
4- async  function  openLocalhost ( page : Page ,  port : number )  { 
5-   await  page . goto ( `http://localhost:${ port }  ) ; 
6-   await  page . waitForLoadState ( 'networkidle' ) ; 
7- } 
8- 
9- async  function  checkElementWithTextPresence ( page : Page ,  selector : string ,  text : string )  { 
10-   const  element  =  page . locator ( `${ selector } ${ text }  ) ; 
11-   await  expect ( element ) . toBeVisible ( ) ; 
12- } 
13- 
14- async  function  clickElementWithText ( page : Page ,  selector : string ,  text : string )  { 
15-   await  page . click ( `${ selector } ${ text }  ) ; 
16- } 
17- 
18- 
19- 
20- const  appsData  =  [ 
1+ import  {  test ,  expect  }  from  '@playwright/test' ; 
2+ import  {  BasePage  }  from  './utils/base-test' ; 
3+ import  {  Constants  }  from  './utils/constants' ; 
4+ import  {  selectors  }  from  './utils/selectors' ; 
5+ 
6+ type  AppInfo  =  { 
7+   host : number ; 
8+   appDisplayName : string ; 
9+   localButtonText : string ; 
10+   localButtonColor : string ; 
11+   remoteButtonText : string ; 
12+   remoteButtonColor : string ; 
13+ } ; 
14+ 
15+ const  headerText  =  Constants . commonConstantsData . headerText ; 
16+ 
17+ const  apps : AppInfo [ ]  =  [ 
2118  { 
22-     headerText : 'Module Federation with Automatic Vendor Sharing' , 
23-     appNameText : 'App 1 (Host & Remote)' , 
24-     buttonColor : 'rgb(255, 0, 0)' , 
2519    host : 3001 , 
20+     appDisplayName : Constants . commonConstantsData . appDisplayNames . app1 , 
21+     localButtonText : Constants . commonConstantsData . buttonLabels . app1 , 
22+     localButtonColor : Constants . color . app1Button , 
23+     remoteButtonText : Constants . commonConstantsData . buttonLabels . app2 , 
24+     remoteButtonColor : Constants . color . app2Button , 
2625  } , 
2726  { 
28-     headerText : 'Module Federation with Automatic Vendor Sharing' , 
29-     appNameText : 'App 2 (Host & Remote)' , 
30-     buttonColor : 'rgb(0, 0, 139)' , 
3127    host : 3002 , 
28+     appDisplayName : Constants . commonConstantsData . appDisplayNames . app2 , 
29+     localButtonText : Constants . commonConstantsData . buttonLabels . app2 , 
30+     localButtonColor : Constants . color . app2Button , 
31+     remoteButtonText : Constants . commonConstantsData . buttonLabels . app1 , 
32+     remoteButtonColor : Constants . color . app1Button , 
3233  } , 
3334] ; 
3435
35- test . describe ( 'Automatic Vendor Sharing E2E Tests' ,  ( )  =>  { 
36-   
37-   appsData . forEach ( ( appData )  =>  { 
38-     const  {  host,  appNameText,  headerText }  =  appData ; 
39-     
40-     test . describe ( `Check ${ appNameText }  ,  ( )  =>  { 
41-       test ( `should display ${ appNameText }  ,  async  ( {  page } )  =>  { 
36+ test . describe ( 'Automatic Vendor Sharing example' ,  ( )  =>  { 
37+   for  ( const  app  of  apps )  { 
38+     test . describe ( app . appDisplayName ,  ( )  =>  { 
39+       test ( `renders the shell for ${ app . appDisplayName }  ,  async  ( {  page } )  =>  { 
40+         const  basePage  =  new  BasePage ( page ) ; 
4241        const  consoleErrors : string [ ]  =  [ ] ; 
42+ 
4343        page . on ( 'console' ,  ( msg )  =>  { 
4444          if  ( msg . type ( )  ===  'error' )  { 
4545            consoleErrors . push ( msg . text ( ) ) ; 
4646          } 
4747        } ) ; 
4848
49-         await  openLocalhost ( page ,  host ) ; 
50- 
51-         // Check header and subheader exist 
52-         await  checkElementWithTextPresence ( page ,  'h1' ,  headerText ) ; 
53-         await  checkElementWithTextPresence ( page ,  'h2' ,  appNameText ) ; 
49+         await  basePage . openLocalhost ( app . host ) ; 
5450
55-         // Verify no critical console errors 
56-         const  criticalErrors  =  consoleErrors . filter ( error  =>  
57-           error . includes ( 'Failed to fetch' )  ||  
58-           error . includes ( 'ChunkLoadError' )  || 
59-           error . includes ( 'Module not found' )  || 
60-           error . includes ( 'TypeError' ) 
61-         ) ; 
62-         expect ( criticalErrors ) . toHaveLength ( 0 ) ; 
63-       } ) ; 
51+         await  expect ( page . locator ( selectors . tags . headers . h1 ) ) . toContainText ( headerText ) ; 
52+         await  expect ( page . locator ( selectors . tags . headers . h2 ) ) . toContainText ( app . appDisplayName ) ; 
6453
65-       test ( `should display ${ appNameText }  ,  async  ( {  page } )  =>  { 
66-         await  openLocalhost ( page ,  host ) ; 
54+         const  relevantErrors  =  consoleErrors . filter ( ( error )  =>  { 
55+           if  ( error . includes ( 'WebSocket connection to' )  &&  error . includes ( 'WEB_SOCKET_CONNECT_MAGIC_ID' ) )  { 
56+             return  false ; 
57+           } 
6758
68-         const  buttonText  =  `${ appNameText . split ( ' ' ) [ 0 ] } ${ appNameText . split ( ' ' ) [ 1 ] }  ; 
69-         
70-         // Check button exists with correct text 
71-         await  checkElementWithTextPresence ( page ,  'button' ,  buttonText ) ; 
72-       } ) ; 
59+           if  ( error . includes ( 'dynamic-remote-type-hints-plugin' ) )  { 
60+             return  false ; 
61+           } 
7362
74-       test ( `should handle  ${ appNameText }  button interactions` ,   async   ( {  page  } )   =>   { 
75-         await   openLocalhost ( page ,   host ) ; 
63+            return   true ; 
64+         } ) ; 
7665
77-         const  buttonText  =  `${ appNameText . split ( ' ' ) [ 0 ] } ${ appNameText . split ( ' ' ) [ 1 ] }  ; 
78-         
79-         // Click the button and verify it responds 
80-         await  clickElementWithText ( page ,  'button' ,  buttonText ) ; 
81-         
82-         // Verify button is still visible and functional after click 
83-         await  checkElementWithTextPresence ( page ,  'button' ,  buttonText ) ; 
84-       } ) ; 
85-     } ) ; 
86-   } ) ; 
87- 
88-   test . describe ( 'Cross-App Integration Tests' ,  ( )  =>  { 
89-     test ( 'should demonstrate automatic vendor sharing between apps' ,  async  ( {  page } )  =>  { 
90-       const  networkRequests : string [ ]  =  [ ] ; 
91-       
92-       page . on ( 'request' ,  ( request )  =>  { 
93-         networkRequests . push ( request . url ( ) ) ; 
66+         expect ( relevantErrors ,  'Unexpected console errors detected in the browser console' ) . toHaveLength ( 0 ) ; 
9467      } ) ; 
9568
96-       // Visit both apps to trigger vendor sharing 
97-       await  page . goto ( 'http://localhost:3001' ) ; 
98-       await  page . waitForLoadState ( 'networkidle' ) ; 
99-       
100-       await  page . goto ( 'http://localhost:3002' ) ; 
101-       await  page . waitForLoadState ( 'networkidle' ) ; 
102- 
103-       // Verify shared dependencies are loaded efficiently 
104-       const  reactRequests  =  networkRequests . filter ( url  =>  
105-         url . includes ( 'react' )  &&  ! url . includes ( 'react-dom' ) 
106-       ) ; 
107-       
108-       // Should not load React multiple times due to vendor sharing 
109-       expect ( reactRequests . length ) . toBeLessThanOrEqual ( 10 ) ; 
110-     } ) ; 
69+       test ( `exposes the styled local button for ${ app . appDisplayName }  ,  async  ( {  page } )  =>  { 
70+         const  basePage  =  new  BasePage ( page ) ; 
11171
112-     test ( 'should handle CORS correctly for federated modules' ,  async  ( {  page } )  =>  { 
113-       const  corsErrors : string [ ]  =  [ ] ; 
114-       page . on ( 'response' ,  ( response )  =>  { 
115-         if  ( response . status ( )  >=  400  &&  response . url ( ) . includes ( 'localhost:300' ) )  { 
116-           corsErrors . push ( `${ response . status ( ) } ${ response . url ( ) }  ) ; 
117-         } 
118-       } ) ; 
72+         await  basePage . openLocalhost ( app . host ) ; 
11973
120-       // Test cross-origin requests work properly 
121-       await  page . goto ( 'http://localhost:3001' ) ; 
122-       await  page . waitForLoadState ( 'networkidle' ) ; 
74+          const   localButton   =   page . getByRole ( 'button' ,   {   name :  app . localButtonText   } ) ; 
75+          await  expect ( localButton ) . toBeVisible ( ) ; 
76+          await  expect ( localButton ) . toHaveCSS ( 'background-color' ,   app . localButtonColor ) ; 
12377
124-       // Should have no CORS errors 
125-       expect ( corsErrors ) . toHaveLength ( 0 ) ; 
126-     } ) ; 
78+          await   localButton . click ( ) ; 
79+          await   expect ( localButton ) . toBeVisible ( ) ; 
80+        } ) ; 
12781
128-     test ( 'should load applications within reasonable time' ,  async  ( {  page } )  =>  { 
129-       const  startTime  =  Date . now ( ) ; 
130-       
131-       await  page . goto ( 'http://localhost:3001' ) ; 
132-       await  page . waitForLoadState ( 'networkidle' ) ; 
133-       
134-       const  loadTime  =  Date . now ( )  -  startTime ; 
135-       expect ( loadTime ) . toBeLessThan ( 10000 ) ;  // Should load within 10 seconds 
136-     } ) ; 
137-   } ) ; 
82+       test ( `loads the remote button for ${ app . appDisplayName }  ,  async  ( {  page } )  =>  { 
83+         const  basePage  =  new  BasePage ( page ) ; 
13884
139-   test . describe ( 'AutomaticVendorFederation Features' ,  ( )  =>  { 
140-     test ( 'should demonstrate shared vendor optimization' ,  async  ( {  page } )  =>  { 
141-       await  page . goto ( 'http://localhost:3001' ) ; 
142-       await  page . waitForLoadState ( 'networkidle' ) ; 
85+         await  basePage . openLocalhost ( app . host ) ; 
86+         await  basePage . waitForDynamicImport ( ) ; 
14387
144-       // Check that the main elements are present 
145-       await  checkElementWithTextPresence ( page ,  'h1' ,  'Module Federation with Automatic Vendor Sharing' ) ; 
146-       await  checkElementWithTextPresence ( page ,  'h2' ,  'App 1 (Host & Remote)' ) ; 
147-     } ) ; 
88+         const  remoteButton  =  page . getByRole ( 'button' ,  {  name : app . remoteButtonText  } ) ; 
89+         await  expect ( remoteButton ) . toBeVisible ( ) ; 
90+         await  expect ( remoteButton ) . toHaveCSS ( 'background-color' ,  app . remoteButtonColor ) ; 
14891
149-     test ( 'should handle error boundaries correctly' ,  async  ( {  page } )  =>  { 
150-       const  consoleErrors : string [ ]  =  [ ] ; 
151-       page . on ( 'console' ,  ( msg )  =>  { 
152-         if  ( msg . type ( )  ===  'error' )  { 
153-           consoleErrors . push ( msg . text ( ) ) ; 
154-         } 
92+         await  remoteButton . click ( ) ; 
93+         await  expect ( remoteButton ) . toBeVisible ( ) ; 
15594      } ) ; 
156- 
157-       await  page . goto ( 'http://localhost:3001' ) ; 
158-       await  page . waitForLoadState ( 'networkidle' ) ; 
159- 
160-       // Click button to test functionality 
161-       const  buttonExists  =  await  page . locator ( 'button' ) . first ( ) . isVisible ( ) ; 
162-       if  ( buttonExists )  { 
163-         await  page . locator ( 'button' ) . first ( ) . click ( ) ; 
164-         await  page . waitForTimeout ( 1000 ) ; 
165-       } 
166- 
167-       // Should handle any errors gracefully 
168-       const  criticalErrors  =  consoleErrors . filter ( error  =>  
169-         error . includes ( 'Uncaught' )  &&  
170-         ! error . includes ( 'webpack-dev-server' )  && 
171-         ! error . includes ( 'DevTools' ) 
172-       ) ; 
173-       expect ( criticalErrors ) . toHaveLength ( 0 ) ; 
17495    } ) ; 
175-   } ) ; 
176- } ) ; 
96+   } 
97+ } ) ; 
0 commit comments