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