All checks were successful
PR Preview / test (pull_request) Has been skipped
Deploy Production / test (push) Successful in 6s
PR Preview / teardown-preview (pull_request) Successful in 14s
PR Preview / deploy-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 6s
Test / build-check (push) Successful in 3s
Deploy Production / deploy (push) Successful in 8s
Test / e2e-test (push) Successful in 3m4s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
138 lines
4.8 KiB
JavaScript
138 lines
4.8 KiB
JavaScript
describe('Kit Export Feature', () => {
|
|
let adminToken
|
|
let authHeaders
|
|
|
|
before(() => {
|
|
cy.getAdminToken().then(token => {
|
|
adminToken = token
|
|
authHeaders = { Authorization: `Bearer ${token}` }
|
|
})
|
|
})
|
|
|
|
describe('API: recipes and oils available', () => {
|
|
it('loads oils list', () => {
|
|
cy.request({ url: '/api/oils', headers: authHeaders }).then(res => {
|
|
expect(res.status).to.eq(200)
|
|
expect(res.body).to.be.an('array')
|
|
expect(res.body.length).to.be.greaterThan(50)
|
|
})
|
|
})
|
|
|
|
it('loads recipes list', () => {
|
|
cy.request({ url: '/api/recipes', headers: authHeaders }).then(res => {
|
|
expect(res.status).to.eq(200)
|
|
expect(res.body).to.be.an('array')
|
|
expect(res.body.length).to.be.greaterThan(10)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('UI: Projects page access', () => {
|
|
it('shows login prompt when not logged in', () => {
|
|
cy.visit('/projects')
|
|
cy.contains('登录', { timeout: 10000 }).should('be.visible')
|
|
})
|
|
|
|
it('shows kit compare button when logged in as admin', () => {
|
|
cy.visit('/projects', {
|
|
onBeforeLoad(win) { win.localStorage.setItem('oil_auth_token', adminToken) }
|
|
})
|
|
cy.contains('套装方案对比', { timeout: 10000 }).should('be.visible')
|
|
})
|
|
})
|
|
|
|
describe('UI: Kit Export page', () => {
|
|
beforeEach(() => {
|
|
cy.visit('/kit-export', {
|
|
onBeforeLoad(win) { win.localStorage.setItem('oil_auth_token', adminToken) }
|
|
})
|
|
})
|
|
|
|
it('loads with 4 kit cards', () => {
|
|
cy.get('.kit-card', { timeout: 10000 }).should('have.length', 4)
|
|
})
|
|
|
|
it('shows kit names and prices', () => {
|
|
cy.contains('芳香调理套装').should('be.visible')
|
|
cy.contains('家庭医生套装').should('be.visible')
|
|
cy.contains('居家呵护套装').should('be.visible')
|
|
cy.contains('全精油套装').should('be.visible')
|
|
cy.contains('¥1575').should('be.visible')
|
|
cy.contains('¥2250').should('be.visible')
|
|
cy.contains('¥3988').should('be.visible')
|
|
cy.contains('¥17700').should('be.visible')
|
|
})
|
|
|
|
it('shows recipe count for each kit', () => {
|
|
cy.get('.kit-recipe-count').should('have.length', 4)
|
|
cy.get('.kit-recipe-count').each($el => {
|
|
expect($el.text()).to.match(/可做 \d+ 个配方/)
|
|
})
|
|
})
|
|
|
|
it('clicking a kit card shows its recipes', () => {
|
|
cy.get('.kit-card').eq(1).click()
|
|
cy.get('.kit-detail', { timeout: 5000 }).should('be.visible')
|
|
cy.get('.recipe-table').should('exist')
|
|
})
|
|
|
|
it('recipe table has cost and profit columns', () => {
|
|
cy.get('.kit-card').first().click()
|
|
cy.get('.recipe-table', { timeout: 5000 }).within(() => {
|
|
cy.contains('th', '套装成本').should('exist')
|
|
cy.contains('th', '单买成本').should('exist')
|
|
cy.contains('th', '售价').should('exist')
|
|
cy.contains('th', '利润率').should('exist')
|
|
cy.contains('th', '可做次数').should('exist')
|
|
})
|
|
})
|
|
|
|
it('shows cross comparison section', () => {
|
|
cy.get('.cross-section', { timeout: 10000 }).should('be.visible')
|
|
cy.get('.cross-table').should('exist')
|
|
})
|
|
|
|
it('cross comparison has single-buy column', () => {
|
|
cy.get('.cross-table', { timeout: 10000 }).within(() => {
|
|
cy.contains('th', '单买').should('exist')
|
|
})
|
|
})
|
|
|
|
it('cross comparison shows staircase pattern (available cells have green bg)', () => {
|
|
cy.get('.td-kit-available', { timeout: 10000 }).should('have.length.greaterThan', 0)
|
|
cy.get('.td-kit-na').should('have.length.greaterThan', 0)
|
|
})
|
|
|
|
it('kit cost is always <= original cost in recipe table', () => {
|
|
cy.get('.kit-card').first().click()
|
|
cy.get('.recipe-table tbody tr', { timeout: 5000 }).each($row => {
|
|
const cells = $row.find('td')
|
|
// td[1] = 可做次数, td[2] = 套装成本, td[3] = 单买成本
|
|
const kitCostText = cells.eq(2).text().replace(/[¥,\s]/g, '')
|
|
const origCostText = cells.eq(3).text().replace(/[¥,\s]/g, '')
|
|
const kitCost = parseFloat(kitCostText)
|
|
const origCost = parseFloat(origCostText)
|
|
if (!isNaN(kitCost) && !isNaN(origCost)) {
|
|
expect(kitCost).to.be.at.most(origCost + 0.01)
|
|
}
|
|
})
|
|
})
|
|
|
|
it('export buttons exist', () => {
|
|
cy.contains('button', '导出完整版').should('be.visible')
|
|
cy.contains('button', '导出简版').should('be.visible')
|
|
})
|
|
|
|
it('shows volume info next to recipe name', () => {
|
|
cy.get('.td-volume', { timeout: 10000 }).should('have.length.greaterThan', 0)
|
|
})
|
|
})
|
|
|
|
describe('UI: Kit Export access control', () => {
|
|
it('redirects to /projects when not logged in', () => {
|
|
cy.visit('/kit-export')
|
|
cy.url({ timeout: 10000 }).should('include', '/projects')
|
|
})
|
|
})
|
|
})
|