describe('Authentication Flow', () => { it('shows login button when not authenticated', () => { cy.visit('/') cy.contains('登录').should('be.visible') }) it('opens login modal when clicking login', () => { cy.visit('/') cy.contains('登录').click() cy.get('[class*="overlay"], [class*="modal"], [class*="login"]').should('be.visible') }) it('login modal has username and password fields', () => { cy.visit('/') cy.contains('登录').click() cy.get('input[placeholder*="用户名"], input[type="text"]').should('exist') cy.get('input[type="password"]').should('exist') }) it('shows error for invalid login', () => { cy.visit('/') cy.contains('登录').click() // Try submitting with invalid credentials cy.get('input[placeholder*="用户名"], input[type="text"]').first().type('nonexistent_user_xyz') cy.get('input[type="password"]').first().type('wrongpassword') cy.contains('button', /登录|确定|提交/).click() // Should show error (alert, toast, or inline message) cy.wait(1000) // The modal should still be visible (login failed) cy.get('[class*="overlay"], [class*="modal"], [class*="login"]').should('exist') }) it('authenticated user sees their name in header', () => { const ADMIN_TOKEN = 'c86ae7afbe10fabe3c1d5e1a7fee74feaadfd5dc7be2ab62' cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('oil_auth_token', ADMIN_TOKEN) } }) cy.get('.app-header', { timeout: 8000 }).should('be.visible') cy.contains('Hera').should('be.visible') }) it('logout clears auth and shows login button', () => { const ADMIN_TOKEN = 'c86ae7afbe10fabe3c1d5e1a7fee74feaadfd5dc7be2ab62' cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('oil_auth_token', ADMIN_TOKEN) } }) cy.contains('Hera', { timeout: 8000 }).should('be.visible') // Click user name to open menu cy.contains('Hera').click() // Click logout cy.contains(/退出|登出|logout/i).click() // Should show login button again cy.contains('登录', { timeout: 5000 }).should('be.visible') }) it('token from URL param authenticates user', () => { const ADMIN_TOKEN = 'c86ae7afbe10fabe3c1d5e1a7fee74feaadfd5dc7be2ab62' cy.visit('/?token=' + ADMIN_TOKEN) // Should authenticate and show user name cy.contains('Hera', { timeout: 8000 }).should('be.visible') // Token should be removed from URL cy.url().should('not.include', 'token=') }) it('protected tabs become accessible after login', () => { const ADMIN_TOKEN = 'c86ae7afbe10fabe3c1d5e1a7fee74feaadfd5dc7be2ab62' cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('oil_auth_token', ADMIN_TOKEN) } }) cy.get('.nav-tab', { timeout: 10000 }).should('have.length.gte', 6) cy.get('.nav-tab').contains('管理配方').click() // Should navigate to manage page, not show login modal cy.url().should('include', '/manage') }) })