describe('Favorites System', () => { let adminToken let authHeaders before(() => { cy.getAdminToken().then(token => { adminToken = token authHeaders = { Authorization: `Bearer ${token}` } }) }) describe('API Level', () => { let firstRecipeId before(() => { cy.getAdminToken().then(token => { cy.request({ url: '/api/recipes', headers: { Authorization: `Bearer ${token}` } }).then(res => { if (res.body.length > 0) { firstRecipeId = res.body[0].id } }) }) }) it('can add a favorite via API', () => { if (!firstRecipeId) return // skip if no recipes cy.request({ method: 'POST', url: `/api/favorites/${firstRecipeId}`, headers: authHeaders, body: {} }).then(res => { expect(res.status).to.be.oneOf([200, 201]) }) }) it('lists the favorite', () => { if (!firstRecipeId) return cy.request({ url: '/api/favorites', headers: authHeaders }).then(res => { expect(res.body).to.include(firstRecipeId) }) }) it('can remove the favorite via API', () => { if (!firstRecipeId) return cy.request({ method: 'DELETE', url: `/api/favorites/${firstRecipeId}`, headers: authHeaders }).then(res => { expect(res.status).to.eq(200) }) }) it('favorite is removed from list', () => { if (!firstRecipeId) return cy.request({ url: '/api/favorites', headers: authHeaders }).then(res => { expect(res.body).to.not.include(firstRecipeId) }) }) }) describe('UI Level', () => { it('recipe cards have favorite buttons for logged-in users', () => { cy.visit('/', { onBeforeLoad(win) { win.localStorage.setItem('oil_auth_token', adminToken) } }) cy.get('.recipe-card', { timeout: 10000 }).should('have.length.gte', 1) // Fav button should be present on cards cy.get('.fav-btn').first().should('exist') }) }) })