describe('Authentication Flow', () => { it('redirects to login when session expired', () => { cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('sp_login_expires', String(Date.now() - 1000)) } }) cy.get('.login-overlay').should('be.visible') }) it('login form accepts Enter key', () => { cy.visit('/') cy.get('.login-input').type('123456{enter}') // Should attempt login (success or fail depends on backend) cy.wait(500) }) it('valid login stores session and shows app', () => { cy.visit('/') cy.get('.login-input').type('123456') cy.get('.login-btn').click() // If default password matches, should show main app cy.get('header', { timeout: 5000 }).should('be.visible') cy.window().then(win => { expect(win.localStorage.getItem('sp_login_expires')).to.not.be.null }) }) it('logout clears session and shows login', () => { cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000)) } }) cy.get('header').should('be.visible') cy.get('.header-menu-btn').click() cy.contains('退出登录').click() cy.get('.login-overlay').should('be.visible') cy.window().then(win => { expect(win.localStorage.getItem('sp_login_expires')).to.be.null }) }) it('session persists across page reloads', () => { cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000)) } }) cy.get('header').should('be.visible') cy.reload() cy.get('header').should('be.visible') cy.get('.login-overlay').should('not.exist') }) })