Files
oil-formula-calculator/frontend/cypress/e2e/auth-flow.cy.js
Hera Zhao ee8ec23dc7 Refactor frontend to Vue 3 + Vite + Pinia + Cypress E2E
- Replace single-file 8441-line HTML with Vue 3 SPA
- Pinia stores: auth, oils, recipes, diary, ui
- Composables: useApi, useDialog, useSmartPaste, useOilTranslation
- 6 shared components: RecipeCard, RecipeDetailOverlay, TagPicker, etc.
- 9 page views: RecipeSearch, RecipeManager, Inventory, OilReference, etc.
- 14 Cypress E2E test specs (113 tests), all passing
- Multi-stage Dockerfile (Node build + Python runtime)
- Demo video generation scripts (TTS + subtitles + screen recording)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:35:00 +00:00

82 lines
3.0 KiB
JavaScript

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')
})
})