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>
116 lines
3.9 KiB
JavaScript
116 lines
3.9 KiB
JavaScript
describe('Notes (随手记)', () => {
|
|
beforeEach(() => {
|
|
cy.visit('/', {
|
|
onBeforeLoad(win) {
|
|
win.localStorage.setItem('sp_login_expires', String(Date.now() + 86400000))
|
|
}
|
|
})
|
|
cy.get('header').should('be.visible')
|
|
cy.get('.tab-btn').contains('随手记').click()
|
|
})
|
|
|
|
it('shows capture input area', () => {
|
|
cy.get('.capture-input').should('be.visible')
|
|
cy.get('.capture-btn').should('be.visible')
|
|
})
|
|
|
|
it('shows tag buttons', () => {
|
|
cy.get('.tag-btn').should('have.length.gte', 8)
|
|
cy.get('.tag-btn').first().should('contain', '💡')
|
|
})
|
|
|
|
it('can select different tags', () => {
|
|
cy.get('.tag-btn').contains('✅').click()
|
|
cy.get('.tag-btn').contains('✅').should('have.class', 'active')
|
|
cy.get('.tag-btn').contains('💡').should('not.have.class', 'active')
|
|
})
|
|
|
|
it('creates a note via input', () => {
|
|
cy.get('.capture-input').type('测试笔记内容')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.note-card').should('contain', '测试笔记内容')
|
|
})
|
|
|
|
it('creates a note with specific tag', () => {
|
|
cy.get('.tag-btn').contains('📖').click()
|
|
cy.get('.capture-input').type('读书笔记测试')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.note-card').first().should('contain', '读书笔记测试')
|
|
cy.get('.note-tag').first().should('contain', '读书')
|
|
})
|
|
|
|
it('creates note via Enter key', () => {
|
|
cy.get('.capture-input').type('回车创建笔记{enter}')
|
|
cy.get('.note-card').should('contain', '回车创建笔记')
|
|
})
|
|
|
|
it('clears input after creating note', () => {
|
|
cy.get('.capture-input').type('清空测试')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.capture-input').should('have.value', '')
|
|
})
|
|
|
|
it('does not create empty notes', () => {
|
|
cy.get('.note-card').then($cards => {
|
|
const count = $cards.length
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.note-card').should('have.length', count)
|
|
})
|
|
})
|
|
|
|
it('can search/filter notes', () => {
|
|
// Create 2 notes
|
|
cy.get('.capture-input').type('苹果笔记')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.capture-input').type('香蕉笔记')
|
|
cy.get('.capture-btn').click()
|
|
// Search
|
|
cy.get('.search-input').type('苹果')
|
|
cy.get('.note-card').should('have.length', 1)
|
|
cy.get('.note-card').should('contain', '苹果')
|
|
})
|
|
|
|
it('can filter by tag', () => {
|
|
cy.get('.tag-btn').contains('💡').click()
|
|
cy.get('.capture-input').type('灵感笔记')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.tag-btn').contains('⏰').click()
|
|
cy.get('.capture-input').type('提醒笔记')
|
|
cy.get('.capture-btn').click()
|
|
// Filter by 灵感
|
|
cy.get('.filter-btn').contains('灵感').click()
|
|
cy.get('.note-card').each($card => {
|
|
cy.wrap($card).find('.note-tag').should('contain', '灵感')
|
|
})
|
|
})
|
|
|
|
it('can edit a note', () => {
|
|
cy.get('.capture-input').type('待编辑笔记')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.note-action-btn').contains('编辑').first().click()
|
|
cy.get('.edit-textarea').clear().type('已编辑笔记')
|
|
cy.get('.btn-accent').contains('保存').click()
|
|
cy.get('.note-card').first().should('contain', '已编辑笔记')
|
|
})
|
|
|
|
it('can delete a note', () => {
|
|
cy.get('.capture-input').type('待删除笔记')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.note-card').should('contain', '待删除笔记')
|
|
cy.get('.note-action-btn.danger').first().click()
|
|
cy.get('.note-card').should('not.contain', '待删除笔记')
|
|
})
|
|
|
|
it('shows empty hint when no notes', () => {
|
|
// This depends on initial state — may or may not be empty
|
|
// Just verify the component handles both states
|
|
cy.get('.notes-layout').should('be.visible')
|
|
})
|
|
|
|
it('displays time for each note', () => {
|
|
cy.get('.capture-input').type('带时间的笔记')
|
|
cy.get('.capture-btn').click()
|
|
cy.get('.note-time').first().should('not.be.empty')
|
|
})
|
|
})
|