describe('Navigation & Routing', () => { beforeEach(() => { cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000)) } }) cy.get('header').should('be.visible') }) it('default tab is 随手记', () => { cy.get('.tab-btn').contains('随手记').should('have.class', 'active') cy.url().should('eq', Cypress.config('baseUrl') + '/') }) it('clicking tab navigates to correct route', () => { const tabs = [ { label: '待办', path: '/tasks' }, { label: '提醒', path: '/reminders' }, { label: '身体', path: '/body' }, { label: '音乐', path: '/music' }, { label: '文档', path: '/docs' }, { label: '日程', path: '/planning' }, { label: '随手记', path: '/' }, ] tabs.forEach(({ label, path }) => { cy.get('.tab-btn').contains(label).click() cy.url().should('include', path === '/' ? Cypress.config('baseUrl') : path) cy.get('.tab-btn').contains(label).should('have.class', 'active') }) }) it('direct URL access works for each route', () => { const routes = ['/tasks', '/reminders', '/body', '/music', '/docs', '/planning'] routes.forEach(route => { cy.visit(route, { onBeforeLoad(win) { win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000)) } }) cy.get('header').should('be.visible') }) }) it('back button works between tabs', () => { cy.get('.tab-btn').contains('待办').click() cy.url().should('include', '/tasks') cy.get('.tab-btn').contains('提醒').click() cy.url().should('include', '/reminders') cy.go('back') cy.url().should('include', '/tasks') }) it('unknown route still renders the app (SPA fallback)', () => { cy.visit('/nonexistent', { onBeforeLoad(win) { win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000)) } }) cy.get('header').should('be.visible') }) it('sleep buddy route works', () => { cy.visit('/sleep-buddy', { onBeforeLoad(win) { win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000)) } }) cy.contains('睡眠打卡').should('be.visible') }) })