test(nested-params): adding extra coverage for deeply nested routing

This commit is contained in:
ShaneK
2026-03-10 13:20:51 -07:00
parent a864822477
commit 6a681e480a
2 changed files with 163 additions and 0 deletions

View File

@@ -63,6 +63,7 @@ const UserLayout: React.FC = () => {
<Route index element={<Navigate to="details" replace />} />
<Route path="details" element={<UserDetails />} />
<Route path="settings" element={<UserSettings />} />
<Route path="profile/*" element={<ProfileLayout />} />
</IonRouterOutlet>
</IonContent>
</IonPage>
@@ -84,6 +85,79 @@ const UserDetails: React.FC = () => {
<IonButton routerLink={`/nested-params/user/${userId}/settings`} id="go-to-settings">
Go to Settings
</IonButton>
<IonButton routerLink={`/nested-params/user/${userId}/profile/edit`} id="go-to-profile-edit">
Go to Profile Edit
</IonButton>
</IonContent>
</IonPage>
);
};
/**
* Deeply nested layout: /nested-params/user/:userId/profile/*
* This tests 4 levels of outlet nesting with relative paths to validate
* that derivePathnameToMatch correctly handles depth > 2 parent segments.
*/
const ProfileLayout: React.FC = () => {
const { userId } = useParams<{ userId: string }>();
return (
<IonPage data-pageid="nested-params-profile-layout">
<IonHeader>
<IonToolbar>
<IonTitle>Profile Layout</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonLabel data-testid="profile-layout-param">Profile layout user: {userId ?? 'missing'}</IonLabel>
<IonRouterOutlet ionPage id="nested-params-profile-outlet">
<Route index element={<Navigate to="edit" replace />} />
<Route path="edit" element={<ProfileEdit />} />
<Route path="view" element={<ProfileView />} />
</IonRouterOutlet>
</IonContent>
</IonPage>
);
};
const ProfileEdit: React.FC = () => {
const { userId } = useParams<{ userId: string }>();
return (
<IonPage data-pageid="nested-params-profile-edit">
<IonHeader>
<IonToolbar>
<IonTitle>Profile Edit</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonLabel data-testid="profile-edit-param">Profile edit user: {userId ?? 'missing'}</IonLabel>
<IonButton routerLink={`/nested-params/user/${userId}/profile/view`} id="go-to-profile-view">
Go to Profile View
</IonButton>
<IonButton routerLink={`/nested-params/user/${userId}/details`} id="back-to-details">
Back to Details
</IonButton>
</IonContent>
</IonPage>
);
};
const ProfileView: React.FC = () => {
const { userId } = useParams<{ userId: string }>();
return (
<IonPage data-pageid="nested-params-profile-view">
<IonHeader>
<IonToolbar>
<IonTitle>Profile View</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonLabel data-testid="profile-view-param">Profile view user: {userId ?? 'missing'}</IonLabel>
<IonButton routerLink={`/nested-params/user/${userId}/profile/edit`} id="back-to-profile-edit">
Back to Profile Edit
</IonButton>
</IonContent>
</IonPage>
);

View File

@@ -222,6 +222,95 @@ describe('Nested Params', () => {
});
});
/**
* Deep nesting tests (4 levels) to validate derivePathnameToMatch
* handles relative paths correctly at depth > 2 parent segments.
*
* Route structure:
* /nested-params/* (App level)
* user/:userId/* (NestedParamsRoot outlet)
* details (UserLayout outlet)
* settings (UserLayout outlet)
* profile/* (UserLayout outlet)
* edit (ProfileLayout outlet - 4th level)
* view (ProfileLayout outlet - 4th level)
*/
it('/nested-params > Deep nesting > Navigate to profile edit (4 levels deep)', () => {
cy.visit(`http://localhost:${port}/nested-params`);
cy.ionPageVisible('nested-params-landing');
// Navigate to user 42 details
cy.get('#go-to-user-42').click();
cy.get('[data-testid="user-details-param"]').should('contain', 'Details view user: 42');
// Navigate to profile edit (4th level)
cy.get('#go-to-profile-edit').click();
cy.get('[data-testid="profile-layout-param"]').should('contain', 'Profile layout user: 42');
cy.get('[data-testid="profile-edit-param"]').should('contain', 'Profile edit user: 42');
cy.location('pathname').should('eq', '/nested-params/user/42/profile/edit');
});
it('/nested-params > Deep nesting > Direct navigation to 4th level route', () => {
// Navigate directly to a deeply nested route
cy.visit(`http://localhost:${port}/nested-params/user/42/profile/edit`);
cy.get('[data-testid="profile-layout-param"]').should('contain', 'Profile layout user: 42');
cy.get('[data-testid="profile-edit-param"]').should('contain', 'Profile edit user: 42');
});
it('/nested-params > Deep nesting > Navigate between 4th level siblings (edit <-> view)', () => {
cy.visit(`http://localhost:${port}/nested-params/user/42/profile/edit`);
cy.get('[data-testid="profile-edit-param"]').should('contain', 'Profile edit user: 42');
// Navigate to profile view (sibling at 4th level)
cy.get('#go-to-profile-view').click();
cy.get('[data-testid="profile-view-param"]').should('contain', 'Profile view user: 42');
cy.location('pathname').should('eq', '/nested-params/user/42/profile/view');
// Navigate back to profile edit
cy.get('#back-to-profile-edit').click();
cy.get('[data-testid="profile-edit-param"]').should('contain', 'Profile edit user: 42');
cy.location('pathname').should('eq', '/nested-params/user/42/profile/edit');
});
it('/nested-params > Deep nesting > Back navigation from 4th level to root', () => {
cy.visit(`http://localhost:${port}/`);
cy.ionPageVisible('home');
// Navigate to nested-params
cy.contains('ion-item', 'Nested Params').click();
cy.ionPageVisible('nested-params-landing');
// Navigate to user 42 details
cy.get('#go-to-user-42').click();
cy.get('[data-testid="user-details-param"]').should('contain', 'Details view user: 42');
// Navigate to profile edit (4th level)
cy.get('#go-to-profile-edit').click();
cy.get('[data-testid="profile-edit-param"]').should('contain', 'Profile edit user: 42');
// Navigate to profile view (sibling at 4th level)
cy.get('#go-to-profile-view').click();
cy.get('[data-testid="profile-view-param"]').should('contain', 'Profile view user: 42');
// Browser back: view -> edit
cy.go('back');
cy.get('[data-testid="profile-edit-param"]').should('contain', 'Profile edit user: 42');
// Browser back: edit -> details
cy.go('back');
cy.get('[data-testid="user-details-param"]').should('contain', 'Details view user: 42');
// Browser back: details -> landing
cy.go('back');
cy.ionPageVisible('nested-params-landing');
// Browser back: landing -> home
cy.go('back');
cy.ionPageVisible('home');
});
it('/nested-params > Sibling route transitions > No nested scrollbars during transition', () => {
// Start directly on the details page
cy.visit(`http://localhost:${port}/nested-params/user/99/details`);