fix: retain uncertain optimistic mutations
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,10 @@ describe("async UI state matrix", () => {
|
||||
[{ data: ["value"], isFetching: true }, "refreshing"],
|
||||
[{ data: ["value"], isStale: true, isDegraded: true }, "stale-degraded"],
|
||||
[{ data: ["value"], isMutationPending: true }, "mutation-pending"],
|
||||
[
|
||||
{ data: ["value"], hasMutationEffectUnknown: true },
|
||||
"mutation-effect-unknown",
|
||||
],
|
||||
[{ data: ["value"], hasMutationConflict: true }, "mutation-conflict"],
|
||||
])("derives overlay state %#", (signals, indicator) => {
|
||||
expect(deriveAsyncState(signals).indicator).toBe(indicator);
|
||||
@@ -35,16 +39,55 @@ describe("async UI state matrix", () => {
|
||||
data: ["value"],
|
||||
isFetching: true,
|
||||
isMutationPending: true,
|
||||
hasMutationEffectUnknown: true,
|
||||
hasMutationConflict: true,
|
||||
});
|
||||
expect(state.indicator).toBe("mutation-conflict");
|
||||
expect(state.indicator).toBe("mutation-effect-unknown");
|
||||
expect(state.overlay).toMatchObject({
|
||||
refreshing: false,
|
||||
mutationPending: false,
|
||||
mutationConflict: true,
|
||||
mutationEffectUnknown: true,
|
||||
mutationConflict: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("renders unknown mutation effects with reconciliation-only actions", async () => {
|
||||
const user = userEvent.setup();
|
||||
const retry = vi.fn();
|
||||
const reconcile = vi.fn();
|
||||
const state = deriveAsyncState({
|
||||
data: ["value"],
|
||||
hasMutationEffectUnknown: true,
|
||||
});
|
||||
|
||||
render(
|
||||
<AsyncSurface
|
||||
state={state}
|
||||
onRetry={retry}
|
||||
onReconcileUnknownEffect={reconcile}
|
||||
>
|
||||
existing content
|
||||
</AsyncSurface>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole("status")).toHaveTextContent(
|
||||
"변경 결과를 확인할 수 없습니다.",
|
||||
);
|
||||
expect(
|
||||
screen.getByText("existing content").closest("section"),
|
||||
).toHaveAttribute("aria-busy", "false");
|
||||
expect(
|
||||
screen.queryByRole("button", { name: "다시 시도" }),
|
||||
).not.toBeInTheDocument();
|
||||
await user.click(screen.getByRole("button", { name: "변경됨으로 확인" }));
|
||||
await user.click(
|
||||
screen.getByRole("button", { name: "변경되지 않음으로 확인" }),
|
||||
);
|
||||
expect(reconcile).toHaveBeenNthCalledWith(1, "APPLIED");
|
||||
expect(reconcile).toHaveBeenNthCalledWith(2, "NOT_APPLIED");
|
||||
expect(retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps content visible while a non-blocking refresh runs", () => {
|
||||
const state = deriveAsyncState({ data: ["value"], isFetching: true });
|
||||
render(<AsyncSurface state={state}>existing content</AsyncSurface>);
|
||||
|
||||
Reference in New Issue
Block a user