Merge feature/ticket79-flaky-permissions-test into develop
Ticket #79 : fix du flake PermissionsPanel > saves project defaults (PermissionEditor draft resync clobbering in-flight edits). QA vert sur le périmètre du ticket (2/2 stable + suite complète non-shuffled) ; le rouge observé en shuffle vient d'un autre test préexistant sans rapport (setCellAgent.test.tsx, tracé séparément en #85). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
import { Button, Panel, Spinner, cn } from "@/shared";
|
||||
import type { PermissionSet, PermissionPosture } from "@/domain";
|
||||
@ -232,9 +232,26 @@ function PermissionEditor({
|
||||
onClear,
|
||||
}: PermissionEditorProps) {
|
||||
const [local, setLocal] = useState<PolicyDraft>(draft);
|
||||
|
||||
// `draft` is a NEW object every time the underlying document changes for ANY
|
||||
// reason (initial load landing after mount, a Refresh, another tab's save…),
|
||||
// even when its content matches what is already in `local`. Naively
|
||||
// re-syncing on every `draft` change is a genuine race: if it fires after the
|
||||
// user has started editing (in production: a slow initial fetch landing
|
||||
// right as the user types; in tests: a passive effect flushing later than a
|
||||
// synchronous `fireEvent` sequence — ticket #79 flake), it silently discards
|
||||
// the user's in-progress edit. `prevDraftRef` tracks the last draft this
|
||||
// effect adopted `local` from; we only re-sync when `local` still matches it
|
||||
// (nothing has been edited since), so a legitimate incoming draft (first
|
||||
// load, or the echo of the user's own just-saved edit) is adopted, but an
|
||||
// edit in flight never gets clobbered.
|
||||
const prevDraftRef = useRef(draft);
|
||||
useEffect(() => {
|
||||
setLocal(draft);
|
||||
setLocal((current) =>
|
||||
JSON.stringify(current) === JSON.stringify(prevDraftRef.current)
|
||||
? draft
|
||||
: current,
|
||||
);
|
||||
prevDraftRef.current = draft;
|
||||
}, [draft]);
|
||||
|
||||
const changed = useMemo(
|
||||
|
||||
Reference in New Issue
Block a user