UNPKG

poto-siril

Version:

Automatization around Siril (<https://siril.org/>) for deep sky astrophotography.

811 lines (716 loc) 28.5 kB
import { jest } from "@jest/globals"; // Import Jest globals import path from "path"; import fs from "fs-extra"; import Enquirer from "enquirer"; import prepare, { SelectedInputSubDirectoryChoices, } from "../../commands/prepare"; import { POTO_JSON } from "../../utils/const"; import clear from "../../commands/clear"; import { generateScripts } from "../../commands/preprocess.generate-scripts"; import { getRealDataFromSample, spawnMockedDatasetToFs_dataset_1, } from "../fixtures"; import { logger } from "../../utils/logger"; describe("E2E", () => { let asiAirDirectory: string = ""; let bankDirectory: string = ""; let projectDirectory: string = ""; let logMessages: string[] = []; const promptMock = jest.fn(); beforeEach(() => { jest.useFakeTimers().setSystemTime(new Date(Date.UTC(2024, 9, 15))); ({ asiAirDirectory, bankDirectory, projectDirectory } = spawnMockedDatasetToFs_dataset_1()); // Spy on logger and Enquirer to capture logs and prompts. logMessages = []; const logMethods = [ "info", "warning", "debug", "error", "success", "step", "space", ] as const; type LogMethod = (typeof logMethods)[number]; // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, @typescript-eslint/no-unused-vars const originalMethods: Record<LogMethod, Function> = logMethods.reduce( (acc, method) => { acc[method] = logger[method]; return acc; }, // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type {} as Record<LogMethod, Function>, ); logMethods.forEach(method => { jest .spyOn(logger, method) .mockImplementation( (...args: Parameters<(typeof logger)[LogMethod]>) => { const message = `${method}: ${args.join(" ")}`; logMessages.push(message); //originalMethods[method].apply(logger, args); }, ); }); jest .spyOn(Enquirer.prototype, "prompt") .mockImplementation(async function (...args) { logMessages.push(`prompt: ${JSON.stringify(args, null, 2)}`); return promptMock(...args); }); }); afterEach(() => { jest.restoreAllMocks(); fs.removeSync(projectDirectory); }); afterAll(() => { // To ease debugging. fs.removeSync(projectDirectory); spawnMockedDatasetToFs_dataset_1(); }); it("should be neat", async () => { promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ selectedInputSubDirectory: "Use Autorun directory" as SelectedInputSubDirectoryChoices, } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240624-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); let files = fs.readdirSync(asiAirDirectory, { recursive: true, withFileTypes: false, encoding: "utf8", }); expect(files.filter(f => f.endsWith("_thn.jpg"))).toHaveLength(3); clear(asiAirDirectory); files = fs.readdirSync(asiAirDirectory, { recursive: true, withFileTypes: false, encoding: "utf8", }); expect(files.filter(f => f.endsWith("_thn.jpg"))).toHaveLength(0); // Make an empty directory to test `removeEmptyDirectories`. fs.mkdirSync(path.join(asiAirDirectory, "empty", "empty"), { recursive: true, }); expect(fs.existsSync(path.join(asiAirDirectory, "empty", "empty"))).toBe( true, ); clear(asiAirDirectory); expect(fs.existsSync(path.join(asiAirDirectory, "empty", "empty"))).toBe( false, ); expect(fs.existsSync(path.join(asiAirDirectory, "empty"))).toBe(false); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }); files = fs.readdirSync(projectDirectory, { recursive: true, withFileTypes: false, encoding: "utf8", }); expect(files).toMatchInlineSnapshot(` [ "Flat_1.0ms_Bin1_gain0", "H", "Light_60.0s_Bin1_gain0", "S", "_poto_siril.json", "any", "Flat_1.0ms_Bin1_gain0/Flat_1.0ms_Bin1_gain0_20240512-094309_-10.5C_0001.fit", "H/Flat_1.0ms_Bin1_H_gain100", "H/Light_60.0s_Bin1_H_gain0", "Light_60.0s_Bin1_gain0/Light_FOV_60.0s_Bin1_gain0_20240629-010840_-10.1C_0001.fit", "Light_60.0s_Bin1_gain0/Light_FOV_60.0s_Bin1_gain0_20240629-010841_-10.1C_0002.fit", "S/Flat_1.0ms_Bin1_S_gain100", "S/Light_120.0s_Bin1_S_gain0__20240626-010853", "S/Light_60.0s_Bin1_S_gain100__20240624-010840", "S/Light_60.0s_Bin1_S_gain100__20240627-010820", "any/Bias_1.0ms_Bin1_gain0", "any/Bias_1.0ms_Bin1_gain100", "any/Dark_120.0s_Bin1_gain0", "any/Dark_60.0s_Bin1_gain0", "any/Dark_60.0s_Bin1_gain100", "H/Flat_1.0ms_Bin1_H_gain100/Flat_1.0ms_Bin1_H_gain100_20240511-094306_-10.5C_0001.fit", "H/Flat_1.0ms_Bin1_H_gain100/Flat_1.0ms_Bin1_H_gain100_20240511-094307_-10.5C_0002.fit", "H/Flat_1.0ms_Bin1_H_gain100/Flat_1.0ms_Bin1_H_gain100_20240511-094308_-10.5C_0003.fit", "H/Light_60.0s_Bin1_H_gain0/Light_FOV_60.0s_Bin1_H_gain0_20240625-010850_-10.1C_0002.fit", "H/Light_60.0s_Bin1_H_gain0/Light_FOV_60.0s_Bin1_H_gain0_20240625-010851_-10.1C_0004.fit", "H/Light_60.0s_Bin1_H_gain0/Light_FOV_60.0s_Bin1_H_gain0_20240625-010852_-10.1C_0005.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240624-094304_-10.5C_0001.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240624-094305_-10.0C_0002.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240624-094306_-10.5C_0003.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240626-094304_-10.5C_0001.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240626-094305_-10.0C_0002.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240626-094306_-10.5C_0003.fit", "S/Light_120.0s_Bin1_S_gain0__20240626-010853/Light_FOV_120.0s_Bin1_S_gain0_20240626-010853_-10.1C_0001.fit", "S/Light_120.0s_Bin1_S_gain0__20240626-010853/Light_FOV_120.0s_Bin1_S_gain0_20240626-010854_-10.1C_0002.fit", "S/Light_60.0s_Bin1_S_gain100__20240624-010840/Light_FOV_60.0s_Bin1_S_gain100_20240624-010840_-10.1C_0001.fit", "S/Light_60.0s_Bin1_S_gain100__20240624-010840/Light_FOV_60.0s_Bin1_S_gain100_20240624-010841_-10.1C_0002.fit", "S/Light_60.0s_Bin1_S_gain100__20240624-010840/Light_FOV_60.0s_Bin1_S_gain100_20240624-010842_-10.1C_0003.fit", "S/Light_60.0s_Bin1_S_gain100__20240627-010820/Light_FOV_60.0s_Bin1_S_gain100_20240627-010820_-10.1C_0001.fit", "S/Light_60.0s_Bin1_S_gain100__20240627-010820/Light_FOV_60.0s_Bin1_S_gain100_20240627-010821_-10.1C_0002.fit", "any/Bias_1.0ms_Bin1_gain0/Bias_1.0ms_Bin1_gain0_20230910-101141_-9.8C_0001.fit", "any/Bias_1.0ms_Bin1_gain100/Bias_1.0ms_Bin1_gain100_20230910-101131_-9.8C_0001.fit", "any/Bias_1.0ms_Bin1_gain100/Bias_1.0ms_Bin1_gain100_20230910-101132_-9.8C_0002.fit", "any/Bias_1.0ms_Bin1_gain100/Bias_1.0ms_Bin1_gain100_20230910-101133_-9.8C_0003.fit", "any/Dark_120.0s_Bin1_gain0/Dark_120.0s_Bin1_L_gain0_20240308-155723_-10.0C_0001.fit", "any/Dark_120.0s_Bin1_gain0/Dark_120.0s_Bin1_L_gain0_20240308-155724_-10.0C_0002.fit", "any/Dark_60.0s_Bin1_gain0/Dark_60.0s_Bin1_gain0_20240308-155722_-10.0C_0001.fit", "any/Dark_60.0s_Bin1_gain0/Dark_60.0s_Bin1_gain0_20240308-155723_-10.0C_0002.fit", "any/Dark_60.0s_Bin1_gain100/Dark_60.0s_Bin1_L_gain100_20240308-155722_-10.0C_0001.fit", "any/Dark_60.0s_Bin1_gain100/Dark_60.0s_Bin1_L_gain100_20240308-155723_-10.0C_0002.fit", "any/Dark_60.0s_Bin1_gain100/Dark_60.0s_Bin1_L_gain100_20240308-155724_-10.0C_0003.fit", "any/Dark_60.0s_Bin1_gain100/Dark_60.0s_Bin1_L_gain100_20240308-155725_-10.0C_0004.fit", ] `); const potoJson = fs.readFileSync(path.join(projectDirectory, POTO_JSON), { encoding: "utf8", }); expect(potoJson).toMatchSnapshot(); await generateScripts( projectDirectory, "src/pipeline/Mono_Preprocessing/Mono_Preprocessing.ssf", ); files = fs.readdirSync(projectDirectory, { recursive: true, withFileTypes: false, encoding: "utf8", }); const scripts = files.filter(f => f.endsWith(".ssf")); expect(scripts).toHaveLength(5); expect(scripts).toMatchInlineSnapshot(` [ "Light_60.0s_Bin1_gain0_process/_poto_Mono_Preprocessing.ssf", "H/Light_60.0s_Bin1_H_gain0_process/_poto_Mono_Preprocessing.ssf", "S/Light_120.0s_Bin1_S_gain0__20240626-010853_process/_poto_Mono_Preprocessing.ssf", "S/Light_60.0s_Bin1_S_gain100__20240624-010840_process/_poto_Mono_Preprocessing.ssf", "S/Light_60.0s_Bin1_S_gain100__20240627-010820_process/_poto_Mono_Preprocessing.ssf", ] `); for (const script of scripts) { const scriptContent = fs.readFileSync( path.join(projectDirectory, script), { encoding: "utf8", }, ); expect(scriptContent).toMatchSnapshotWithNormalizedPaths(); } expect(logMessages).toMatchSnapshotWithNormalizedPaths(); }); describe("reading an input directory, asking plan/autorun question", () => { it("should errorthrow if no files", async () => { const autorunDirectory = `${asiAirDirectory}/Autorun`; fs.removeSync(autorunDirectory); const planDirectory = `${asiAirDirectory}/Plan`; fs.removeSync(planDirectory); promptMock.mockResolvedValueOnce({ createProjectDirectory: true, } as never); await expect( prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }), ).rejects.toThrow(`No FITS files found in input dir ${asiAirDirectory}`); }); it("should errorthrow if no files (ASIAIR version)", async () => { const autorunDirectory = `${asiAirDirectory}/Autorun`; fs.removeSync(autorunDirectory); const planDirectory = `${asiAirDirectory}/Plan`; fs.removeSync(planDirectory); fs.mkdirSync(planDirectory); promptMock.mockResolvedValueOnce({ createProjectDirectory: true, } as never); await expect( prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }), ).rejects.toThrow("No FITS files found in Autorun nor Plan folders."); }); it("should errorthrow if directory does not exists", async () => { fs.removeSync(asiAirDirectory); promptMock.mockResolvedValueOnce({ createProjectDirectory: true, } as never); await expect( prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }), ).rejects.toThrow(`Input directory ${asiAirDirectory} does not exists.`); }); it("should auto pick Autorun files", async () => { const planDirectory = `${asiAirDirectory}/Plan`; fs.removeSync(planDirectory); promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240624-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }); const files = fs.readdirSync(projectDirectory, { recursive: true, withFileTypes: false, encoding: "utf8", }); expect(files).toContain( "H/Light_60.0s_Bin1_H_gain0/Light_FOV_60.0s_Bin1_H_gain0_20240625-010850_-10.1C_0002.fit", ); }); it("should auto pick Plan files", async () => { const autorunDirectory = `${asiAirDirectory}/Autorun`; fs.removeSync(autorunDirectory); promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }); expect(logMessages).toContain( "info: 🔭 Cumulated light integration: 0 minutes.", ); const files = fs.readdirSync(projectDirectory, { recursive: true, withFileTypes: false, encoding: "utf8", }); expect(files.length).toBe(1); }); it("should pick both directories", async () => { promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ selectedInputSubDirectory: "Use both directory" as SelectedInputSubDirectoryChoices, } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240624-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }); expect(logMessages).toContain( `info: Found 27 FITS in input dir ${asiAirDirectory}.`, ); }); it("should pick plan directorie", async () => { promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ selectedInputSubDirectory: "Use Plan directory" as SelectedInputSubDirectoryChoices, } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory, bankDirectory], }); expect(logMessages).toContain( `info: Found 1 FITS in input dir ${asiAirDirectory}.`, ); }); }); describe("no Darks/Biases matching, multiples sequences", () => { it("should warn if no matching darks and biases", async () => { promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ selectedInputSubDirectory: "Use Autorun directory" as SelectedInputSubDirectoryChoices, } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240624-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], // No bank directory in input. }); const files = fs.readdirSync(projectDirectory, { recursive: true, withFileTypes: false, encoding: "utf8", }); expect(files).toMatchInlineSnapshot(` [ "Flat_1.0ms_Bin1_gain0", "H", "Light_60.0s_Bin1_gain0", "S", "_poto_siril.json", "Flat_1.0ms_Bin1_gain0/Flat_1.0ms_Bin1_gain0_20240512-094309_-10.5C_0001.fit", "H/Flat_1.0ms_Bin1_H_gain100", "H/Light_60.0s_Bin1_H_gain0", "Light_60.0s_Bin1_gain0/Light_FOV_60.0s_Bin1_gain0_20240629-010840_-10.1C_0001.fit", "Light_60.0s_Bin1_gain0/Light_FOV_60.0s_Bin1_gain0_20240629-010841_-10.1C_0002.fit", "S/Flat_1.0ms_Bin1_S_gain100", "S/Light_120.0s_Bin1_S_gain0__20240626-010853", "S/Light_60.0s_Bin1_S_gain100__20240624-010840", "S/Light_60.0s_Bin1_S_gain100__20240627-010820", "H/Flat_1.0ms_Bin1_H_gain100/Flat_1.0ms_Bin1_H_gain100_20240511-094306_-10.5C_0001.fit", "H/Flat_1.0ms_Bin1_H_gain100/Flat_1.0ms_Bin1_H_gain100_20240511-094307_-10.5C_0002.fit", "H/Flat_1.0ms_Bin1_H_gain100/Flat_1.0ms_Bin1_H_gain100_20240511-094308_-10.5C_0003.fit", "H/Light_60.0s_Bin1_H_gain0/Light_FOV_60.0s_Bin1_H_gain0_20240625-010850_-10.1C_0002.fit", "H/Light_60.0s_Bin1_H_gain0/Light_FOV_60.0s_Bin1_H_gain0_20240625-010851_-10.1C_0004.fit", "H/Light_60.0s_Bin1_H_gain0/Light_FOV_60.0s_Bin1_H_gain0_20240625-010852_-10.1C_0005.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240624-094304_-10.5C_0001.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240624-094305_-10.0C_0002.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240624-094306_-10.5C_0003.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240626-094304_-10.5C_0001.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240626-094305_-10.0C_0002.fit", "S/Flat_1.0ms_Bin1_S_gain100/Flat_1.0ms_Bin1_S_gain100_20240626-094306_-10.5C_0003.fit", "S/Light_120.0s_Bin1_S_gain0__20240626-010853/Light_FOV_120.0s_Bin1_S_gain0_20240626-010853_-10.1C_0001.fit", "S/Light_120.0s_Bin1_S_gain0__20240626-010853/Light_FOV_120.0s_Bin1_S_gain0_20240626-010854_-10.1C_0002.fit", "S/Light_60.0s_Bin1_S_gain100__20240624-010840/Light_FOV_60.0s_Bin1_S_gain100_20240624-010840_-10.1C_0001.fit", "S/Light_60.0s_Bin1_S_gain100__20240624-010840/Light_FOV_60.0s_Bin1_S_gain100_20240624-010841_-10.1C_0002.fit", "S/Light_60.0s_Bin1_S_gain100__20240624-010840/Light_FOV_60.0s_Bin1_S_gain100_20240624-010842_-10.1C_0003.fit", "S/Light_60.0s_Bin1_S_gain100__20240627-010820/Light_FOV_60.0s_Bin1_S_gain100_20240627-010820_-10.1C_0001.fit", "S/Light_60.0s_Bin1_S_gain100__20240627-010820/Light_FOV_60.0s_Bin1_S_gain100_20240627-010821_-10.1C_0002.fit", ] `); const potoJson = fs.readFileSync(path.join(projectDirectory, POTO_JSON), { encoding: "utf8", }); expect(potoJson).toMatchSnapshot(); expect(logMessages).toMatchSnapshotWithNormalizedPaths(); expect(logMessages).toContain( "error: No darks matching light set Light_60.0s_Bin1_H_gain0 (regardless of temperature filtering).", ); }); it("should warn if no matching darks (temperature filtering)", async () => { promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ selectedInputSubDirectory: "Use Autorun directory" as SelectedInputSubDirectoryChoices, } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240624-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); fs.writeFileSync( path.join( asiAirDirectory, "Autorun/Dark_60.0s_Bin1_S_gain100_20240308-155722_-66.0C_0001.fit", ), getRealDataFromSample("Dark"), ); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], // No bank directory in input. }); expect(logMessages).toContain( "error: No darks matching light set Light_60.0s_Bin1_H_gain0 (regardless of temperature filtering).", ); expect(logMessages).toContain( "error: No darks available for Light_60.0s_Bin1_S_gain100 with temperature window +-3.", ); expect(logMessages).toContain( "info: There are 1 darks for Light_60.0s_Bin1_S_gain100 if we ignore temperature.", ); }); it("should warn if multiples darks and biases sequences", async () => { promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ selectedInputSubDirectory: "Use Autorun directory" as SelectedInputSubDirectoryChoices, } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240624-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ selectedFlatSequence: "Flat_1.0ms_Bin1_S_gain100__20240626-094304", } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); fs.writeFileSync( path.join( asiAirDirectory, "Autorun/Dark_60.0s_Bin1_S_gain100_20250101-155722_-10.0C_0001.fit", ), getRealDataFromSample("Dark"), ); fs.writeFileSync( path.join( asiAirDirectory, "Autorun/Dark_60.0s_Bin1_S_gain100_20250102-155722_-10.0C_0001.fit", ), // another sequence getRealDataFromSample("Dark"), ); fs.writeFileSync( path.join( asiAirDirectory, "Autorun/Bias_1.0ms_Bin1_gain100_20250101-101131_-9.8C_0001.fit", ), getRealDataFromSample("Bias"), ); fs.writeFileSync( path.join( asiAirDirectory, "Autorun/Bias_1.0ms_Bin1_gain100_20250102-101131_-9.8C_0001.fit", ), // another sequence getRealDataFromSample("Bias"), ); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], // No bank directory in input. }); expect(logMessages).toContain( "warning: Multiple dark sequences found for Light_60.0s_Bin1_S_gain100: 20250101-155722, 20250102-155722", ); expect(logMessages).toContain( "warning: Gathering them all for the master dark. Make sure that's what you wanted.", ); expect(logMessages).toContain( "warning: Multiple bias sequences found for Flat_1.0ms_Bin1_S_gain100: 20250101-101131, 20250102-101131", ); expect(logMessages).toContain( "warning: Gathering them all for the master bias. Make sure that's what you wanted.", ); }); }); describe("checking if project path is already populated/dir not exists etc...", () => { const logInEnquirerAskingToCreateDirectory = "Directory tmp/project does not exist. Do you want to create it?"; const logInEnquirerAskOverwrite = "Directory tmp/project already have a _poto_siril.json. Continue?"; const logAbort = "warning: Aborted."; const logAfterTheCheckDirectory = "step: Reading input directories"; beforeEach(() => { const planDirectory = `${asiAirDirectory}/Plan`; fs.removeSync(planDirectory); const FlatDirectory = `${asiAirDirectory}/Autorun/Flat`; fs.removeSync(FlatDirectory); }); it("should ask to create project directory because the dir does not exist", async () => { promptMock .mockResolvedValueOnce({ createProjectDirectory: true, } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], }); expect( logMessages.filter(x => x.includes(logInEnquirerAskingToCreateDirectory), ), ).toHaveLength(1); expect( logMessages.filter(x => x.includes(logInEnquirerAskOverwrite)), ).toHaveLength(0); expect(logMessages).not.toContain(logAbort); expect(logMessages).toContain(logAfterTheCheckDirectory); }); it("should ask to create project directory because the dir does not exist (abort)", async () => { promptMock.mockResolvedValueOnce({ createProjectDirectory: false, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], }); expect( logMessages.filter(x => x.includes(logInEnquirerAskingToCreateDirectory), ), ).toHaveLength(1); expect( logMessages.filter(x => x.includes(logInEnquirerAskOverwrite)), ).toHaveLength(0); expect(logMessages).toContain(logAbort); expect(logMessages).not.toContain(logAfterTheCheckDirectory); }); it("should not ask to create project directory because the dir exists (empty)", async () => { fs.mkdirSync(projectDirectory, { recursive: true }); promptMock .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], }); expect( logMessages.filter(x => x.includes(logInEnquirerAskingToCreateDirectory), ), ).toHaveLength(0); expect( logMessages.filter(x => x.includes(logInEnquirerAskOverwrite)), ).toHaveLength(0); expect(logMessages).not.toContain(logAbort); expect(logMessages).toContain(logAfterTheCheckDirectory); }); it("should abort if we decide not to (project dir already exists)", async () => { fs.mkdirSync(projectDirectory, { recursive: true }); fs.writeFileSync(path.join(projectDirectory, POTO_JSON), "{}"); promptMock.mockResolvedValueOnce({ continueEvenIfProjectAlreadyExists: false, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], }); expect( logMessages.filter(x => x.includes(logInEnquirerAskingToCreateDirectory), ), ).toHaveLength(0); expect( logMessages.filter(x => x.includes(logInEnquirerAskOverwrite)), ).toHaveLength(1); expect(logMessages).toContain(logAbort); expect(logMessages).not.toContain(logAfterTheCheckDirectory); }); it("should continue if we decide to (project dir already exists)", async () => { fs.mkdirSync(projectDirectory, { recursive: true }); fs.writeFileSync(path.join(projectDirectory, POTO_JSON), "{}"); promptMock .mockResolvedValueOnce({ continueEvenIfProjectAlreadyExists: true, } as never) .mockResolvedValueOnce({ darkTemperatureTolerance: 3, } as never) .mockResolvedValueOnce({ go: true, } as never); await prepare({ projectDirectory, inputDirectories: [asiAirDirectory], }); expect( logMessages.filter(x => x.includes(logInEnquirerAskingToCreateDirectory), ), ).toHaveLength(0); expect( logMessages.filter(x => x.includes(logInEnquirerAskOverwrite)), ).toHaveLength(1); expect(logMessages).not.toContain(logAbort); expect(logMessages).toContain(logAfterTheCheckDirectory); }); }); describe("clear function tests", () => { it("should throw not asiair directory", async () => { expect(() => clear(bankDirectory)).toThrow("Not an ASIAIR directory!"); }); }); });