export async function runBrowserAppOpfsSections(context) { const { browserHasOpfs, createHiddenAppFrame, disposeAppFrame, expectIncludes, expectText, getAppFrameSimulator, parseAppFrameProgram, runSection, waitFor, waitForAppAlarm, waitForAppControls, } = context; if (!browserHasOpfs()) { return; } await runSection("browser app opfs save", async () => { const appFrame = await createHiddenAppFrame(); try { await waitForAppControls(appFrame, "app frame did not load CNC controls"); parseAppFrameProgram(appFrame, "G21 G90\nG0 X1\nG28.1\nM30\n"); await waitForAppAlarm(appFrame, "OK ", "app frame did not parse program"); const appSimulator = await getAppFrameSimulator(appFrame, "app frame did not create OPFS simulator workspace"); const savedProgram = new TextDecoder().decode(await appSimulator.fs.opfs.readFile("programs/current.ngc")); expectText(savedProgram, "G21 G90\nG0 X1\nG28.1\nM30\n", "app frame did not persist current program into OPFS"); const savedParameterFile = new TextDecoder().decode(await appSimulator.fs.opfs.readFile("parameters/rs274ngc.var")); expectIncludes(savedParameterFile, "5161\t1.000000", "app frame did not persist LinuxCNC parameter state into OPFS"); await appSimulator.fs.opfs.removeFile("parameters/rs274ngc.var.bak"); parseAppFrameProgram(appFrame, "G21 G90\nG0 X2\nG28.1\nM30\n"); await waitFor( () => appFrame.contentDocument?.querySelector("#axisX")?.value === "2.000", "app frame did not parse second program for parameter backup coverage", ); // LinuxCNC source basis: rs274ngc_pre.cc save_parameters() // preserves the previous parameter file as filename + ".bak". const updatedParameterFile = new TextDecoder().decode(await appSimulator.fs.opfs.readFile("parameters/rs274ngc.var")); expectIncludes(updatedParameterFile, "5161\t2.000000", "app frame did not replace LinuxCNC parameter state after second parse"); const savedParameterBackup = new TextDecoder().decode(await appSimulator.fs.opfs.readFile("parameters/rs274ngc.var.bak")); expectIncludes(savedParameterBackup, "5161\t1.000000", "app frame did not persist LinuxCNC parameter backup into OPFS"); await appSimulator.fs.opfs.removeFile("parameters/rs274ngc.var.bak"); const backupDirectory = appSimulator.fs.opfs.resolvePath("parameters/rs274ngc.var.bak"); appSimulator.fs.module.FS.mkdir(backupDirectory); await appSimulator.fs.opfs.persistDirectory("parameters/rs274ngc.var.bak"); parseAppFrameProgram(appFrame, "G21 G90\nG0 X3\nG28.1\nM30\n"); await waitFor( () => appFrame.contentDocument?.querySelector("#axisX")?.value === "3.000", "app frame did not parse third program for backup-directory coverage", ); const directoryBackupParameterFile = new TextDecoder().decode(await appSimulator.fs.opfs.readFile("parameters/rs274ngc.var")); expectIncludes(directoryBackupParameterFile, "5161\t3.000000", "app frame did not save LinuxCNC parameter state when backup link failed"); await context.expectOpfsDirectoryStat( appSimulator, "parameters/rs274ngc.var.bak", "app frame removed an existing OPFS backup directory after LinuxCNC non-fatal backup failure", ); // LinuxCNC source basis: rs274ngc_pre.cc save_parameters() // renames filename + ".new" over filename after a successful save. await context.expectOpfsMissing( appSimulator, "parameters/rs274ngc.var.new", "app frame did not clean up LinuxCNC temporary parameter file in OPFS", ); } finally { await disposeAppFrame(appFrame); } }); await runSection("browser app opfs restore", async () => { const restoredAppFrame = await createHiddenAppFrame(); try { await waitForAppControls(restoredAppFrame, "restored app frame did not load CNC controls"); await waitFor(() => { const restoredInput = restoredAppFrame.contentDocument?.querySelector("#programInput"); return restoredInput?.value === "G21 G90\nG0 X3\nG28.1\nM30\n"; }, "app frame did not restore current program from OPFS after reload"); await waitForAppAlarm( restoredAppFrame, "OPFS PROGRAM RESTORED", "app frame did not report OPFS program restore after reload", ); await getAppFrameSimulator(restoredAppFrame, "restored app frame did not create OPFS simulator workspace"); parseAppFrameProgram( restoredAppFrame, "G21 G90\nF100\nO10 if [#5161 EQ 3]\nG1 X13\nO10 endif\nM30\n", ); await waitForAppAlarm( restoredAppFrame, "OK ", "restored app frame did not parse program with reloaded parameter state", ); await waitFor( () => restoredAppFrame.contentDocument?.querySelector("#axisX")?.value === "13.000", "app frame did not reload LinuxCNC parameter state from OPFS after reload", ); } finally { await disposeAppFrame(restoredAppFrame); } }); }