import assert from "node:assert/strict"; import { getOpfsRoot, loadTextFile, saveTextFile, } from "../../../runtime/opfs/file-service.js"; class MockFileHandle { constructor(name) { this.name = name; this.textValue = ""; } async createWritable() { return { write: async (text) => { this.textValue = String(text); }, close: async () => {}, }; } async getFile() { return { text: async () => this.textValue, }; } } class MockDirectoryHandle { constructor(name = "") { this.name = name; this.dirs = new Map(); this.files = new Map(); } async getDirectoryHandle(name, options = {}) { if (!this.dirs.has(name)) { if (!options.create) { throw new Error(`missing directory: ${name}`); } this.dirs.set(name, new MockDirectoryHandle(name)); } return this.dirs.get(name); } async getFileHandle(name, options = {}) { if (!this.files.has(name)) { if (!options.create) { throw new Error(`missing file: ${name}`); } this.files.set(name, new MockFileHandle(name)); } return this.files.get(name); } } const root = new MockDirectoryHandle(); const storage = { getDirectory: async () => root, }; assert.equal(await getOpfsRoot(storage), root); await saveTextFile( "linuxcnc/machines/xyzab.ini", "[EMC]\nMACHINE = opfs-smoke\n", storage, ); assert.equal( await loadTextFile("linuxcnc/machines/xyzab.ini", storage), "[EMC]\nMACHINE = opfs-smoke\n", ); await assert.rejects( () => loadTextFile("linuxcnc/machines/missing.ini", storage), /missing file/, ); await assert.rejects( () => saveTextFile("../escape.ini", "", storage), /Invalid OPFS path/, ); await assert.rejects( () => getOpfsRoot({}), /OPFS is not available/, ); console.log("opfs_file_service_node_smoke=ok");