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

Aperta Adatta ai principianti
#335 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
78/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
csharp, react, typescript
Ambito
frontend, testing

Direzione di ricerca

Leggi TaskFlow.Web/src/hooks/useTasks.ts ed esamina useDeleteTaskMutation.onSuccess; l’issue identifica l’ordine di invalidazione e rimozione che attiva le richieste. Inizia con il test suggerito dell’hook, poi esegui i test esistenti di eliminazione della pagina di dettaglio. Il lavoro è completato quando l’eliminazione di un’attività non genera altre richieste per le query dell’attività, delle note o della cronologia, mentre l’elenco delle attività e i conteggi dei progetti continuano ad aggiornarsi; se l’eliminazione non riesce, la pagina e le query devono rimanere intatte.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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.
Lingua principale
C#
Stelle
1
Fork
0
Merge medio
2h 2m
PR unite (30g)
98

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di nevridge/TaskFlow

Tutte le issue di nevridge/TaskFlow

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.