mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-16 17:46:07 +00:00
test: cover case-only file renames in Obsidian
This commit is contained in:
@@ -859,6 +859,8 @@ If this enabled, all chunks will be stored with the revision made from its conte
|
||||
Setting key: handleFilenameCaseSensitive
|
||||
If this enabled, All files are handled as case-Sensitive (Previous behaviour).
|
||||
|
||||
When this setting is disabled, changing only the letter case of a file name within the same directory is synchronised as a rename. Changing the letter case of a directory name is not supported by this handling.
|
||||
|
||||
### 4. Compatibility (Internal API Usage)
|
||||
|
||||
#### Scan changes on customisation sync
|
||||
|
||||
@@ -91,7 +91,7 @@ LIVESYNC_CLI_COMMAND="docker run --rm --network host --user $(id -u):$(id -g) --
|
||||
|
||||
`test:e2e:obsidian:startup-scan` configures a temporary CouchDB database, stops Obsidian, writes a note directly into the vault, restarts Obsidian, and verifies from CouchDB that the boot-time scan picked up the offline file.
|
||||
|
||||
`test:e2e:obsidian:two-vault-sync` runs a two-vault note synchronisation workflow. It verifies note creation, update, rename, deletion, per-device target filters where one vault ignores a note that the other vault synchronises, and a separate encrypted round-trip with Path Obfuscation enabled. The optional Markdown conflict automatic merge check can be enabled with `E2E_OBSIDIAN_INCLUDE_MARKDOWN_CONFLICT=true`, but it is not part of the default local suite.
|
||||
`test:e2e:obsidian:two-vault-sync` runs a two-vault note synchronisation workflow. It verifies note creation, update, ordinary rename, a case-only file name change within the same directory, deletion, per-device target filters where one vault ignores a note that the other vault synchronises, and a separate encrypted round-trip with Path Obfuscation enabled. Directory case changes deliberately remain outside this scenario because they require directory-aware rename handling. The optional Markdown conflict automatic merge check can be enabled with `E2E_OBSIDIAN_INCLUDE_MARKDOWN_CONFLICT=true`, but it is not part of the default local suite.
|
||||
|
||||
`test:e2e:obsidian:hidden-file-snippet-sync` runs a two-vault hidden file round-trip. It verifies creation and deletion of a real `.obsidian/snippets/*.css` file, automatic JSON conflict merging for a hidden file with the merged result propagated by a second synchronisation, manual JSON Resolve dialogue application through Obsidian's UI, and per-device target patterns where one vault ignores a hidden file that the other vault synchronises.
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ const updatePath = "E2E/two-vault/update.md";
|
||||
const deletePath = "E2E/two-vault/delete.md";
|
||||
const renameFromPath = "E2E/two-vault/rename-source.md";
|
||||
const renameToPath = "E2E/two-vault/renamed/rename-target.md";
|
||||
const caseRenameFromPath = "E2E/two-vault/Case-Rename.md";
|
||||
const caseRenameToPath = "E2E/two-vault/case-rename.md";
|
||||
const conflictPath = "E2E/two-vault/conflict.md";
|
||||
const targetMismatchPath = "E2E/two-vault/target-mismatch.md";
|
||||
const encryptedPath = "E2E/two-vault/encrypted.md";
|
||||
@@ -362,6 +364,39 @@ async function runRename(context: RunnerContext, vaultA: TemporaryVault, vaultB:
|
||||
console.log("Two-vault note rename round-tripped.");
|
||||
}
|
||||
|
||||
async function runCaseOnlyRename(
|
||||
context: RunnerContext,
|
||||
vaultA: TemporaryVault,
|
||||
vaultB: TemporaryVault
|
||||
): Promise<void> {
|
||||
const fileContent = "# Case-only rename\n\nThe document ID should remain live.\n";
|
||||
|
||||
let session = await startConfiguredSession(context, vaultA);
|
||||
await writeNoteViaObsidian(context.cliBinary, session.cliEnv, caseRenameFromPath, fileContent);
|
||||
await uploadNote(context, session, caseRenameFromPath);
|
||||
await session.app.stop();
|
||||
|
||||
session = await startConfiguredSession(context, vaultB);
|
||||
await syncAndApply(context, session);
|
||||
await waitForPathContent(vaultB.path, caseRenameFromPath, (content) => content === fileContent);
|
||||
await session.app.stop();
|
||||
|
||||
session = await startConfiguredSession(context, vaultA);
|
||||
await renameNoteViaObsidian(context.cliBinary, session.cliEnv, caseRenameFromPath, caseRenameToPath);
|
||||
await waitForLocalDatabaseEntry(context.cliBinary, session.cliEnv, caseRenameToPath);
|
||||
await pushLocalChanges(context.cliBinary, session.cliEnv);
|
||||
await session.app.stop();
|
||||
|
||||
session = await startConfiguredSession(context, vaultB);
|
||||
await syncAndApply(context, session);
|
||||
const renamedOnB = await waitForPathContent(vaultB.path, caseRenameToPath, (content) => content === fileContent);
|
||||
await waitForPathDeleted(vaultB.path, caseRenameFromPath);
|
||||
await session.app.stop();
|
||||
|
||||
assertEqual(renamedOnB, fileContent, "Case-only note rename did not round-trip to the second vault.");
|
||||
console.log("Two-vault case-only note rename round-tripped without a tombstone.");
|
||||
}
|
||||
|
||||
async function runEncryptedRoundTrip(
|
||||
context: RunnerContext,
|
||||
vaultA: TemporaryVault,
|
||||
@@ -498,6 +533,7 @@ async function main(): Promise<void> {
|
||||
|
||||
await runCreateUpdateDelete(context, vaultA, vaultB);
|
||||
await runRename(context, vaultA, vaultB);
|
||||
await runCaseOnlyRename(context, vaultA, vaultB);
|
||||
if (process.env.E2E_OBSIDIAN_INCLUDE_MARKDOWN_CONFLICT === "true") {
|
||||
await runMarkdownAutoMerge(context, vaultA, vaultB);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user