feat(#93): IMP-55 u1~u12 frontend manual section swap detection (manual_section_assignment bool axis + drag-only marker gate + dual-axis persistence + backend manual-true gate)
Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 9s
Some checks failed
Multi-MDX Regression (IMP-91) / multi-mdx-regression (push) Failing after 9s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -559,3 +559,67 @@ describe("saveUserOverrides (IMP-51 #79 u3) — image_overrides axis", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// IMP-55 #93 u1 — manual_section_assignment axis (7th axis) parity coverage
|
||||
//
|
||||
// The bool intent marker rides on the same per-axis coalescing rails as the
|
||||
// 6 sibling axes. These tests lock the typed client behavior so a regression
|
||||
// in the boolean serialization (e.g., coercion to "true" string, dropped
|
||||
// `false` due to truthy filtering) fails here instead of in Home.tsx (u6/u7)
|
||||
// or the backend gate (u9~u11).
|
||||
// ============================================================================
|
||||
|
||||
describe("saveUserOverrides (IMP-55 #93 u1) — manual_section_assignment axis", () => {
|
||||
it("PUT body carries only manual_section_assignment when it is the sole mutated axis", async () => {
|
||||
fetchMock.mockResolvedValue(mockResponse({}));
|
||||
void saveUserOverrides("03", { manual_section_assignment: true });
|
||||
vi.advanceTimersByTime(300);
|
||||
await drainMicrotasks();
|
||||
|
||||
const body = lastPutBody() as Record<string, unknown>;
|
||||
expect(Object.keys(body)).toEqual(["manual_section_assignment"]);
|
||||
expect(body.manual_section_assignment).toBe(true);
|
||||
});
|
||||
|
||||
it("later-wins coalesces true → false within a single debounce window", async () => {
|
||||
// Drag-then-cancel inside 300 ms — server must see only the final
|
||||
// `false`, not a transient `true` that would re-enable backend
|
||||
// consumption of stale zone_sections.
|
||||
fetchMock.mockResolvedValue(mockResponse({}));
|
||||
void saveUserOverrides("03", { manual_section_assignment: true });
|
||||
void saveUserOverrides("03", { manual_section_assignment: false });
|
||||
|
||||
vi.advanceTimersByTime(300);
|
||||
await drainMicrotasks();
|
||||
expect(putCallsCount()).toBe(1);
|
||||
expect(lastPutBody()).toEqual({ manual_section_assignment: false });
|
||||
});
|
||||
|
||||
it("forwards null sentinel verbatim (explicit clear)", async () => {
|
||||
fetchMock.mockResolvedValue(mockResponse({}));
|
||||
void saveUserOverrides("03", { manual_section_assignment: null });
|
||||
|
||||
vi.advanceTimersByTime(300);
|
||||
await drainMicrotasks();
|
||||
expect(lastPutBody()).toEqual({ manual_section_assignment: null });
|
||||
});
|
||||
|
||||
it("coalesces with zone_sections sibling into a single PUT (drag-drop pair)", async () => {
|
||||
// Real-world drag flow (u6): one save() sets the bool + zone_sections
|
||||
// together. Asserts both axes survive coalescing as a single PUT body.
|
||||
fetchMock.mockResolvedValue(mockResponse({}));
|
||||
void saveUserOverrides("03", {
|
||||
zone_sections: { left: ["03-2"], right: ["03-1"] },
|
||||
manual_section_assignment: true,
|
||||
});
|
||||
|
||||
vi.advanceTimersByTime(300);
|
||||
await drainMicrotasks();
|
||||
expect(putCallsCount()).toBe(1);
|
||||
expect(lastPutBody()).toEqual({
|
||||
zone_sections: { left: ["03-2"], right: ["03-1"] },
|
||||
manual_section_assignment: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user