Add comprehensive test suite: 105 unit + 167 E2E tests
- Vitest unit tests: smart paste parsing (37), cost calculations (21),
oil translation (16), dialog system (12), with production data fixtures
- Cypress E2E tests: API CRUD (27), auth flow (8), recipe detail (10),
search (12), oil reference (4), favorites (6), inventory (6),
recipe management (10), diary (11), bug tracker (8), user management (13),
cost parity (6), data integrity (8), responsive (9), performance (6),
navigation (8), admin flow (5)
- Test coverage doc with prioritized gap analysis
- Found backend bug: POST /api/bug-reports/{id}/comment deletes the bug
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
101
frontend/cypress/e2e/manage-recipes.cy.js
Normal file
101
frontend/cypress/e2e/manage-recipes.cy.js
Normal file
@@ -0,0 +1,101 @@
|
||||
describe('Manage Recipes Page', () => {
|
||||
const ADMIN_TOKEN = 'c86ae7afbe10fabe3c1d5e1a7fee74feaadfd5dc7be2ab62'
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('/manage', {
|
||||
onBeforeLoad(win) {
|
||||
win.localStorage.setItem('oil_auth_token', ADMIN_TOKEN)
|
||||
}
|
||||
})
|
||||
// Wait for the recipe manager to load
|
||||
cy.get('.recipe-manager', { timeout: 10000 }).should('exist')
|
||||
})
|
||||
|
||||
it('loads and shows recipe lists', () => {
|
||||
// Should show public recipes section with at least some recipes
|
||||
cy.contains('公共配方库').should('be.visible')
|
||||
cy.get('.recipe-row').should('have.length.gte', 1)
|
||||
})
|
||||
|
||||
it('search box filters recipes', () => {
|
||||
cy.get('.recipe-row').then($rows => {
|
||||
const initialCount = $rows.length
|
||||
// Type a search term
|
||||
cy.get('.manage-toolbar .search-input').type('薰衣草')
|
||||
cy.wait(500)
|
||||
// Filtered count should be different (fewer or equal)
|
||||
cy.get('.recipe-row').should('have.length.lte', initialCount)
|
||||
})
|
||||
})
|
||||
|
||||
it('clearing search restores all recipes', () => {
|
||||
cy.get('.manage-toolbar .search-input').type('薰衣草')
|
||||
cy.wait(500)
|
||||
cy.get('.recipe-row').then($filtered => {
|
||||
const filteredCount = $filtered.length
|
||||
cy.get('.manage-toolbar .search-input').clear()
|
||||
cy.wait(500)
|
||||
cy.get('.recipe-row').should('have.length.gte', filteredCount)
|
||||
})
|
||||
})
|
||||
|
||||
it('can click a recipe to open the editor overlay', () => {
|
||||
// Click the row-info area (which triggers editRecipe)
|
||||
cy.get('.recipe-row .row-info').first().click()
|
||||
// Editor overlay should appear
|
||||
cy.get('.overlay-panel', { timeout: 5000 }).should('be.visible')
|
||||
cy.contains('编辑配方').should('be.visible')
|
||||
// Should have form fields
|
||||
cy.get('.form-group').should('have.length.gte', 1)
|
||||
})
|
||||
|
||||
it('editor shows ingredients table with oil selects', () => {
|
||||
cy.get('.recipe-row .row-info').first().click()
|
||||
cy.get('.overlay-panel', { timeout: 5000 }).should('be.visible')
|
||||
// Ingredients section should have rows with select dropdowns
|
||||
cy.get('.overlay-panel .ing-row').should('have.length.gte', 1)
|
||||
cy.get('.overlay-panel .form-select').should('have.length.gte', 1)
|
||||
cy.get('.overlay-panel .form-input-sm').should('have.length.gte', 1)
|
||||
})
|
||||
|
||||
it('can close the editor overlay', () => {
|
||||
cy.get('.recipe-row .row-info').first().click()
|
||||
cy.get('.overlay-panel', { timeout: 5000 }).should('be.visible')
|
||||
// Close via the close button
|
||||
cy.get('.overlay-panel .btn-close').click()
|
||||
cy.get('.overlay-panel').should('not.exist')
|
||||
})
|
||||
|
||||
it('can close the editor with cancel button', () => {
|
||||
cy.get('.recipe-row .row-info').first().click()
|
||||
cy.get('.overlay-panel', { timeout: 5000 }).should('be.visible')
|
||||
cy.get('.overlay-panel').contains('取消').click()
|
||||
cy.get('.overlay-panel').should('not.exist')
|
||||
})
|
||||
|
||||
it('tag filter bar toggles', () => {
|
||||
// Look for any tag-related toggle button
|
||||
cy.get('body').then($body => {
|
||||
const hasToggle = $body.find('.tag-toggle-btn, [class*="tag-filter"] button, button:contains("标签")').length > 0
|
||||
if (hasToggle) {
|
||||
cy.get('.tag-toggle-btn, [class*="tag-filter"] button, button').contains('标签').first().click()
|
||||
cy.wait(500)
|
||||
// Tag area should exist after toggle
|
||||
cy.get('[class*="tag"]').should('exist')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('shows recipe cost in each row', () => {
|
||||
cy.get('.row-cost').first().should('not.be.empty')
|
||||
cy.get('.row-cost').first().invoke('text').should('contain', '¥')
|
||||
})
|
||||
|
||||
it('has add recipe button that opens overlay', () => {
|
||||
cy.get('.manage-toolbar').contains('添加配方').click()
|
||||
cy.get('.overlay-panel', { timeout: 5000 }).should('be.visible')
|
||||
cy.contains('添加配方').should('be.visible')
|
||||
// Close it
|
||||
cy.get('.overlay-panel .btn-close').click()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user