fix(studio): synchronize batch completion state
This commit is contained in:
1 parent
9f349c3343
commit
f2e67ebace
2 files changed
+43
-5
No files matched your search
@@ -0,0 +1,34 @@
|
|||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("StudioClient batch completion contract", () => {
|
||||||
|
it("marks React state without recursively invoking its completion callback", () => {
|
||||||
|
const source = readFileSync(
|
||||||
|
new URL("./studio-client.tsx", import.meta.url),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
const callbackBody = source.match(
|
||||||
|
/const markBatchDone = useCallback\(\(\) => \{([\s\S]*?)\n\t\}, \[\]\);/,
|
||||||
|
)?.[1];
|
||||||
|
|
||||||
|
expect(callbackBody).toBeDefined();
|
||||||
|
expect(callbackBody).toContain("setBatchDone(true);");
|
||||||
|
expect(callbackBody).not.toContain("markBatchDone();");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resets the completion ref and React state before every batch", () => {
|
||||||
|
const source = readFileSync(
|
||||||
|
new URL("./studio-client.tsx", import.meta.url),
|
||||||
|
"utf8",
|
||||||
|
);
|
||||||
|
const callbackBody = source.match(
|
||||||
|
/const resetBatchDone = useCallback\(\(\) => \{([\s\S]*?)\n\t\}, \[\]\);/,
|
||||||
|
)?.[1];
|
||||||
|
|
||||||
|
expect(callbackBody).toBeDefined();
|
||||||
|
expect(callbackBody).toContain("batchDoneRef.current = false;");
|
||||||
|
expect(callbackBody).toContain("setBatchDone(false);");
|
||||||
|
expect(source.match(/resetBatchDone\(\);/g)).toHaveLength(4);
|
||||||
|
expect(source.match(/setBatchDone\(false\);/g)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -154,7 +154,11 @@ export function StudioClient({
|
|||||||
const batchDoneRef = useRef(false);
|
const batchDoneRef = useRef(false);
|
||||||
const markBatchDone = useCallback(() => {
|
const markBatchDone = useCallback(() => {
|
||||||
batchDoneRef.current = true;
|
batchDoneRef.current = true;
|
||||||
markBatchDone();
|
setBatchDone(true);
|
||||||
|
}, []);
|
||||||
|
const resetBatchDone = useCallback(() => {
|
||||||
|
batchDoneRef.current = false;
|
||||||
|
setBatchDone(false);
|
||||||
}, []);
|
}, []);
|
||||||
const [batchSucceeded, setBatchSucceeded] = useState(0);
|
const [batchSucceeded, setBatchSucceeded] = useState(0);
|
||||||
const [batchFailed, setBatchFailed] = useState(0);
|
const [batchFailed, setBatchFailed] = useState(0);
|
||||||
@@ -430,7 +434,7 @@ export function StudioClient({
|
|||||||
initial.set(cn, { classname: cn, status: "pending" });
|
initial.set(cn, { classname: cn, status: "pending" });
|
||||||
}
|
}
|
||||||
setBatchProgress(initial);
|
setBatchProgress(initial);
|
||||||
setBatchDone(false);
|
resetBatchDone();
|
||||||
setBatchSucceeded(0);
|
setBatchSucceeded(0);
|
||||||
setBatchFailed(0);
|
setBatchFailed(0);
|
||||||
setFailedClassnames([]);
|
setFailedClassnames([]);
|
||||||
@@ -693,7 +697,7 @@ export function StudioClient({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setBatchDone(false);
|
resetBatchDone();
|
||||||
setBatchSucceeded(0);
|
setBatchSucceeded(0);
|
||||||
setBatchFailed(0);
|
setBatchFailed(0);
|
||||||
setBatchCancelling(false);
|
setBatchCancelling(false);
|
||||||
@@ -831,7 +835,7 @@ export function StudioClient({
|
|||||||
async function retryFailed(failed: string[]) {
|
async function retryFailed(failed: string[]) {
|
||||||
if (!activeSource || failed.length === 0) return;
|
if (!activeSource || failed.length === 0) return;
|
||||||
// For clone sources, re-run cloneAllMissing with only the failed classnames
|
// For clone sources, re-run cloneAllMissing with only the failed classnames
|
||||||
setBatchDone(false);
|
resetBatchDone();
|
||||||
setBatchSucceeded(0);
|
setBatchSucceeded(0);
|
||||||
setBatchFailed(0);
|
setBatchFailed(0);
|
||||||
setFailedClassnames([]);
|
setFailedClassnames([]);
|
||||||
@@ -1957,7 +1961,7 @@ export function StudioClient({
|
|||||||
onCancel={cloneAllAbortRef.current ? cancelCloneAll : cancelBatch}
|
onCancel={cloneAllAbortRef.current ? cancelCloneAll : cancelBatch}
|
||||||
onDismiss={() => {
|
onDismiss={() => {
|
||||||
setBatchProgress(null);
|
setBatchProgress(null);
|
||||||
setBatchDone(false);
|
resetBatchDone();
|
||||||
setVerification(null);
|
setVerification(null);
|
||||||
setFailedClassnames([]);
|
setFailedClassnames([]);
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in new issue
Block a user