diff --git a/src/serviceModules/FileSystemAdapters/ObsidianStorageAdapter.unit.spec.ts b/src/serviceModules/FileSystemAdapters/ObsidianStorageAdapter.unit.spec.ts new file mode 100644 index 00000000..7172879f --- /dev/null +++ b/src/serviceModules/FileSystemAdapters/ObsidianStorageAdapter.unit.spec.ts @@ -0,0 +1,32 @@ +import { describe, expect, it, vi } from "vitest"; +import type { App } from "obsidian"; +import { ObsidianStorageAdapter } from "./ObsidianStorageAdapter"; + +describe("ObsidianStorageAdapter", () => { + it("floors write-option timestamps before calling Obsidian storage methods", async () => { + const write = vi.fn().mockResolvedValue(undefined); + const writeBinary = vi.fn().mockResolvedValue(undefined); + const append = vi.fn().mockResolvedValue(undefined); + const app = { + vault: { + adapter: { + write, + writeBinary, + append, + }, + }, + } as unknown as App; + const adapter = new ObsidianStorageAdapter(app); + const options = { ctime: 1778511180024.462, mtime: 1778511180999.913 }; + const expectedOptions = { ctime: 1778511180024, mtime: 1778511180999 }; + + await adapter.write("note.md", "text", options); + await adapter.writeBinary("image.bin", new ArrayBuffer(0), options); + await adapter.append("log.md", "text", options); + + expect(write).toHaveBeenCalledWith("note.md", "text", expectedOptions); + expect(writeBinary).toHaveBeenCalledWith("image.bin", expect.any(ArrayBuffer), expectedOptions); + expect(append).toHaveBeenCalledWith("log.md", "text", expectedOptions); + expect(options).toEqual({ ctime: 1778511180024.462, mtime: 1778511180999.913 }); + }); +}); diff --git a/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.unit.spec.ts b/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.unit.spec.ts index 5a307d52..0c22f212 100644 --- a/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.unit.spec.ts +++ b/src/serviceModules/FileSystemAdapters/ObsidianVaultAdapter.unit.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from "vitest"; import type { App, TFile } from "obsidian"; import { ObsidianVaultAdapter } from "./ObsidianVaultAdapter"; -describe("ObsidianVaultAdapter.read", () => { +describe("ObsidianVaultAdapter", () => { it("preserves a UTF-8 BOM so the content size matches the file stat", async () => { const path = "Transcripts/字幕.md"; const contentWithoutBom = "字幕の検証行です。\n"; @@ -34,4 +34,34 @@ describe("ObsidianVaultAdapter.read", () => { expect(adapterRead).toHaveBeenCalledWith(path); expect(read).not.toHaveBeenCalled(); }); + + it("floors write-option timestamps before calling Obsidian vault methods", async () => { + const modify = vi.fn().mockResolvedValue(undefined); + const modifyBinary = vi.fn().mockResolvedValue(undefined); + const create = vi.fn().mockResolvedValue({}); + const createBinary = vi.fn().mockResolvedValue({}); + const app = { + vault: { + modify, + modifyBinary, + create, + createBinary, + }, + } as unknown as App; + const file = { path: "note.md" } as TFile; + const adapter = new ObsidianVaultAdapter(app); + const options = { ctime: 1778511180024.462, mtime: 1778511180999.913 }; + const expectedOptions = { ctime: 1778511180024, mtime: 1778511180999 }; + + await adapter.modify(file, "text", options); + await adapter.modifyBinary(file, new ArrayBuffer(0), options); + await adapter.create("created.md", "text", options); + await adapter.createBinary("created.bin", new ArrayBuffer(0), options); + + expect(modify).toHaveBeenCalledWith(file, "text", expectedOptions); + expect(modifyBinary).toHaveBeenCalledWith(file, expect.any(ArrayBuffer), expectedOptions); + expect(create).toHaveBeenCalledWith("created.md", "text", expectedOptions); + expect(createBinary).toHaveBeenCalledWith("created.bin", expect.any(ArrayBuffer), expectedOptions); + expect(options).toEqual({ ctime: 1778511180024.462, mtime: 1778511180999.913 }); + }); }); diff --git a/src/serviceModules/FileSystemAdapters/sanitizeWriteOptions.ts b/src/serviceModules/FileSystemAdapters/sanitizeWriteOptions.ts index 4cb92355..3c055c16 100644 --- a/src/serviceModules/FileSystemAdapters/sanitizeWriteOptions.ts +++ b/src/serviceModules/FileSystemAdapters/sanitizeWriteOptions.ts @@ -1,4 +1,4 @@ -import type { UXDataWriteOptions } from "@lib/common/types"; +import type { UXDataWriteOptions } from "@vrtmrz/livesync-commonlib/compat/common/types"; /** * Coerce the timestamp fields of a write-options object to integer milliseconds.