fix: scope completion motion to user actions
ci / gitleaks (push) Successful in 6s
ci / docker (push) Successful in 3m26s

This commit is contained in:
2026-09-09 09:45:38 +08:00
parent 88f9501468
commit aff070d2f7
4 changed files with 47 additions and 11 deletions
+17 -5
View File
@@ -49,12 +49,23 @@ describe('warm Liquid Glass styling', () => {
})
describe('completion feedback motion', () => {
it('animates completed task and habit rows without ignoring reduced motion', () => {
expect(css).toContain('.task-row.done,.habit-row.done{animation:completion-row-settle .34s cubic-bezier(.2,.85,.3,1)}')
expect(css).toContain('.task-row.done .task-check-mark,.habit-row.done .task-check-mark{animation:completion-check-pop .38s cubic-bezier(.2,1.4,.35,1)}')
it('animates only transient just-completed rows and respects reduced motion', () => {
expect(css).toContain('.task-row.just-completed,.habit-row.just-completed{animation:completion-row-settle .34s cubic-bezier(.2,.85,.3,1)}')
expect(css).toContain('.task-row.just-completed .task-check-mark,.habit-row.just-completed .task-check-mark{animation:completion-check-pop .38s cubic-bezier(.2,1.4,.35,1)}')
expect(css).not.toContain('.task-row.done,.habit-row.done{animation:')
expect(css).toContain('@keyframes completion-row-settle')
expect(css).toContain('@keyframes completion-check-pop')
expect(css).toContain('@media(prefers-reduced-motion:reduce){.task-row.done,.habit-row.done,.task-row.done .task-check-mark,.habit-row.done .task-check-mark{animation:none}}')
expect(css).toContain('@media(prefers-reduced-motion:reduce){.task-row.just-completed,.habit-row.just-completed,.task-row.just-completed .task-check-mark,.habit-row.just-completed .task-check-mark{animation:none}}')
})
it('adds transient completion classes only for incomplete to complete transitions', () => {
expect(app).toContain("const justCompletedTaskIds = ref(new Set<string>())")
expect(app).toContain("if (completing) markTaskJustCompleted(task.id)")
expect(app).toContain("'just-completed': justCompletedTaskIds.has(node.task.id)")
expect(app).toContain("'just-completed': justCompletedTaskIds.has(subtask.id)")
expect(mvpPanel).toContain("const justCompletedHabitIds = ref(new Set<string>())")
expect(mvpPanel.match(/if \(!wasDone && isHabitComplete\(h\.kind, next, h\.target \?\? 1\)\) markHabitJustCompleted\(h\.id\)/g)).toHaveLength(2)
expect(mvpPanel.match(/'just-completed': justCompletedHabitIds\.has\(h\.id\)/g)).toHaveLength(2)
})
})
@@ -191,7 +202,8 @@ describe('task and habit row decoration', () => {
it('refreshes the current task data after toggling completion', () => {
const toggleBlock = app.slice(app.indexOf('async function toggle(task: Task)'), app.indexOf('function isInteractiveTarget'))
expect(toggleBlock).toContain('await patchTask(task, { completed: !task.completed })')
expect(toggleBlock).toContain('const completing = !task.completed')
expect(toggleBlock).toContain('await patchTask(task, { completed: completing })')
expect(toggleBlock).toContain('await loadTasksPage()')
expect(toggleBlock).toContain("if (activeView.value === 'today')")
expect(toggleBlock).toContain('await loadOverdueTasks()')