Skip to content

Commit 227b0c5

Browse files
authored
feat: Add e2e tests for react-nextjs -> nextjs-host-react-remote sample (#2744)
1 parent 1fb1e10 commit 227b0c5

File tree

22 files changed

+542
-43
lines changed

22 files changed

+542
-43
lines changed

cypress/common/base.ts

Lines changed: 87 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ export class BaseMethods {
360360
text,
361361
isParent = false,
362362
checkType = 'contains',
363-
isWithInvoke = true
363+
isWithInvoke = true,
364+
isInclude = true
364365
}: {
365366
selector: string,
366367
attr?: string,
@@ -373,7 +374,8 @@ export class BaseMethods {
373374
text?: string,
374375
isParent?: boolean,
375376
checkType?: string,
376-
isWithInvoke?: boolean
377+
isWithInvoke?: boolean,
378+
isInclude?: boolean
377379
}
378380
): Cypress.Chainable<JQuery<HTMLElement>> {
379381
if(text) {
@@ -382,7 +384,18 @@ export class BaseMethods {
382384
.contains(text)
383385
.parent()
384386
.invoke(attr, prop)
385-
.should('include', value)
387+
.should(isInclude? 'include' : 'not.include', value)
388+
389+
// @ts-ignore
390+
return;
391+
}
392+
393+
if (parentSelector) {
394+
cy.get(parentSelector)
395+
.find(selector)
396+
.contains(text)
397+
.invoke(attr, prop)
398+
.should(isInclude? 'include' : 'not.include', value)
386399

387400
// @ts-ignore
388401
return;
@@ -394,7 +407,7 @@ export class BaseMethods {
394407
.eq(index)
395408
.contains(text)
396409
.invoke(attr, prop)
397-
.should('include', value)
410+
.should(isInclude? 'include' : 'not.include', value)
398411

399412
// @ts-ignore
400413
return;
@@ -415,29 +428,29 @@ export class BaseMethods {
415428
return cy.get(selector)
416429
.contains(text)
417430
.invoke(attr, prop)
418-
.should('include', value)
431+
.should(isInclude? 'include' : 'not.include', value)
419432
}
420433

421434
if(index) {
422435
return cy.get(selector)
423436
.eq(index)
424437
.invoke(attr, prop)
425-
.should('include', value)
438+
.should(isInclude? 'include' : 'not.include', value)
426439
}
427440

428441
if(parentSelector && isShadowElement) {
429442
return cy.get(parentSelector)
430443
.shadow()
431444
.find(selector)
432445
.invoke(attr, prop)
433-
.should('include', value)
446+
.should(isInclude? 'include' : 'not.include', value)
434447
}
435448

436449
if(parentSelector) {
437450
return cy.get(parentSelector)
438451
.find(selector)
439452
.invoke(attr, prop)
440-
.should('include', value)
453+
.should(isInclude? 'include' : 'not.include', value)
441454
}
442455

443456
if(isMultiple) {
@@ -453,7 +466,7 @@ export class BaseMethods {
453466

454467
return cy.get(selector)
455468
.invoke(attr, prop)
456-
.should('include', value)
469+
.should(isInclude? 'include' : 'not.include', value)
457470
}
458471

459472
public checkElementQuantity({
@@ -704,14 +717,25 @@ export class BaseMethods {
704717
public writeContentToFile({
705718
filePath,
706719
content,
707-
wait = 500
720+
wait = 500,
721+
contentFilePath
708722
}: {
709723
filePath: string,
710-
content: string
711-
wait?: number
724+
content?: string
725+
wait?: number,
726+
contentFilePath?: string
712727
}): void {
713-
writeTofile(filePath, content)
714-
cy.wait(wait)
728+
if(contentFilePath) {
729+
readFile(contentFilePath).then((file: string) => {
730+
writeTofile(filePath, file)
731+
cy.wait(wait)
732+
})
733+
}
734+
735+
if(content) {
736+
writeTofile(filePath, content)
737+
cy.wait(wait)
738+
}
715739
}
716740

717741
public fillField({
@@ -749,6 +773,24 @@ export class BaseMethods {
749773
cy.skipWhen(condition)
750774
}
751775

776+
public hoverElement({
777+
selector,
778+
text,
779+
wait = 0
780+
}: {
781+
selector: string,
782+
text?: string,
783+
wait?: number
784+
}): void {
785+
if (text) {
786+
cy.wait(wait).get(selector).contains(text).realHover()
787+
788+
return;
789+
}
790+
791+
cy.wait(wait).get(selector).realHover()
792+
}
793+
752794
public openLocalhost(number: number, path?: string): Cypress.Chainable<Cypress.AUTWindow> {
753795
return path ?
754796
cy.visit(`${Cypress.env(`localhost${number}`)}/${path}`)
@@ -825,6 +867,37 @@ export class BaseMethods {
825867
});
826868
}
827869

870+
public checkOutsideResourceUrl({
871+
parentSelector,
872+
selector,
873+
text,
874+
link,
875+
isInclude = true
876+
}: {
877+
parentSelector?: string,
878+
selector: string,
879+
text: string,
880+
link: string,
881+
isInclude?: boolean
882+
}): void {
883+
if(parentSelector) {
884+
this.clickElementWithText({
885+
parentSelector,
886+
selector,
887+
text,
888+
isTargetChanged: true
889+
})
890+
} else {
891+
this.clickElementWithText({
892+
selector,
893+
text,
894+
isTargetChanged: true
895+
})
896+
}
897+
this.checkUrlText(link, isInclude, true)
898+
}
899+
900+
828901
/*
829902
*---------------------------------------------------
830903
* PRIVATES SECTION

cypress/common/selectors.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ export const baseSelectors = {
4141
strong: 'strong',
4242
emphasis: 'em',
4343
appRoot: 'app-root',
44-
pre: 'pre'
44+
pre: 'pre',
45+
footer: 'footer'
4546
},
4647
ids: {
4748
app: '#app',
@@ -175,6 +176,9 @@ export const selectors = {
175176
},
176177
completeReactCaseApp: {
177178
toolTip: '.tool-tip',
179+
},
180+
nextJsHostReactRemoteApp: {
181+
linkCard: '[data-e2e="TEXTED_LINK_CARD"]'
178182
}
179183
}
180184

cypress/fixtures/commonTestData.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export class CommonTestData {
5151
appName: Constants.commonConstantsData.commonCountAppNames.app2
5252
}
5353
];
54+
public static readonly nextJsHostReactRemoteAppLinkName = Constants.commonPhrases.nextJsHostReactRemoteApp.messages.welcome.split('to')[1].trim()
5455
}
5556

5657
export function returnCommonDynamicAppsData(paragraphText: string[]) {

cypress/fixtures/constants.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ export class Constants {
66
app2: 'self-healing/app2/webpack.config.js',
77
},
88
serverSideRenderOnlyChangeFilePath: 'server-side-render-only/remoteServer/SharedComponent.js',
9+
nextJsHostReactRemoteApp: {
10+
files: {
11+
root: 'react-nextjs/nextjs-host-react-remote/host/pages/index.js',
12+
changedContent: 'react-nextjs/nextjs-host-react-remote/e2e/fixtures/changedContent.js',
13+
originalContent: 'react-nextjs/nextjs-host-react-remote/e2e/fixtures/originalContent.js'
14+
}
15+
},
916
}
1017

1118
public static readonly selectorParts = {
@@ -139,7 +146,10 @@ export class Constants {
139146
},
140147
helloWorldMessage: 'Hello World',
141148
commonVueAppComponentState: 'Remote Component in Action..',
142-
commonReactLink: 'https://reactjs.org'
149+
links: {
150+
react: 'https://reactjs.org',
151+
vercel: 'https://vercel.com'
152+
},
143153
}
144154

145155
public static readonly updatedConstantsData = {
@@ -845,6 +855,27 @@ export class Constants {
845855
intro: 'Hello Vite + federation! +1+2+3+4',
846856
edit: 'Edit App.tsx and save to test HMR updates.'
847857
}
858+
},
859+
nextJsHostReactRemoteApp: {
860+
messages: {
861+
welcome: 'Welcome to Next.js!',
862+
start: 'Get started by editing pages/index.js',
863+
remotes: {
864+
component: 'This component is from the Host React App hosted at localhost:8081',
865+
page: 'This is the Remote App'
866+
},
867+
engine: 'Powered by',
868+
footer: 'Scipt is only needed if you are not using the federation @ syntax when setting your remotes.',
869+
},
870+
linksCardsText: [
871+
'Documentation →Find in-depth information about Next.js features and API.',
872+
'Learn →Learn about Next.js in an interactive course with quizzes!',
873+
'Examples →Discover and deploy boilerplate example Next.js projects.',
874+
'Deploy →Instantly deploy your Next.js site to a public URL with Vercel.'
875+
],
876+
contents: {
877+
original: ''
878+
}
848879
}
849880
}
850881

@@ -885,7 +916,9 @@ export class Constants {
885916
lightGrey: 'rgb(239, 239, 239)',
886917
darkGrey: 'rgb(40, 44, 52)',
887918
darkSaturatedBlue: 'rgb(0, 0, 255)',
888-
mint: 'rgb(97, 218, 251)'
919+
mint: 'rgb(97, 218, 251)',
920+
skyBlue: 'rgb(0, 112, 243)',
921+
lightMint: 'rgb(95, 158, 160)'
889922
}
890923

891924
public static readonly hrefs = {
@@ -985,6 +1018,15 @@ export class Constants {
9851018
thirdPartyScriptsPostRequestPath: 'https://www.google-analytics.com/j/collect?**',
9861019
viteReactSimpleApp: {
9871020
viteLink: 'https://vitejs.dev/guide/features.html'
1021+
},
1022+
nextJsHostReactRemoteApp: {
1023+
nextJsLink: 'https://nextjs.org/',
1024+
cardsLinks: [
1025+
'https://nextjs.org/docs',
1026+
'https://nextjs.org/learn/foundations/about-nextjs',
1027+
'https://github.com/vercel/next.js/tree/canary/examples',
1028+
Constants.commonConstantsData.links.vercel
1029+
]
9881030
}
9891031
}
9901032
}

cypress/support/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
// }
3838

3939
import 'cypress-fill-command';
40+
import 'cypress-real-events';
4041
import 'cypress-wait-until';
4142

4243
declare global {

cypress/support/e2e.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,12 @@
1616
// Import commands.js using ES2015 syntax:
1717
import './commands'
1818
import '@shelex/cypress-allure-plugin';
19+
20+
Cypress.on('uncaught:exception', (err: Error) => {
21+
if (err.message.includes('cookie') || err.name.includes('cookie')) {
22+
return false
23+
}
24+
})
25+
1926
// Alternatively you can use CommonJS syntax:
2027
// require('./commands')

native-federation-react/e2e/tests/hostComponentChecks.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ describe('Native Federation React', () => {
9494
selector: baseSelectors.tags.coreElements.link,
9595
attr: Constants.commonConstantsData.commonAttributes.attr,
9696
prop: Constants.commonConstantsData.commonAttributes.href,
97-
value: Constants.commonConstantsData.commonReactLink,
97+
value: Constants.commonConstantsData.links.react,
9898
isMultiple: true
9999
})
100100
})

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
"./react-in-vue/*",
7373
"./react-nested-routers",
7474
"./react-nested-routers/*",
75+
"./react-nextjs/nextjs-host-react-remote",
76+
"./react-nextjs/nextjs-host-react-remote/*",
7577
"./react-nextjs/react-host-remote",
7678
"./react-nextjs/react-host-remote/*",
7779
"./redux-reducer-injection",
@@ -137,6 +139,7 @@
137139
"cross-spawn": "7.0.3",
138140
"cypress": "10",
139141
"cypress-fill-command": "1.0.2",
142+
"cypress-real-events": "1.7.6",
140143
"cypress-wait-until": "1.7.2",
141144
"forever": "4.0.3",
142145
"husky": "7.0.4",

react-nextjs/nextjs-host-react-remote/README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,14 @@ yarn start
2525
```
2626

2727
```bash
28-
npm run dev
29-
# or
30-
yarn dev
28+
yarn start
3129
```
3230

33-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
31+
Open [http://localhost:8080](http://localhost:8080) with your browser to see the result.
3432

3533
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
3634

37-
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
35+
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:8080/api/hello](http://localhost:8080/api/hello). This endpoint can be edited in `pages/api/hello.js`.
3836

3937
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
4038

0 commit comments

Comments
 (0)