mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
fix(ui): reset stale mutation state when the import configuration changes
After a failed preview or import, editing the package URL, source mode, target, or collision strategy cleared the preview but left the mutation error state behind, so the persistent error panel kept describing a superseded request (and a stale import error could resurface under a fresh preview). Route all configuration changes through a shared reset that also clears both mutations, and cover the reset in the component tests.
This commit is contained in:
1 parent
55d849cedc
commit
37cc66e9d6
2 files changed
+29
-7
No files matched your search
@@ -206,14 +206,14 @@ describe("CompanyImport", () => {
|
||||
await flushReact();
|
||||
}
|
||||
|
||||
async function enterGithubUrl() {
|
||||
async function enterGithubUrl(url = "https://github.com/acme/starter/tree/main/company") {
|
||||
const urlInput = container.querySelector<HTMLInputElement>(
|
||||
'input[placeholder="https://github.com/owner/repo/tree/main/company"]',
|
||||
);
|
||||
expect(urlInput).toBeTruthy();
|
||||
await act(async () => {
|
||||
const setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")!.set!;
|
||||
setter.call(urlInput!, "https://github.com/acme/starter/tree/main/company");
|
||||
setter.call(urlInput!, url);
|
||||
urlInput!.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
});
|
||||
await flushReact();
|
||||
@@ -355,6 +355,11 @@ describe("CompanyImport", () => {
|
||||
expect(container.textContent).toContain("Preview failed: stream disconnected");
|
||||
expect(container.textContent).toContain("Retry, or use the CLI folder import");
|
||||
expect(mockPushToast).toHaveBeenCalledWith(expect.objectContaining({ tone: "error" }));
|
||||
|
||||
// Changing the package supersedes the failed request: the error panel resets.
|
||||
await enterGithubUrl("https://github.com/acme/other-starter/tree/main/company");
|
||||
|
||||
expect(container.textContent).not.toContain("Preview failed:");
|
||||
});
|
||||
|
||||
it("shows a progress panel while the import runs and a durable error panel when it fails", async () => {
|
||||
@@ -383,5 +388,13 @@ describe("CompanyImport", () => {
|
||||
expect(container.textContent).toContain("Import failed: connection reset");
|
||||
expect(container.textContent).toContain("check the target company before retrying.");
|
||||
expect(mockPushToast).toHaveBeenCalledWith(expect.objectContaining({ tone: "error" }));
|
||||
|
||||
// Changing the package supersedes the failed import: previewing a fresh
|
||||
// package must not resurface the stale import error panel.
|
||||
await enterGithubUrl("https://github.com/acme/other-starter/tree/main/company");
|
||||
await clickButton((text) => text === "Preview import");
|
||||
|
||||
expect(findButton((text) => text.startsWith("Import 3 file"))).toBeTruthy();
|
||||
expect(container.textContent).not.toContain("Import failed:");
|
||||
});
|
||||
});
|
||||
@@ -927,13 +927,22 @@ export function CompanyImport() {
|
||||
},
|
||||
});
|
||||
|
||||
// Any change to the package or import configuration supersedes the last
|
||||
// preview and any settled mutation state, so the persistent progress/error
|
||||
// panels never keep describing a request that no longer applies.
|
||||
function resetImportFlowState() {
|
||||
setImportPreview(null);
|
||||
previewMutation.reset();
|
||||
importMutation.reset();
|
||||
}
|
||||
|
||||
async function handleChooseLocalPackage(e: ChangeEvent<HTMLInputElement>) {
|
||||
const fileList = e.target.files;
|
||||
if (!fileList || fileList.length === 0) return;
|
||||
try {
|
||||
const pkg = await readLocalPackageZip(fileList[0]!);
|
||||
setLocalPackage(pkg);
|
||||
setImportPreview(null);
|
||||
resetImportFlowState();
|
||||
} catch (err) {
|
||||
pushToast({
|
||||
tone: "error",
|
||||
@@ -1311,7 +1320,7 @@ export function CompanyImport() {
|
||||
)}
|
||||
onClick={() => {
|
||||
setSourceMode(key);
|
||||
setImportPreview(null);
|
||||
resetImportFlowState();
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -1379,7 +1388,7 @@ export function CompanyImport() {
|
||||
placeholder="https://github.com/owner/repo/tree/main/company"
|
||||
onChange={(e) => {
|
||||
setImportUrl(e.target.value);
|
||||
setImportPreview(null);
|
||||
resetImportFlowState();
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
@@ -1391,7 +1400,7 @@ export function CompanyImport() {
|
||||
value={targetMode}
|
||||
onChange={(e) => {
|
||||
setTargetMode(e.target.value as "existing" | "new");
|
||||
setImportPreview(null);
|
||||
resetImportFlowState();
|
||||
}}
|
||||
>
|
||||
<option value="new">Create new company</option>
|
||||
@@ -1425,7 +1434,7 @@ export function CompanyImport() {
|
||||
value={collisionStrategy}
|
||||
onChange={(e) => {
|
||||
setCollisionStrategy(e.target.value as CompanyPortabilityCollisionStrategy);
|
||||
setImportPreview(null);
|
||||
resetImportFlowState();
|
||||
}}
|
||||
>
|
||||
<option value="rename">Rename on conflict</option>
|
||||
|
||||
Reference in new issue
Block a user