fix(import): empty the root files when another import folder is chosen (#446)

SET_IMPORT_FOLDER now empties rootFiles. Until the new folder's scan
landed, or for good when that scan failed, the warning about files
placed directly in the import folder named the previous folder's files
under the new folder's name. scannedSources is left as it was: the
source list of the last scan stays until the new one, as before.

Reducer tests next to "a scan error leaves the root files of the last
scan in place": a folder change empties the root files and keeps the
sources until the next scan, and a scan error after a folder change
names no root file of the previous folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
le king fu 2026-10-18 20:59:13 -04:00
parent 08c2f57559
commit a62150d926
2 changed files with 39 additions and 5 deletions

View file

@ -222,6 +222,34 @@ describe("wizardReducer — rootFiles (#427)", () => {
const after = wizardReducer(before, { type: "SET_ERROR", payload: "folder not found" }); const after = wizardReducer(before, { type: "SET_ERROR", payload: "folder not found" });
expect(after.rootFiles).toBe(before.rootFiles); expect(after.rootFiles).toBe(before.rootFiles);
}); });
it("choosing another folder empties the root files until its own scan lands (#446)", () => {
const before = reduce([
{ type: "SET_IMPORT_FOLDER", payload: "/releves" },
{ type: "SET_SCANNED_SOURCES", payload: scan(["a.csv"]) },
]);
const changed = wizardReducer(before, { type: "SET_IMPORT_FOLDER", payload: "/autre" });
// The warning would name "a.csv" of /releves under the name of /autre.
expect(changed.importFolder).toBe("/autre");
expect(changed.rootFiles).toEqual([]);
// Prior behaviour, kept: the sources of the last scan stay until the new one.
expect(changed.scannedSources).toBe(before.scannedSources);
const scanned = wizardReducer(changed, { type: "SET_SCANNED_SOURCES", payload: scan(["b.csv"], []) });
expect(scanned.rootFiles).toEqual(["b.csv"]);
expect(scanned.scannedSources).toEqual([]);
});
it("a scan error after a folder change names no root file of the previous folder (#446)", () => {
const after = reduce([
{ type: "SET_IMPORT_FOLDER", payload: "/releves" },
{ type: "SET_SCANNED_SOURCES", payload: scan(["a.csv"]) },
{ type: "SET_IMPORT_FOLDER", payload: "/autre" },
{ type: "SET_LOADING", payload: true },
{ type: "SET_ERROR", payload: "folder not found" },
]);
expect(after.rootFiles).toEqual([]);
});
}); });
describe("sampleFolderError — the refusals of create_sample_import_folders (#384, D2)", () => { describe("sampleFolderError — the refusals of create_sample_import_folders (#384, D2)", () => {

View file

@ -110,9 +110,11 @@ export interface WizardState {
/** /**
* Names of the CSV/TXT files placed directly at the root of the import * Names of the CSV/TXT files placed directly at the root of the import
* folder, which no source reads (#427). Set with `scannedSources` by the * folder, which no source reads (#427). Set with `scannedSources` by the
* same action, so the warning and the source list always come from the same * same action, so the warning and the source list come from the same scan;
* scan; kept by `RESET` like them. Shown on screen only, never logged: a * kept by `RESET` like them. Emptied by `SET_IMPORT_FOLDER`, which leaves
* statement name often carries an account number. * `scannedSources` alone (#446): another folder shows no warning until its
* own scan. Shown on screen only, never logged: a statement name often
* carries an account number.
*/ */
rootFiles: string[]; rootFiles: string[];
selectedSource: ScannedSource | null; selectedSource: ScannedSource | null;
@ -252,8 +254,12 @@ export function wizardReducer(state: WizardState, action: WizardAction): WizardS
case "SET_STEP": case "SET_STEP":
return { ...state, step: action.payload }; return { ...state, step: action.payload };
case "SET_IMPORT_FOLDER": case "SET_IMPORT_FOLDER":
// The sample-folder banner describes the previous folder: drop it. // The sample-folder banner describes the previous folder: drop it. So do
return { ...state, importFolder: action.payload, sampleCreated: null }; // the root files (#446): until the new folder's scan lands, or for good
// if it fails, the warning would name the previous folder's files under
// the new folder's name. The scanned sources stay until that scan, as
// they always did.
return { ...state, importFolder: action.payload, rootFiles: [], sampleCreated: null };
case "SET_IMPORT_FOLDER_LOADED": case "SET_IMPORT_FOLDER_LOADED":
return { ...state, importFolderLoaded: true }; return { ...state, importFolderLoaded: true };
case "SET_SCANNED_SOURCES": case "SET_SCANNED_SOURCES":