Files
obsidian-livesync/test/e2e-cli/test-remote-commands.ts
T
vorotamoroz 2433d117c2 Migrate CLI E2E tests to Node.js 26
Run the CLI subprocess suites and benchmark tools as native TypeScript with
node:test, and move them under test/e2e-cli.

Update CI and Compose runners, run local smoke tests on Linux, macOS, and
Windows, and collect source-mapped CLI coverage with c8.
2026-10-31 06:01:30 +00:00

130 lines
5.6 KiB
TypeScript

/**
* Node.js port of test-remote-commands-linux.sh
*
* Tests remote management commands: remote-status, lock-remote, unlock-remote,
* and mark-resolved.
*
* Scenario:
* 1. Start CouchDB, create a test database, and perform an initial sync.
* 2. Run remote-status and assert that the output contains the database name in JSON format.
* 3. Run lock-remote and verify that the remote database is locked.
* 4. Lock the remote database milestone manually, verify status, and run unlock-remote.
* Assert that the output of unlock-remote contains the unlocked verification status.
* 5. Lock the remote database milestone manually, run mark-resolved, and verify that the
* current device is accepted.
*
* Run:
* node --test test-remote-commands.ts
*/
import { test } from "node:test";
import { mkdir } from "node:fs/promises";
import { join } from "node:path";
import { TempDir } from "./helpers/temp.ts";
import { runCli, assertContains } from "./helpers/cli.ts";
import { applyCouchdbSettings, initSettingsFile } from "./helpers/settings.ts";
import { startCouchdb, stopCouchdb, updateCouchdbDoc } from "./helpers/docker.ts";
async function runCliCombinedOrFail(...args: string[]): Promise<string> {
const res = await runCli(...args);
if (res.code !== 0) {
throw new Error(`CLI exited with code ${res.code}\nstdout: ${res.stdout}\nstderr: ${res.stderr}`);
}
return res.combined;
}
test("remote management commands", async () => {
await using workDir = await TempDir.create("livesync-cli-remote-cmds");
const settingsFile = workDir.join("settings.json");
const vaultDir = workDir.join("vault");
await mkdir(vaultDir, { recursive: true });
const uri = process.env["COUCHDB_URI"] ?? "http://127.0.0.1:5989/";
const user = process.env["COUCHDB_USER"] ?? "admin";
const password = process.env["COUCHDB_PASSWORD"] ?? "testpassword";
const dbSuffix = `${Date.now()}-${Math.floor(Math.random() * 10000)}`;
const dbname = process.env["COUCHDB_DBNAME"] ?? `remotes-${dbSuffix}`;
const shouldStartDocker = process.env["LIVESYNC_START_DOCKER"] !== "0";
const keepDocker = process.env["LIVESYNC_DEBUG_KEEP_DOCKER"] === "1";
if (shouldStartDocker) {
await startCouchdb(uri, user, password, dbname);
}
try {
await initSettingsFile(settingsFile);
await applyCouchdbSettings(settingsFile, uri, user, password, dbname, true);
console.log("[INFO] Performing initial sync to create milestone document...");
await runCliCombinedOrFail(vaultDir, "--settings", settingsFile, "sync");
// 1. remote-status outputs valid JSON with CouchDB details
console.log("[CASE] remote-status outputs valid JSON with CouchDB details");
const statusOutput = await runCliCombinedOrFail(vaultDir, "--settings", settingsFile, "remote-status");
assertContains(statusOutput, `"db_name": "${dbname}"`, "remote-status should return JSON containing db_name");
console.log("[PASS] remote-status verified");
// 2. lock-remote locks and verifies state
console.log("[CASE] lock-remote locks and verifies state");
const lockOutput = await runCliCombinedOrFail(vaultDir, "--settings", settingsFile, "lock-remote");
assertContains(
lockOutput,
"[Verification] Remote Database: LOCKED",
"lock-remote output should show that the remote database is locked"
);
console.log("[PASS] lock-remote verified");
// 3. unlock-remote unlocks and verifies state
console.log("[CASE] unlock-remote unlocks and verifies state");
// Manually lock milestone
console.log("[INFO] Manually locking milestone...");
await updateCouchdbDoc(uri, user, password, `${dbname}/_local/obsydian_livesync_milestone`, (doc) => {
doc.locked = true;
doc.accepted_nodes = [];
return doc;
});
// Run unlock-remote and verify output contains verification message
const unlockOutput = await runCliCombinedOrFail(vaultDir, "--settings", settingsFile, "unlock-remote");
assertContains(
unlockOutput,
"[Verification] Remote Database: UNLOCKED",
"unlock-remote output should contain verification status"
);
console.log("[PASS] unlock-remote verified");
// 4. mark-resolved resolves and verifies state
console.log("[CASE] mark-resolved resolves and verifies state");
// Manually lock milestone
console.log("[INFO] Manually locking milestone...");
await updateCouchdbDoc(uri, user, password, `${dbname}/_local/obsydian_livesync_milestone`, (doc) => {
doc.locked = true;
doc.accepted_nodes = [];
return doc;
});
// Run mark-resolved and verify output contains verification messages
const resolvedOutput = await runCliCombinedOrFail(vaultDir, "--settings", settingsFile, "mark-resolved");
assertContains(
resolvedOutput,
"[Verification] Remote Database: LOCKED",
"mark-resolved output should show that the remote database remains locked"
);
assertContains(
resolvedOutput,
"ACCEPTED",
"mark-resolved output should show that the current device node is accepted"
);
console.log("[PASS] mark-resolved verified");
console.log("[ALL PASS] All remote CLI commands verified successfully");
} finally {
if (shouldStartDocker && !keepDocker) {
await stopCouchdb().catch(() => {});
}
}
});