Some checks failed
- Backend: FastAPI + SQLite (WAL mode), 22 tables, ~40 API endpoints - Frontend: Vue 3 + Vite + Pinia + Vue Router, 8 views, 3 stores - Database: migrate from JSON file to SQLite with proper schema - Dockerfile: multi-stage build (node + python) - Deploy: K8s manifests (namespace, deployment, service, ingress, pvc, backup) - CI/CD: Gitea Actions (test, deploy, PR preview at pr-$id.planner.oci.euphon.net) - Tests: 20 Cypress E2E test files, 196 test cases, ~85% coverage - Doc: test-coverage.md with full feature coverage report Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
232 lines
7.8 KiB
JavaScript
232 lines
7.8 KiB
JavaScript
describe('API CRUD Operations', () => {
|
|
const uid = () => 'cy_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6)
|
|
|
|
// ---- Notes ----
|
|
it('POST /api/notes creates a note', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/notes', { id, text: 'E2E test note', tag: '灵感' }).then(res => {
|
|
expect(res.status).to.eq(200)
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('DELETE /api/notes/:id deletes a note', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/notes', { id, text: 'to delete', tag: '灵感' })
|
|
cy.request('DELETE', `/api/notes/${id}`).then(res => {
|
|
expect(res.status).to.eq(200)
|
|
})
|
|
})
|
|
|
|
// ---- Todos ----
|
|
it('POST /api/todos creates a todo', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/todos', { id, text: 'E2E todo', quadrant: 'q1', done: 0 }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('POST /api/todos updates a todo (upsert)', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/todos', { id, text: 'before', quadrant: 'q1', done: 0 })
|
|
cy.request('POST', '/api/todos', { id, text: 'after', quadrant: 'q2', done: 1 }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
cy.request('/api/todos').then(res => {
|
|
const todo = res.body.find(t => t.id === id)
|
|
expect(todo.text).to.eq('after')
|
|
expect(todo.quadrant).to.eq('q2')
|
|
expect(todo.done).to.eq(1)
|
|
})
|
|
})
|
|
|
|
it('DELETE /api/todos/:id deletes a todo', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/todos', { id, text: 'to delete', quadrant: 'q1', done: 0 })
|
|
cy.request('DELETE', `/api/todos/${id}`).then(res => {
|
|
expect(res.status).to.eq(200)
|
|
})
|
|
})
|
|
|
|
// ---- Inbox ----
|
|
it('POST /api/inbox creates inbox item', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/inbox', { id, text: 'inbox test' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('DELETE /api/inbox clears all inbox', () => {
|
|
cy.request('DELETE', '/api/inbox').then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
cy.request('/api/inbox').then(res => {
|
|
expect(res.body).to.have.length(0)
|
|
})
|
|
})
|
|
|
|
// ---- Reminders ----
|
|
it('POST /api/reminders creates a reminder', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/reminders', { id, text: 'test reminder', time: '09:00', repeat: 'daily', enabled: 1 }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('DELETE /api/reminders/:id deletes a reminder', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/reminders', { id, text: 'to delete', repeat: 'none', enabled: 1 })
|
|
cy.request('DELETE', `/api/reminders/${id}`).then(res => {
|
|
expect(res.status).to.eq(200)
|
|
})
|
|
})
|
|
|
|
// ---- Goals ----
|
|
it('POST /api/goals creates and updates a goal', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/goals', { id, name: 'test goal', month: '2026-06', checks: '{}' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
cy.request('POST', '/api/goals', { id, name: 'updated goal', month: '2026-07', checks: '{"2026-07-01":true}' })
|
|
cy.request('/api/goals').then(res => {
|
|
const goal = res.body.find(g => g.id === id)
|
|
expect(goal.name).to.eq('updated goal')
|
|
})
|
|
})
|
|
|
|
// ---- Checklists ----
|
|
it('POST /api/checklists creates a checklist', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/checklists', { id, title: 'test list', items: '[]', archived: 0 }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
// ---- Sleep ----
|
|
it('POST /api/sleep creates a record', () => {
|
|
cy.request('POST', '/api/sleep', { date: '2026-01-01', time: '22:30' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('POST /api/sleep upserts on same date', () => {
|
|
cy.request('POST', '/api/sleep', { date: '2026-01-02', time: '22:00' })
|
|
cy.request('POST', '/api/sleep', { date: '2026-01-02', time: '23:00' })
|
|
cy.request('/api/sleep').then(res => {
|
|
const rec = res.body.find(r => r.date === '2026-01-02')
|
|
expect(rec.time).to.eq('23:00')
|
|
})
|
|
})
|
|
|
|
it('DELETE /api/sleep/:date deletes a record', () => {
|
|
cy.request('POST', '/api/sleep', { date: '2026-01-03', time: '21:00' })
|
|
cy.request('DELETE', '/api/sleep/2026-01-03').then(res => {
|
|
expect(res.status).to.eq(200)
|
|
})
|
|
})
|
|
|
|
// ---- Gym ----
|
|
it('POST /api/gym creates a record', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/gym', { id, date: '2026-04-07', type: '跑步', duration: '30min', note: '5km' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
// ---- Period ----
|
|
it('POST /api/period creates a record', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/period', { id, start_date: '2026-04-01', end_date: '2026-04-05', note: '' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
// ---- Docs ----
|
|
it('POST /api/docs creates a doc', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/docs', { id, name: 'test doc', icon: '📖', keywords: 'test', extract_rule: 'none' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('POST /api/doc-entries creates an entry', () => {
|
|
const docId = uid()
|
|
const entryId = uid()
|
|
cy.request('POST', '/api/docs', { id: docId, name: 'doc for entry', icon: '📄', keywords: '', extract_rule: 'none' })
|
|
cy.request('POST', '/api/doc-entries', { id: entryId, doc_id: docId, text: 'entry text' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
cy.request('/api/docs').then(res => {
|
|
const doc = res.body.find(d => d.id === docId)
|
|
expect(doc.entries).to.have.length(1)
|
|
expect(doc.entries[0].text).to.eq('entry text')
|
|
})
|
|
})
|
|
|
|
// ---- Bugs ----
|
|
it('POST /api/bugs creates a bug', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/bugs', { id, text: 'test bug', status: 'open' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('DELETE /api/bugs/:id deletes a bug', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/bugs', { id, text: 'to delete', status: 'open' })
|
|
cy.request('DELETE', `/api/bugs/${id}`).then(res => {
|
|
expect(res.status).to.eq(200)
|
|
})
|
|
})
|
|
|
|
// ---- Schedule ----
|
|
it('POST /api/schedule-modules creates a module', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/schedule-modules', { id, name: 'work', emoji: '💼', color: '#667eea', sort_order: 0 }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('POST /api/schedule-slots creates a slot', () => {
|
|
const modId = uid()
|
|
cy.request('POST', '/api/schedule-modules', { id: modId, name: 'slot test', emoji: '📌', color: '#333', sort_order: 0 })
|
|
cy.request('POST', '/api/schedule-slots', { date: '2026-04-07', time_slot: '09:00', module_id: modId }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
// ---- Reviews ----
|
|
it('POST /api/reviews creates a review', () => {
|
|
cy.request('POST', '/api/reviews', { week: '2026-W15', data: '{"wins":"test"}' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
// ---- Health check-in ----
|
|
it('POST /api/health-items creates an item', () => {
|
|
const id = uid()
|
|
cy.request('POST', '/api/health-items', { id, name: 'vitamin C', type: 'health' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('POST /api/health-plans saves a plan', () => {
|
|
cy.request('POST', '/api/health-plans', { month: '2026-04', type: 'health', item_ids: '["item1"]' }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
it('POST /api/health-checks toggles a check', () => {
|
|
cy.request('POST', '/api/health-checks', { date: '2026-04-07', type: 'health', item_id: 'item1', checked: 1 }).then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
|
|
// ---- Backup ----
|
|
it('POST /api/backup triggers backup', () => {
|
|
cy.request('POST', '/api/backup').then(res => {
|
|
expect(res.body.ok).to.be.true
|
|
})
|
|
})
|
|
})
|