11import { test , expect } from '@playwright/test' ;
2+ import type { Page } from '@playwright/test' ;
23
34const base = 'http://localhost:3001' ;
45
6+ const demoPages = [
7+ { name : 'Main' , hash : '#/' } ,
8+ { name : 'UI Library' , hash : '#/ui-library' } ,
9+ { name : 'Dialog' , hash : '#/dialog' } ,
10+ { name : 'Svelte Page' , hash : '#/svelte' } ,
11+ { name : 'Routing' , hash : '#/routing/foo' } ,
12+ ] ;
13+
14+ const appLinks = [
15+ { name : 'App #1' , href : 'http://localhost:3001' } ,
16+ { name : 'App #2' , href : 'http://localhost:3002' } ,
17+ { name : 'App #3' , href : 'http://localhost:3003' } ,
18+ { name : 'App #4' , href : 'http://localhost:3004' } ,
19+ { name : 'App #5' , href : 'http://localhost:3005' } ,
20+ ] ;
21+
22+ const mainPageParagraphs = [
23+ 'Welcome to the Module Federation Demo!' ,
24+ 'Click any of the items on the left to get started.' ,
25+ 'Feel free to leave me feedback' ,
26+ ] ;
27+
28+ const uiLibraryParagraphs = [
29+ 'Simple example showing host app and external component using separate CSS solutions.' ,
30+ 'This Button component can be found in App #3.' ,
31+ 'This button is also used in the routing demo.' ,
32+ ] ;
33+
34+ const routingParagraphs = [
35+ 'The following tab components are being imported remotely from "bravo-app".' ,
36+ "Notice that your browser's route is /routing/<foo|bar> depending on which tab is active." ,
37+ 'If you open http://localhost:3002 you will see the same tab components at the root level' ,
38+ 'The "Bar" tab also lazily renders the styled-component Button from the UI Library demo only when rendered.' ,
39+ ] ;
40+
41+ const escapeRegExp = ( value : string ) => value . replace ( / [ - / \^ $ * + ? . ( ) | [ \] { } ] / g, '\$&' ) ;
42+
43+ const expectAppBar = async ( page : Page , title : string ) => {
44+ const appBar = page . locator ( 'header' ) . first ( ) ;
45+ await expect ( appBar ) . toBeVisible ( ) ;
46+ await expect ( appBar ) . toHaveCSS ( 'background-color' , 'rgb(63, 81, 181)' ) ;
47+ await expect ( page . getByRole ( 'heading' , { name : title } ) ) . toBeVisible ( ) ;
48+ } ;
49+
550test . describe ( 'Comprehensive Demo App1' , ( ) => {
651 test ( 'main page displays sidebar links and elements' , async ( { page } ) => {
752 await page . goto ( base ) ;
53+
854 await expect ( page . getByRole ( 'heading' , { name : 'SideNav' } ) ) . toBeVisible ( ) ;
55+ await expect ( page . getByText ( 'Demo Pages' ) ) . toBeVisible ( ) ;
56+ await expect ( page . getByText ( 'Apps' ) ) . toBeVisible ( ) ;
957
10- const demoLinks = [ 'Main' , 'UI Library' , 'Dialog' , 'Svelte Page' , 'Routing' ] ;
11- for ( const name of demoLinks ) {
12- await expect ( page . getByRole ( 'button' , { name } ) ) . toBeVisible ( ) ;
58+ for ( const { name, hash } of demoPages ) {
59+ const link = page . locator ( 'a' , { hasText : name } ) . first ( ) ;
60+ await expect ( link ) . toBeVisible ( ) ;
61+ await expect ( link ) . toHaveAttribute ( 'href' , hash ) ;
1362 }
1463
15- const appLinks = [
16- { name : 'App #1' , href : 'http://localhost:3001' } ,
17- { name : 'App #2' , href : 'http://localhost:3002' } ,
18- { name : 'App #3' , href : 'http://localhost:3003' } ,
19- { name : 'App #4' , href : 'http://localhost:3004' } ,
20- { name : 'App #5' , href : 'http://localhost:3005' } ,
21- ] ;
2264 for ( const { name, href } of appLinks ) {
23- await expect ( page . locator ( 'a' , { hasText : name } ) ) . toHaveAttribute ( 'href' , href ) ;
65+ const link = page . locator ( `a[href="${ href } "]` ) . first ( ) ;
66+ await expect ( link ) . toBeVisible ( ) ;
67+ await expect ( link ) . toHaveAttribute ( 'href' , href ) ;
68+ await expect ( link ) . toContainText ( name ) ;
69+ await expect ( link ) . toContainText ( href ) ;
2470 }
2571
26- await expect ( page . getByRole ( 'heading' , { name : 'Module Federation Demo' } ) ) . toBeVisible ( ) ;
27- await expect ( page . getByText ( 'Alert from LitElement' ) ) . toBeVisible ( ) ;
28- const actionButton = page . getByRole ( 'button' , { name : 'Lit Element Action' } ) ;
29- await expect ( actionButton ) . toBeVisible ( ) ;
72+ await expectAppBar ( page , 'Module Federation Demo' ) ;
73+
74+ const alert = page . locator ( '.alert' ) ;
75+ await expect ( alert ) . toBeVisible ( ) ;
76+ await expect ( alert ) . toHaveText ( / A l e r t f r o m L i t E l e m e n t / ) ;
77+ await expect ( page . locator ( '.closebtn' ) ) . toBeVisible ( ) ;
78+
79+ for ( const paragraph of mainPageParagraphs ) {
80+ await expect ( page . locator ( 'p' , { hasText : paragraph } ) ) . toBeVisible ( ) ;
81+ }
82+
83+ await expect (
84+ page . getByRole ( 'link' , { name : 'https://github.com/module-federation/mfe-webpack-demo' } ) ,
85+ ) . toHaveAttribute ( 'href' , 'https://github.com/module-federation/mfe-webpack-demo' ) ;
86+
87+ const actionButton = page . locator ( 'action-button button' ) ;
88+ await expect ( actionButton ) . toHaveText ( 'Lit Element Action' ) ;
89+ await expect ( actionButton ) . toHaveCSS ( 'background-color' , 'rgb(219, 112, 147)' ) ;
3090 } ) ;
3191
3292 test ( 'main tab functionality' , async ( { page } ) => {
3393 await page . goto ( base ) ;
94+
3495 page . once ( 'dialog' , async dialog => {
3596 expect ( dialog . message ( ) ) . toBe ( 'You have pressed a button.' ) ;
3697 await dialog . accept ( ) ;
3798 } ) ;
38- await page . getByRole ( 'button' , { name : 'Lit Element Action' } ) . click ( ) ;
99+
100+ await page . locator ( 'action-button button' ) . click ( ) ;
39101 await page . locator ( '.closebtn' ) . click ( ) ;
40102 await expect ( page . locator ( '.alert' ) ) . toBeHidden ( ) ;
103+
104+ for ( const { name, hash } of demoPages ) {
105+ await page . locator ( 'a' , { hasText : name } ) . first ( ) . click ( ) ;
106+ await expect ( page ) . toHaveURL ( `${ base } /${ hash } ` ) ;
107+ }
108+
109+ await page . locator ( 'a' , { hasText : 'Main' } ) . first ( ) . click ( ) ;
110+ await expect ( page ) . toHaveURL ( `${ base } /#/` ) ;
111+
112+ for ( const { href } of appLinks ) {
113+ await Promise . all ( [
114+ page . waitForNavigation ( { waitUntil : 'load' } ) ,
115+ page . locator ( `a[href="${ href } "]` ) . first ( ) . click ( ) ,
116+ ] ) ;
117+ await expect ( page ) . toHaveURL ( new RegExp ( `^${ escapeRegExp ( href ) } ` ) ) ;
118+ await page . goBack ( ) ;
119+ await expect ( page ) . toHaveURL ( new RegExp ( `^${ escapeRegExp ( base ) } ` ) ) ;
120+ await expect ( page . getByRole ( 'heading' , { name : 'Module Federation Demo' } ) ) . toBeVisible ( ) ;
121+ }
41122 } ) ;
42123
43124 test ( 'UI library page renders remote button' , async ( { page } ) => {
44125 await page . goto ( `${ base } /#/ui-library` ) ;
45- await expect ( page . getByRole ( 'heading' , { name : 'UI Library Demo' } ) ) . toBeVisible ( ) ;
46- await expect (
47- page . getByText ( 'Simple example showing host app and external component using separate CSS solutions.' ) ,
48- ) . toBeVisible ( ) ;
49- await expect ( page . getByRole ( 'button' , { name : / B u t t o n / } ) ) . toBeVisible ( ) ;
126+
127+ await expectAppBar ( page , 'UI Library Demo' ) ;
128+
129+ for ( const paragraph of uiLibraryParagraphs ) {
130+ await expect ( page . locator ( 'p' , { hasText : paragraph } ) ) . toBeVisible ( ) ;
131+ }
132+
133+ await expect ( page . locator ( 'a[href="http://localhost:3003/"]' ) . first ( ) ) . toHaveAttribute (
134+ 'href' ,
135+ 'http://localhost:3003/' ,
136+ ) ;
137+ await expect ( page . locator ( 'a[href="http://localhost:3001/#/routing/foo"]' ) . first ( ) ) . toHaveAttribute (
138+ 'href' ,
139+ 'http://localhost:3001/#/routing/foo' ,
140+ ) ;
141+
142+ const styledButton = page . getByRole ( 'button' , { name : '💅 Button' } ) ;
143+ await expect ( styledButton ) . toBeVisible ( ) ;
144+ await expect ( styledButton ) . toHaveCSS ( 'background-color' , 'rgb(219, 112, 147)' ) ;
50145 } ) ;
51146
52147 test ( 'dialog page loads and dialog opens' , async ( { page } ) => {
53148 await page . goto ( `${ base } /#/dialog` ) ;
54- await expect ( page . getByRole ( 'heading' , { name : 'Dialog Demo' } ) ) . toBeVisible ( ) ;
149+
150+ await expectAppBar ( page , 'Dialog Demo' ) ;
55151 await expect (
56- page . getByText (
57- 'Clicking the button below will render a Dialog using React Portal. This dialog component is being lazy loaded from the app #2.' ,
58- ) ,
152+ page . locator ( 'p' , {
153+ hasText :
154+ 'Clicking the button below will render a Dialog using React Portal. This dialog component is being lazy loaded from the app #2.' ,
155+ } ) ,
59156 ) . toBeVisible ( ) ;
157+
60158 await page . getByRole ( 'button' , { name : 'Open Dialog' } ) . click ( ) ;
61159 const dialog = page . locator ( '[role="dialog"]' ) ;
62160 await expect ( dialog . getByRole ( 'heading' , { name : 'Dialog Example' } ) ) . toBeVisible ( ) ;
@@ -69,21 +167,32 @@ test.describe('Comprehensive Demo App1', () => {
69167
70168 test ( 'svelte page updates greeting' , async ( { page } ) => {
71169 await page . goto ( `${ base } /#/svelte` ) ;
72- await expect ( page . getByRole ( 'heading' , { name : 'Svelte Demo' } ) ) . toBeVisible ( ) ;
170+
171+ await expectAppBar ( page , 'Svelte Demo' ) ;
172+
73173 const input = page . locator ( 'input' ) ;
74- await input . fill ( 'test' ) ;
75- await expect ( page . locator ( 'h1' ) ) . toHaveText ( 'Hello From Svelte test!' ) ;
174+ await expect ( input ) . toBeVisible ( ) ;
175+ await input . fill ( 'May The Force Be With You' ) ;
176+ await expect ( page . locator ( 'h1' ) ) . toHaveText ( 'Hello From Svelte May The Force Be With You!' ) ;
76177 } ) ;
77178
78179 test ( 'routing page renders tabs' , async ( { page } ) => {
79180 await page . goto ( `${ base } /#/routing/foo` ) ;
80- await expect ( page . getByRole ( 'heading' , { name : 'Routing Demo' } ) ) . toBeVisible ( ) ;
181+
182+ await expectAppBar ( page , 'Routing Demo' ) ;
183+
184+ for ( const paragraph of routingParagraphs ) {
185+ await expect ( page . locator ( 'p' , { hasText : paragraph } ) ) . toBeVisible ( ) ;
186+ }
187+
188+ await expect ( page . getByRole ( 'tab' , { name : 'Foo' } ) ) . toBeVisible ( ) ;
81189 await expect ( page . getByText ( 'Foo Content' ) ) . toBeVisible ( ) ;
190+
82191 await page . getByRole ( 'tab' , { name : 'Bar' } ) . click ( ) ;
83192 await expect ( page . getByText ( 'Bar Content' ) ) . toBeVisible ( ) ;
84- await expect ( page . getByRole ( 'button' , { name : 'Bar Button' } ) ) . toHaveCSS (
85- 'background-color' ,
86- 'rgb(219, 112, 147)' ,
87- ) ;
193+
194+ const barButton = page . getByRole ( 'button' , { name : 'Bar Button' } ) ;
195+ await expect ( barButton ) . toBeVisible ( ) ;
196+ await expect ( barButton ) . toHaveCSS ( 'background-color' , 'rgb(219, 112, 147)' ) ;
88197 } ) ;
89198} ) ;
0 commit comments