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:
99
frontend/cypress/e2e/bug-tracker-flow.cy.js
Normal file
99
frontend/cypress/e2e/bug-tracker-flow.cy.js
Normal file
@@ -0,0 +1,99 @@
|
||||
describe('Bug Tracker Flow', () => {
|
||||
const ADMIN_TOKEN = 'c86ae7afbe10fabe3c1d5e1a7fee74feaadfd5dc7be2ab62'
|
||||
const authHeaders = { Authorization: `Bearer ${ADMIN_TOKEN}` }
|
||||
const TEST_CONTENT = 'Cypress_E2E_Bug_测试缺陷_' + Date.now()
|
||||
let testBugId = null
|
||||
|
||||
describe('API: bug lifecycle', () => {
|
||||
it('submits a new bug via API', () => {
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: '/api/bug-report',
|
||||
headers: authHeaders,
|
||||
body: { content: TEST_CONTENT, priority: 2 }
|
||||
}).then(res => {
|
||||
expect(res.status).to.be.oneOf([200, 201])
|
||||
})
|
||||
})
|
||||
|
||||
it('verifies the bug appears in the list', () => {
|
||||
cy.request({ url: '/api/bug-reports', headers: authHeaders }).then(res => {
|
||||
expect(res.body).to.be.an('array')
|
||||
const found = res.body.find(b => b.content && b.content.includes('Cypress_E2E_Bug'))
|
||||
expect(found).to.exist
|
||||
testBugId = found.id
|
||||
})
|
||||
})
|
||||
|
||||
it('updates bug status to testing', () => {
|
||||
cy.request({ url: '/api/bug-reports', headers: authHeaders }).then(res => {
|
||||
const found = res.body.find(b => b.content && b.content.includes('Cypress_E2E_Bug'))
|
||||
testBugId = found.id
|
||||
cy.request({
|
||||
method: 'PUT',
|
||||
url: `/api/bug-reports/${testBugId}`,
|
||||
headers: authHeaders,
|
||||
body: { status: 1, note: 'E2E test status change' }
|
||||
}).then(r => expect(r.status).to.eq(200))
|
||||
})
|
||||
})
|
||||
|
||||
it('verifies status was updated', () => {
|
||||
cy.request({ url: '/api/bug-reports', headers: authHeaders }).then(res => {
|
||||
const found = res.body.find(b => b.content && b.content.includes('Cypress_E2E_Bug'))
|
||||
expect(found.is_resolved).to.eq(1)
|
||||
})
|
||||
})
|
||||
|
||||
// NOTE: POST /api/bug-reports/{id}/comment has a backend bug — the decorator
|
||||
// is stacked on delete_bug function, so POST to /comment actually deletes the bug.
|
||||
// Skipping comment tests until backend is fixed.
|
||||
it('bug has auto-generated creation comment', () => {
|
||||
cy.request({ url: '/api/bug-reports', headers: authHeaders }).then(res => {
|
||||
const found = res.body.find(b => b.content && b.content.includes('Cypress_E2E_Bug'))
|
||||
expect(found).to.exist
|
||||
expect(found.comments).to.be.an('array')
|
||||
expect(found.comments.length).to.be.gte(1) // auto creation log
|
||||
})
|
||||
})
|
||||
|
||||
it('deletes the test bug', () => {
|
||||
cy.request({ url: '/api/bug-reports', headers: authHeaders }).then(res => {
|
||||
const found = res.body.find(b => b.content && b.content.includes('Cypress_E2E_Bug'))
|
||||
if (found) {
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: `/api/bug-reports/${found.id}`,
|
||||
headers: authHeaders
|
||||
}).then(r => expect(r.status).to.eq(200))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('verifies the bug is deleted', () => {
|
||||
cy.request({ url: '/api/bug-reports', headers: authHeaders }).then(res => {
|
||||
const found = res.body.find(b => b.content && b.content.includes('Cypress_E2E_Bug'))
|
||||
expect(found).to.not.exist
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('UI: bugs page', () => {
|
||||
it('visits /bugs and page renders', () => {
|
||||
cy.visit('/bugs', {
|
||||
onBeforeLoad(win) { win.localStorage.setItem('oil_auth_token', ADMIN_TOKEN) }
|
||||
})
|
||||
cy.contains('Bug', { timeout: 10000 }).should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
after(() => {
|
||||
cy.request({ url: '/api/bug-reports', headers: authHeaders, failOnStatusCode: false }).then(res => {
|
||||
if (res.status === 200 && Array.isArray(res.body)) {
|
||||
res.body.filter(b => b.content && b.content.includes('Cypress_E2E_Bug')).forEach(bug => {
|
||||
cy.request({ method: 'DELETE', url: `/api/bug-reports/${bug.id}`, headers: authHeaders, failOnStatusCode: false })
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user