import { AuthTestUtils } from '../../support/auth-utils'; import { TestTool } from '../../support/page-utils'; import { BreadcrumbSelectors, PageSelectors, SidebarSelectors, SpaceSelectors } from '../../support/selectors'; import { generateRandomEmail, logAppFlowyEnvironment } from '../../support/test-config'; import { testLog } from '../../support/test-helpers'; describe('Breadcrumb Navigation Complete Tests', () => { let testEmail: string; before(() => { // Log environment configuration for debugging logAppFlowyEnvironment(); }); beforeEach(() => { // Generate unique test data for each test testEmail = generateRandomEmail(); // Handle uncaught exceptions cy.on('uncaught:exception', (err: Error) => { if (err.message.includes('No workspace or service found')) { return false; } // Handle View not found errors if (err.message.includes('View not found')) { return false; } return true; }); }); describe('Basic Navigation Tests', () => { it('should navigate through space and check for breadcrumb availability', () => { // // Login testLog.info('=== Step 1: Login ==='); cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load testLog.info('Waiting for app to fully load...'); cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); // Wait for pages to be ready PageSelectors.names().should('have.length.at.least', 1); testLog.info('App loaded successfully'); // Step 2: Expand first space testLog.info('=== Step 2: Expanding first space ==='); TestTool.expandSpace(0); // Wait for space to expand and pages to be visible PageSelectors.names().should('be.visible', { timeout: 10000 }); testLog.info('Expanded first space'); // Step 3: Navigate to first page testLog.info('=== Step 3: Navigating to first page ==='); PageSelectors.names().first().then($page => { const pageName = $page.text(); testLog.info(`Navigating to: ${pageName}`); cy.wrap($page).click(); }); // Wait for page to load cy.url().should('include', '/app/', { timeout: 10000 }); // Step 4: Check for breadcrumb navigation testLog.info('=== Step 4: Checking for breadcrumb navigation ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { testLog.info('✓ Breadcrumb navigation found on this page'); BreadcrumbSelectors.items().then($items => { testLog.info(`✓ Found ${$items.length} breadcrumb items`); }); } else { testLog.info('No breadcrumb navigation on this page (normal for top-level pages)'); } }); // Verify no errors cy.get('body').then($body => { const hasError = $body.text().includes('Error') || $body.text().includes('Failed'); if (!hasError) { testLog.info('✓ Navigation completed without errors'); } }); testLog.info('=== Basic navigation test completed ==='); }); }); it('should navigate to nested pages and use breadcrumb to go back', () => { // Login cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); // Wait for pages to be ready PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Expand first space ==='); TestTool.expandSpace(0); // Wait for space to expand and pages to be visible PageSelectors.names().should('be.visible', { timeout: 10000 }); testLog.info('=== Step 2: Navigate to first page ==='); PageSelectors.names().first().click(); // Wait for page to load cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for sidebar to update testLog.info('=== Step 3: Check for nested pages ==='); PageSelectors.names().then($pages => { testLog.info(`Found ${$pages.length} pages in sidebar`); // Find child pages by name const childPageNames = ['Desktop guide', 'Mobile guide', 'Web guide']; let childPageFound = false; for (let i = 0; i < $pages.length; i++) { const pageName = Cypress.$($pages[i]).text().trim(); if (childPageNames.includes(pageName)) { testLog.info(`Found child page: ${pageName}`); cy.wrap($pages[i]).click({ force: true }); childPageFound = true; break; } } if (!childPageFound && $pages.length > 1) { // Fallback: navigate to second page testLog.info('No known child page found, clicking second page as fallback'); cy.wrap($pages[1]).click({ force: true }); } // Wait for page to load cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Check for breadcrumb navigation testLog.info('=== Step 4: Testing breadcrumb navigation ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { testLog.info('✓ Breadcrumb navigation is visible'); BreadcrumbSelectors.items().should('have.length.at.least', 1); BreadcrumbSelectors.items().then($items => { if ($items.length > 1) { cy.wrap($items).first().click({ force: true }); testLog.info('✓ Clicked breadcrumb item to navigate back'); // Wait for navigation to complete cy.url().should('include', '/app/', { timeout: 10000 }); testLog.info('✓ Successfully used breadcrumb navigation'); } else { testLog.info('Only one breadcrumb item found'); } }); } else { testLog.info('No breadcrumb navigation on nested page'); } }); }); testLog.info('=== Nested navigation test completed ==='); }); }); }); describe('Full Breadcrumb Flow Test', () => { it('should navigate through General > Get Started > Desktop Guide flow (if available)', () => { // Login cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); // Wait for pages to be ready PageSelectors.names().should('have.length.at.least', 1); // Step 1: Find and expand General space or first space testLog.info('=== Step 1: Looking for General space ==='); SpaceSelectors.names().then($spaces => { const spaceNames = Array.from($spaces).map((el: Element) => el.textContent?.trim()); testLog.info(`Available spaces: ${spaceNames.join(', ')}`); // Find General space or use first const generalIndex = spaceNames.findIndex(name => name?.toLowerCase().includes('general') ); if (generalIndex !== -1) { testLog.info(`Found General space at index ${generalIndex}`); TestTool.expandSpace(generalIndex); } else { testLog.info('Using first available space'); TestTool.expandSpace(0); } }); // Wait for space to expand and pages to be visible PageSelectors.names().should('be.visible', { timeout: 10000 }); // Step 2: Look for Get Started page or use first page testLog.info('=== Step 2: Looking for Get Started page ==='); PageSelectors.names().then($pages => { const pageNames = Array.from($pages).map((el: Element) => el.textContent?.trim()); testLog.info(`Available pages: ${pageNames.join(', ')}`); // Find Get Started or similar page const getStartedPage = Array.from($pages).find((el: Element) => { const text = el.textContent?.trim().toLowerCase(); return text?.includes('get') || text?.includes('start') || text?.includes('welcome') || text?.includes('guide'); }); if (getStartedPage) { cy.wrap(getStartedPage).click(); testLog.info(`Clicked on: ${getStartedPage.textContent?.trim()}`); } else { PageSelectors.names().first().click(); testLog.info('Clicked first available page'); } }); // Wait for page to load cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for sidebar to update // Step 3: Look for Desktop Guide or sub-page testLog.info('=== Step 3: Looking for Desktop Guide or sub-pages ==='); PageSelectors.names().then($subPages => { const subPageNames = Array.from($subPages).map((el: Element) => el.textContent?.trim()); testLog.info(`Found pages: ${subPageNames.join(', ')}`); // Look for Desktop Guide or any guide const childPageNames = ['Desktop guide', 'Mobile guide', 'Web guide']; let guidePage = null; for (let i = 0; i < $subPages.length; i++) { const el = $subPages[i]; const text = el.textContent?.trim().toLowerCase(); if (text?.includes('desktop') || childPageNames.some(name => text.includes(name.toLowerCase()))) { guidePage = el; break; } } if (guidePage) { cy.wrap(guidePage).click({ force: true }); testLog.info(`Navigated to: ${guidePage.textContent?.trim()}`); } else if ($subPages.length > 1) { // Try to find a child page by name let childFound = false; for (let i = 0; i < $subPages.length; i++) { const pageName = Cypress.$($subPages[i]).text().trim(); if (childPageNames.includes(pageName)) { cy.wrap($subPages[i]).click({ force: true }); testLog.info(`Navigated to: ${pageName}`); childFound = true; break; } } if (!childFound) { cy.wrap($subPages[1]).click({ force: true }); testLog.info('Navigated to second page'); } } // Wait for page to load cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Step 4: Test breadcrumb navigation testLog.info('=== Step 4: Testing breadcrumb navigation ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { testLog.info('✓ Breadcrumb navigation is visible'); BreadcrumbSelectors.items().should('have.length.at.least', 1); BreadcrumbSelectors.items().then($items => { testLog.info(`Found ${$items.length} breadcrumb items`); if ($items.length > 1) { const targetIndex = Math.max(0, $items.length - 2); cy.wrap($items[targetIndex]).click({ force: true }); testLog.info(`✓ Clicked breadcrumb at index ${targetIndex} to go back`); // Wait for navigation to complete cy.url().should('include', '/app/', { timeout: 10000 }); testLog.info('✓ Successfully navigated back using breadcrumb'); } }); } else { testLog.info('Breadcrumb navigation not available on this page'); } }); }); // Final verification cy.get('body').then($body => { const hasError = $body.text().includes('Error') || $body.text().includes('Failed') || $body.find('[role="alert"]').length > 0; if (!hasError) { testLog.info('✓ Test completed without errors'); } }); testLog.info('=== Full breadcrumb flow test completed ==='); }); }); }); describe('Breadcrumb Item Verification Tests', () => { it('should verify breadcrumb items display correct names and are clickable', () => { cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Navigate to nested page ==='); TestTool.expandSpace(0); PageSelectors.names().should('be.visible', { timeout: 10000 }); // Navigate to first page PageSelectors.names().first().click(); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for sidebar to update // Navigate to nested page if available PageSelectors.names().then($pages => { // Find child pages by name const childPageNames = ['Desktop guide', 'Mobile guide', 'Web guide']; let childPageFound = false; for (let i = 0; i < $pages.length; i++) { const pageName = Cypress.$($pages[i]).text().trim(); if (childPageNames.includes(pageName)) { testLog.info(`Found child page: ${pageName}`); cy.wrap($pages[i]).click({ force: true }); childPageFound = true; break; } } if (!childPageFound && $pages.length > 1) { cy.wrap($pages[1]).click({ force: true }); } cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); testLog.info('=== Step 2: Verify breadcrumb items ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { BreadcrumbSelectors.items().then($items => { testLog.info(`Found ${$items.length} breadcrumb items`); // Verify each breadcrumb item has text $items.each((index, item) => { const $item = Cypress.$(item); const itemText = $item.text().trim(); testLog.info(`Breadcrumb ${index}: "${itemText}"`); expect(itemText).to.not.be.empty; }); // Verify last item is not clickable (should be disabled) if ($items.length > 0) { const lastItem = $items.last(); cy.wrap(lastItem).should('exist'); testLog.info('✓ Verified breadcrumb items structure'); } }); } else { testLog.info('No breadcrumb navigation available'); } }); }); }); }); it('should verify breadcrumb navigation updates correctly when navigating', () => { cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Navigate to parent page ==='); TestTool.expandSpace(0); PageSelectors.names().should('be.visible', { timeout: 10000 }); let parentPageName: string; PageSelectors.names().first().then($page => { parentPageName = $page.text().trim(); testLog.info(`Parent page: ${parentPageName}`); cy.wrap($page).click(); }); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for sidebar to update testLog.info('=== Step 2: Navigate to nested page ==='); PageSelectors.names().then($pages => { // Find child pages by name const childPageNames = ['Desktop guide', 'Mobile guide', 'Web guide']; let childPageFound = false; for (let i = 0; i < $pages.length; i++) { const pageName = Cypress.$($pages[i]).text().trim(); if (childPageNames.includes(pageName)) { testLog.info(`Found child page: ${pageName}`); cy.wrap($pages[i]).click({ force: true }); childPageFound = true; break; } } if (!childPageFound && $pages.length > 1) { cy.wrap($pages[1]).click({ force: true }); } cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); testLog.info('=== Step 3: Verify breadcrumb shows parent ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { BreadcrumbSelectors.items().then($items => { if ($items.length > 1) { // Verify parent page appears in breadcrumb const breadcrumbTexts = Array.from($items).map(el => Cypress.$(el).text().trim()); const hasParent = breadcrumbTexts.some(text => text.includes(parentPageName)); if (hasParent) { testLog.info('✓ Parent page found in breadcrumb'); } } }); } }); testLog.info('=== Step 4: Navigate back via breadcrumb ==='); BreadcrumbSelectors.items().then($items => { if ($items.length > 1) { // Click first breadcrumb (parent) cy.wrap($items).first().click({ force: true }); cy.url().should('include', '/app/', { timeout: 10000 }); testLog.info('✓ Successfully navigated back via breadcrumb'); } }); }); }); }); }); describe('Deep Navigation Tests', () => { it('should handle breadcrumb navigation for 3+ level deep pages', () => { cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Navigate to first level ==='); TestTool.expandSpace(0); PageSelectors.names().should('be.visible', { timeout: 10000 }); // Get initial page count let initialPageCount = 0; PageSelectors.names().then($pages => { initialPageCount = $pages.length; testLog.info(`Initial pages in sidebar: ${initialPageCount}`); }); // Click first page and wait for navigation PageSelectors.names().first().then($firstPage => { const firstPageName = $firstPage.text().trim(); testLog.info(`Clicking on first page: ${firstPageName}`); cy.wrap($firstPage).click(); }); cy.url().should('include', '/app/', { timeout: 10000 }); // Wait for page to load and sidebar to potentially update cy.wait(2000); testLog.info('Waiting for sidebar to update with nested pages...'); testLog.info('=== Step 2: Navigate to second level ==='); // Look for nested pages - they should be children of the first page // In the sidebar, nested pages appear after their parent when expanded PageSelectors.names().then($pages => { testLog.info(`Pages in sidebar after navigation: ${$pages.length}`); const pageNames = Array.from($pages).map((el: Element) => el.textContent?.trim()); testLog.info(`Available pages: ${pageNames.join(', ')}`); // Find "Desktop guide" or another child page (usually appears after "Getting started") // Children of "Getting started" are: Desktop guide, Mobile guide, Web guide const childPageNames = ['Desktop guide', 'Mobile guide', 'Web guide']; let childPageFound = false; for (let i = 0; i < $pages.length; i++) { const pageName = Cypress.$($pages[i]).text().trim(); if (childPageNames.includes(pageName)) { testLog.info(`Found child page: ${pageName} at index ${i}`); cy.wrap($pages[i]).click({ force: true }); childPageFound = true; break; } } if (!childPageFound && $pages.length > 1) { // Fallback: click second page if no known child found testLog.info('No known child page found, clicking second page as fallback'); cy.wrap($pages[1]).click({ force: true }); } cy.url().should('include', '/app/', { timeout: 10000 }); // Wait for sidebar to update again cy.wait(2000); testLog.info('Waiting for sidebar to update with third level pages...'); testLog.info('=== Step 3: Navigate to third level if available ==='); // Wait for third level pages to appear PageSelectors.names().should('exist', { timeout: 10000 }); PageSelectors.names().then($subPages => { testLog.info(`Pages in sidebar after second navigation: ${$subPages.length}`); const subPageNames = Array.from($subPages).map((el: Element) => el.textContent?.trim()); testLog.info(`Available sub-pages: ${subPageNames.join(', ')}`); // Try to find another nested page or click a different page if ($subPages.length > 2) { // Click a page that's different from what we've already clicked // Skip first two (Getting started and Desktop guide) and try third cy.wrap($subPages[2]).click({ force: true }); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for page to fully load testLog.info('=== Step 4: Verify breadcrumb shows all levels ==='); // Wait a bit more for breadcrumb to render cy.wait(1000); BreadcrumbSelectors.navigation().should('exist', { timeout: 10000 }).then($nav => { if ($nav.length > 0) { BreadcrumbSelectors.items().should('have.length.at.least', 1); BreadcrumbSelectors.items().then($items => { testLog.info(`Found ${$items.length} breadcrumb items (3+ levels deep)`); // Log breadcrumb item texts for debugging const breadcrumbTexts = Array.from($items).map(el => Cypress.$(el).text().trim()); testLog.info(`Breadcrumb items: ${breadcrumbTexts.join(' > ')}`); expect($items.length).to.be.at.least(2); // Verify we can navigate back through breadcrumbs if ($items.length > 2) { // Click second-to-last breadcrumb const targetIndex = $items.length - 2; testLog.info(`Clicking breadcrumb at index ${targetIndex} (${breadcrumbTexts[targetIndex]})`); cy.wrap($items[targetIndex]).click({ force: true }); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(1000); testLog.info('✓ Successfully navigated back from deep level'); } else { testLog.info(`Only ${$items.length} breadcrumb items found, expected at least 3 for deep navigation`); } }); } else { testLog.info('Breadcrumb not available for deep navigation'); } }); } else { testLog.info(`No third level pages available (found ${$subPages.length} pages)`); } }); }); }); }); }); describe('Breadcrumb After Page Creation Tests', () => { it('should show breadcrumb after creating a new nested page', () => { cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Navigate to a page ==='); TestTool.expandSpace(0); PageSelectors.names().should('be.visible', { timeout: 10000 }); PageSelectors.names().first().click(); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for page to load testLog.info('=== Step 2: Create a new nested page ==='); const newPageName = `Test Page ${Date.now()}`; // Create page using the new page button PageSelectors.newPageButton().should('be.visible').click(); cy.wait(1000); // Close any modals that might appear cy.get('body').then($body => { if ($body.find('[role="dialog"]').length > 0) { cy.get('body').type('{esc}'); cy.wait(500); } }); // Wait for page to be created and navigate to it cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for page to fully load // Set page title if title input is available (use force to bypass modal backdrop) PageSelectors.titleInput().then($titleInput => { if ($titleInput.length > 0) { cy.wrap($titleInput).first().click({ force: true }); cy.wait(500); cy.wrap($titleInput).first().type('{selectall}', { force: true }); cy.wrap($titleInput).first().type(newPageName, { force: true }); cy.wrap($titleInput).first().type('{enter}', { force: true }); cy.wait(1000); } }); testLog.info('=== Step 3: Verify breadcrumb appears for new page ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { testLog.info('✓ Breadcrumb navigation found after page creation'); BreadcrumbSelectors.items().should('have.length.at.least', 1); BreadcrumbSelectors.items().then($items => { testLog.info(`Found ${$items.length} breadcrumb items for new page`); // Verify we can navigate back if ($items.length > 1) { cy.wrap($items).first().click({ force: true }); cy.url().should('include', '/app/', { timeout: 10000 }); testLog.info('✓ Successfully navigated back from newly created page'); } }); } else { testLog.info('No breadcrumb navigation (page may be top-level)'); } }); }); }); }); describe('Breadcrumb Text Content Tests', () => { it('should verify breadcrumb items contain correct page names', () => { cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Navigate through pages and collect names ==='); TestTool.expandSpace(0); PageSelectors.names().should('be.visible', { timeout: 10000 }); const pageNames: string[] = []; PageSelectors.names().then($pages => { // Collect first 3 page names const maxPages = Math.min($pages.length, 3); for (let i = 0; i < maxPages; i++) { const pageName = Cypress.$($pages[i]).text().trim(); pageNames.push(pageName); } testLog.info(`Collected page names: ${pageNames.join(', ')}`); // Navigate to first page if (pageNames.length > 0) { cy.wrap($pages[0]).click(); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for sidebar to update // Find and navigate to nested page const childPageNames = ['Desktop guide', 'Mobile guide', 'Web guide']; let childFound = false; PageSelectors.names().then($subPages => { for (let i = 0; i < $subPages.length; i++) { const pageName = Cypress.$($subPages[i]).text().trim(); if (childPageNames.includes(pageName)) { cy.wrap($subPages[i]).click({ force: true }); childFound = true; break; } } if (!childFound && $subPages.length > 1) { cy.wrap($subPages[1]).click({ force: true }); } cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); testLog.info('=== Step 2: Verify breadcrumb contains page names ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { BreadcrumbSelectors.items().then($items => { const breadcrumbTexts = Array.from($items).map(el => Cypress.$(el).text().trim() ); testLog.info(`Breadcrumb texts: ${breadcrumbTexts.join(' > ')}`); // Verify parent page name appears in breadcrumb if (pageNames.length > 0 && breadcrumbTexts.length > 0) { const hasParentName = breadcrumbTexts.some(text => text.includes(pageNames[0]) ); if (hasParentName) { testLog.info('✓ Parent page name found in breadcrumb'); } } }); } }); }); } }); }); }); }); describe('Breadcrumb Edge Cases', () => { it('should handle breadcrumb when navigating between different spaces', () => { cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Navigate to first space ==='); TestTool.expandSpace(0); PageSelectors.names().should('be.visible', { timeout: 10000 }); PageSelectors.names().first().click(); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for sidebar to update testLog.info('=== Step 2: Check breadcrumb state ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length > 0) { BreadcrumbSelectors.items().then($items => { testLog.info(`Breadcrumb items before navigation: ${$items.length}`); // Navigate to nested page PageSelectors.names().then($pages => { // Find child pages by name const childPageNames = ['Desktop guide', 'Mobile guide', 'Web guide']; let childFound = false; for (let i = 0; i < $pages.length; i++) { const pageName = Cypress.$($pages[i]).text().trim(); if (childPageNames.includes(pageName)) { cy.wrap($pages[i]).click({ force: true }); childFound = true; break; } } if (!childFound && $pages.length > 1) { cy.wrap($pages[1]).click({ force: true }); } cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Verify breadcrumb updates BreadcrumbSelectors.items().then($newItems => { testLog.info(`Breadcrumb items after navigation: ${$newItems.length}`); if ($newItems.length > $items.length) { testLog.info('✓ Breadcrumb updated correctly after navigation'); } }); }); }); } }); }); }); it('should verify breadcrumb does not appear on top-level pages', () => { cy.visit('/login', { failOnStatusCode: false }); cy.get('body').should('be.visible'); const authUtils = new AuthTestUtils(); authUtils.signInWithTestUrl(testEmail).then(() => { cy.url().should('include', '/app'); // Wait for app to load cy.get('body', { timeout: 30000 }).should('not.contain', 'Welcome!'); SidebarSelectors.pageHeader().should('be.visible', { timeout: 30000 }); PageSelectors.names().should('exist', { timeout: 30000 }); PageSelectors.names().should('have.length.at.least', 1); testLog.info('=== Step 1: Navigate to top-level page ==='); TestTool.expandSpace(0); PageSelectors.names().should('be.visible', { timeout: 10000 }); // Click first page (likely top-level) PageSelectors.names().first().click(); cy.url().should('include', '/app/', { timeout: 10000 }); cy.wait(2000); // Wait for page to load testLog.info('=== Step 2: Verify breadcrumb behavior on top-level page ==='); BreadcrumbSelectors.navigation().then($nav => { if ($nav.length === 0) { testLog.info('✓ No breadcrumb on top-level page (expected behavior)'); } else { BreadcrumbSelectors.items().then($items => { testLog.info(`Found ${$items.length} breadcrumb items on top-level page`); // Top-level pages may or may not have breadcrumbs depending on structure }); } }); }); }); }); });