test: lock in task-delete cache ordering, and fix project-delete ordering

Đang mở Phù hợp với người mới
#335 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
78/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
csharp, react, typescript
Lĩnh vực
frontend, testing

Hướng nghiên cứu

Đọc TaskFlow.Web/src/hooks/useTasks.ts và kiểm tra useDeleteTaskMutation.onSuccess; issue xác định thứ tự vô hiệu hóa và xóa làm phát sinh các request. Bắt đầu với bài kiểm tra hook được đề xuất, sau đó chạy các bài kiểm tra xóa hiện có của trang chi tiết. Hoàn tất khi việc xóa một tác vụ không tạo thêm request nào cho các truy vấn tác vụ, ghi chú hoặc lịch sử của tác vụ đó, trong khi danh sách tác vụ và số lượng dự án vẫn được cập nhật; nếu xóa thất bại, trang và các truy vấn phải được giữ nguyên.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

tech-debt

Groomed 2026-10-30 — ready for implementation.

Original Description

Found during the /ux-test run for #320 / PR #333. Not caused by that PR; the delete handler is unchanged there.

Problem

Deleting a task from its detail page (/tasks/:id) succeeds and redirects to /tasks, but the browser console logs five 404 errors for the task that was just deleted:

GET /api/v1/TaskItems/<id>          404  (x2)
GET /api/v1/TaskItems/<id>/notes    404  (x2)
GET /api/v1/TaskItems/<id>/history  404  (x1)

No user-visible effect was observed (the redirect wins), but it is wasted requests, console noise that hides real errors, and a possible brief not-found flash if the redirect is ever slower.

Cause

useDeleteTaskMutation (TaskFlow.Web/src/hooks/useTasks.ts) runs, in onSuccess:

qc.invalidateQueries({ queryKey: taskKeys.all })            // ['tasks']
qc.invalidateQueries({ queryKey: projectKeys.all })
qc.removeQueries({ queryKey: taskKeys.detail(id) })         // ['tasks', id]

invalidateQueries matches by key prefix, so ['tasks'] also matches the deleted task's own queries, which are all still mounted and active on the detail page: ['tasks', id] (task), ['tasks', id, 'notes'] and ['tasks', id, 'history']. Invalidation refetches active queries immediately, so they fire (and retry once, retry: 1 in main.tsx) before removeQueries runs and before TaskDetailPage navigates in its own onSuccess. removeQueries does not cancel a fetch already in flight.

The deleted task's queries should never be refetched, only dropped.

Suggested fix

In useDeleteTaskMutation.onSuccess, remove the deleted task's queries first (removeQueries({ queryKey: taskKeys.detail(id) }) already covers detail, notes and history by prefix), then invalidate the rest. Alternatively invalidate with a predicate that skips keys whose second element is id.

Acceptance criteria

  • Given a task detail page, when I delete the task and confirm, then I land on /tasks and no request is made to /TaskItems/<id>, /notes or /history after the DELETE.
  • Given the delete succeeds, then the task list and project counts still refresh (the list and project queries are still invalidated).
  • Given a failed delete, then the page stays as is and nothing is removed.

Notes

  • Test: a hook test on useDeleteTaskMutation asserting the deleted task's queries are not refetched, plus the existing detail-page delete tests staying green.
  • Overlaps with #321 (Undo toast for Tasks-page deletes), which also changes the delete hooks. Fix this in the same place, or land this first.
  • useDeleteProjectMutation has the same invalidate-then-remove order, but it has no UI yet, so it is not hit today. Worth fixing the same way while there.

User Story

As a developer maintaining TaskFlow, I want a regression test that proves deleting a task never refetches its own queries, and the same remove-before-invalidate ordering applied to project deletion, so that deletes produce no wasted requests or 404 console noise, and the ordering can't silently regress.

Scope note (2026-10-30): the task-side fix has already landed. invalidateAfterTaskDelete in hooks/useTasks.ts (lines 205-226) removes the deleted task's queries first, and TaskDetailPage now deletes through useDeleteTaskUndoable (#321), which navigates to /tasks before the DELETE is sent. The description above is kept for history. The remaining work is a regression test for the task side and the ordering fix for projects (hooks/useProjects.ts, lines 91-103). Paths are relative to TaskFlow.Web/src.

Acceptance Criteria

Task delete (lock in existing behavior, test only)

  1. Given a real query client with the deleted task's detail, notes and history queries mounted, when the task-delete invalidation runs after a successful DELETE, then no further request is made for that task's detail, notes or history.
  2. Given that same test, when the code is changed to invalidate before removing, then the test fails.
  3. Given a successful task delete, when invalidation completes, then the task list, project and journal queries are still invalidated.
  4. Given a DELETE that fails when the Undo window ends, when the commit settles, then the task's cached queries are kept. This replaces the original "page stays as is" criterion, because the user has already been taken to /tasks. The existing useDeleteTaskUndoable test (hooks/useDeleteTaskUndoable.test.tsx, lines 78-85) already covers it and must stay green.

Project delete (fix and test)

  1. Given a successful project delete, when useDeleteProjectMutation succeeds, then the project's detail and tasks queries are removed before projectKeys.all and taskKeys.all are invalidated.
  2. Given a real query client with an active ['projects', id] query, when the delete succeeds, then no request is made for that project after the DELETE. This test fails against the current order.
  3. Given a successful project delete, when it completes, then the project list and task queries are still refreshed.
  4. Given a failed project delete, when the mutation errors, then nothing is removed from the cache.

Edge Cases

  • The new tests need a real query client with mounted observers and call counts on the SDK mocks. Spies on invalidateQueries / removeQueries, like the existing order-insensitive check at hooks/useProjects.test.ts lines 151-159, can't show refetches.
  • TanStack v5 may rebuild a removed query if an observer stays mounted. The tests should confirm this does not happen for the task and project cases. This was unverified in the research.
  • pages/TaskDetailPage.test.tsx mocks useDeleteTaskUndoable entirely, so the real delete-and-navigate sequence still has no integration coverage. This story does not add it.
  • taskKeys.all stays invalidated after a project delete, because that project's tasks may have changed. Only the order changes.

Out of Scope

  • The Undo toast (#321), which is already implemented.
  • Adding UI for deleting projects. useDeleteProjectMutation and useDeleteTaskMutation have no production callers.
  • Changing the Undo window timing, toast behavior, or the query client defaults (staleTime 30_000, retry 1).
  • Browser-based verification that the 404s are gone. The tests are sufficient.
  • Auditing the invalidation order of other mutations.
  • Rewriting the original issue body.
Ngôn ngữ chính
C#
Star
1
Fork
0
Merge trung bình
2 giờ 2 phút
Pull request đã merge (30 ngày)
98

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của nevridge/TaskFlow

Tất cả issue của nevridge/TaskFlow

Issue tương tự

Thêm issue về C#

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.