diff --git a/packages/playground/website/src/lib/state/opfs/opfs-site-storage.spec.ts b/packages/playground/website/src/lib/state/opfs/opfs-site-storage.spec.ts index 0c4a9454b7a..6add1f7b6da 100644 --- a/packages/playground/website/src/lib/state/opfs/opfs-site-storage.spec.ts +++ b/packages/playground/website/src/lib/state/opfs/opfs-site-storage.spec.ts @@ -7,11 +7,13 @@ describe('opfsSiteStorage', () => { let storage: NonNullable; let loadPersistedBlueprintBundle: ReturnType; let loadPersistedBlueprintBundleFromPath: ReturnType; + let loggerError: ReturnType; beforeEach(async () => { vi.resetModules(); loadPersistedBlueprintBundle = vi.fn(); loadPersistedBlueprintBundleFromPath = vi.fn(); + loggerError = vi.fn(); const activeWorkerWrites = new Set(); opfsRoot = new MemoryDirectoryHandle(''); vi.stubGlobal('navigator', { @@ -73,6 +75,9 @@ describe('opfsSiteStorage', () => { vi.doMock('@wp-playground/blueprints', () => ({ getBlueprintDeclaration: vi.fn(async (blueprint) => blueprint), })); + vi.doMock('@php-wasm/logger', () => ({ + logger: { error: loggerError }, + })); const module = await import('./opfs-site-storage'); storage = module.opfsSiteStorage!; @@ -107,6 +112,14 @@ describe('opfsSiteStorage', () => { ).rejects.toThrow("Site with slug 'a/b' already exists."); }); + it('silently skips directories left by interrupted first saves', async () => { + const sitesRoot = await getSitesRoot(opfsRoot); + await sitesRoot.getDirectoryHandle('site-incomplete', { create: true }); + + await expect(storage.list()).resolves.toEqual([]); + expect(loggerError).not.toHaveBeenCalled(); + }); + it('stores setup URL params alongside site metadata', async () => { const originalUrlParams = { searchParams: { diff --git a/packages/playground/website/src/lib/state/opfs/opfs-site-storage.ts b/packages/playground/website/src/lib/state/opfs/opfs-site-storage.ts index 84cd9f8ea41..d0e2fafb795 100644 --- a/packages/playground/website/src/lib/state/opfs/opfs-site-storage.ts +++ b/packages/playground/website/src/lib/state/opfs/opfs-site-storage.ts @@ -167,6 +167,11 @@ class OpfsSiteStorage { sites.push(site); } } catch (e) { + if (isMissingOpfsEntry(e)) { + // An interrupted first save can leave the directory behind + // before its metadata file is written. + continue; + } // @TODO: Still return this site's info, just in an error state. logger.error(`Error reading site ${entry.name}:`, e); // @TODO: Handle per-site errors somehow.