Files
schedule-planner/frontend/cypress/e2e/tasks-flow.cy.js
Hera Zhao d3f3b4f37b
Some checks failed
Test / build-check (push) Successful in 3s
PR Preview / test (pull_request) Successful in 3s
PR Preview / teardown-preview (pull_request) Has been skipped
Test / e2e-test (push) Failing after 55s
PR Preview / deploy-preview (pull_request) Failing after 40s
Refactor to Vue 3 + FastAPI + SQLite architecture
- 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>
2026-04-07 21:18:22 +00:00

141 lines
5.5 KiB
JavaScript

describe('Tasks (待办)', () => {
beforeEach(() => {
cy.visit('/tasks', {
onBeforeLoad(win) {
win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000))
}
})
cy.get('header').should('be.visible')
})
// ---- Sub tabs ----
it('shows sub tabs: 待办, 目标, 清单', () => {
cy.get('.sub-tab').should('have.length', 3)
cy.get('.sub-tab').eq(0).should('contain', '待办')
cy.get('.sub-tab').eq(1).should('contain', '目标')
cy.get('.sub-tab').eq(2).should('contain', '清单')
})
it('defaults to 待办 sub tab', () => {
cy.get('.sub-tab').contains('待办').should('have.class', 'active')
})
it('switches between sub tabs', () => {
cy.get('.sub-tab').contains('目标').click()
cy.get('.sub-tab').contains('目标').should('have.class', 'active')
cy.get('.sub-tab').contains('清单').click()
cy.get('.sub-tab').contains('清单').should('have.class', 'active')
})
// ---- Inbox ----
it('shows inbox input', () => {
cy.get('.inbox-card').should('be.visible')
cy.get('.inbox-card .capture-input').should('be.visible')
})
it('adds item to inbox', () => {
cy.get('.inbox-card .capture-input').type('收集箱测试')
cy.get('.inbox-card .capture-btn').click()
cy.get('.inbox-item').should('contain', '收集箱测试')
})
it('inbox item has quadrant assignment buttons', () => {
cy.get('.inbox-card .capture-input').type('分类测试')
cy.get('.inbox-card .capture-btn').click()
cy.get('.inbox-item-actions button').should('have.length.gte', 4)
})
it('moves inbox item to quadrant', () => {
cy.get('.inbox-card .capture-input').type('移入q1')
cy.get('.inbox-card .capture-btn').click()
// Click 🔴 (q1 - urgent important)
cy.get('.inbox-item').contains('移入q1').parent().find('.inbox-item-actions button').first().click()
cy.get('.inbox-item').should('not.contain', '移入q1')
cy.get('.todo-item').should('contain', '移入q1')
})
// ---- Quadrants ----
it('shows 4 quadrants', () => {
cy.get('.quadrant').should('have.length', 4)
cy.get('.q-urgent-important').should('contain', '紧急且重要')
cy.get('.q-important').should('contain', '重要不紧急')
cy.get('.q-urgent').should('contain', '紧急不重要')
cy.get('.q-neither').should('contain', '不紧急不重要')
})
it('adds todo directly to a quadrant', () => {
cy.get('.q-urgent-important .add-todo-row input').type('直接添加任务{enter}')
cy.get('.q-urgent-important .todo-item').should('contain', '直接添加任务')
})
it('toggles todo completion', () => {
cy.get('.q-important .add-todo-row input').type('完成测试{enter}')
cy.get('.q-important .todo-item').contains('完成测试').parent().find('input[type="checkbox"]').check()
// Enable "show done" to verify
cy.get('#todoShowDone, .toggle-label input').check()
cy.get('.todo-item').contains('完成测试').parent().find('span.done').should('exist')
})
it('deletes a todo', () => {
cy.get('.q-neither .add-todo-row input').type('待删除todo{enter}')
cy.get('.todo-item').contains('待删除todo').parent().find('.remove-btn').click()
cy.get('.todo-item').should('not.contain', '待删除todo')
})
it('search filters todos', () => {
cy.get('.q-urgent-important .add-todo-row input').type('搜索目标A{enter}')
cy.get('.q-important .add-todo-row input').type('搜索目标B{enter}')
cy.get('.search-input').type('目标A')
cy.get('.todo-item').should('have.length', 1)
cy.get('.todo-item').should('contain', '搜索目标A')
})
// ---- Goals ----
it('creates a goal', () => {
cy.get('.sub-tab').contains('目标').click()
cy.get('.btn-accent').contains('新目标').click()
cy.get('.edit-form input').first().type('减肥5斤')
cy.get('.edit-form input[type="month"]').type('2026-06')
cy.get('.btn-accent').contains('保存').click()
cy.get('.goal-card').should('contain', '减肥5斤')
})
it('deletes a goal', () => {
cy.get('.sub-tab').contains('目标').click()
cy.get('.btn-accent').contains('新目标').click()
cy.get('.edit-form input').first().type('待删除目标')
cy.get('.btn-accent').contains('保存').click()
cy.get('.goal-card').contains('待删除目标').parent().find('.remove-btn').click()
cy.get('.goal-card').should('not.contain', '待删除目标')
})
// ---- Checklists ----
it('creates a checklist', () => {
cy.get('.sub-tab').contains('清单').click()
cy.get('.btn-accent').contains('新清单').click()
cy.get('.checklist-card').should('exist')
})
it('adds items to checklist', () => {
cy.get('.sub-tab').contains('清单').click()
cy.get('.btn-accent').contains('新清单').click()
cy.get('.checklist-card .add-todo-row input').first().type('清单项目1{enter}')
cy.get('.checklist-item').should('contain', '清单项目1')
})
it('toggles checklist item', () => {
cy.get('.sub-tab').contains('清单').click()
cy.get('.btn-accent').contains('新清单').click()
cy.get('.checklist-card .add-todo-row input').first().type('打勾测试{enter}')
cy.get('.checklist-item').contains('打勾测试').parent().find('input[type="checkbox"]').check()
cy.get('.checklist-item').contains('打勾测试').should('have.class', 'done')
})
it('deletes a checklist', () => {
cy.get('.sub-tab').contains('清单').click()
cy.get('.btn-accent').contains('新清单').click()
cy.get('.checklist-card').should('exist')
cy.get('.checklist-header .remove-btn').first().click()
})
})