Refresh setup guides and capture fixtures
@@ -107,15 +107,30 @@ Use this path when CouchDB is ready but a Setup URI is unavailable. It configure
|
||||
1. Install and enable Self-hosted LiveSync in the intended Vault.
|
||||
2. Select the `Welcome to Self-hosted LiveSync` Notice, choose `I am setting this up for the first time`, then confirm that you want to set up a new synchronisation.
|
||||
3. On `Connection Method`, select `Configure a remote manually`, then select `Proceed with manual configuration`.
|
||||
|
||||

|
||||
|
||||
4. On `End-to-End Encryption`, decide how the synchronised data will be protected.
|
||||
- For an ordinary new Vault, enable `End-to-End Encryption` and enter a strong Vault encryption passphrase.
|
||||
- Enable `Obfuscate Properties` if remote document properties should also be concealed.
|
||||
- Store the Vault encryption passphrase securely. It is separate from the passphrase used to protect a Setup URI.
|
||||
|
||||

|
||||
|
||||
5. On `Choose a synchronisation remote`, select `CouchDB`, then select `Continue to CouchDB setup`.
|
||||
|
||||

|
||||
|
||||
6. Enter the complete CouchDB URL, username, password, and database name.
|
||||
- Obsidian Mobile requires HTTPS. Plain HTTP is suitable only for a trusted local connection from a desktop device.
|
||||
- Use credentials which are allowed to connect to the selected database and, when configuring the first device, create it if it does not exist.
|
||||
|
||||

|
||||
|
||||
7. `Check server requirements` is optional. It sends the displayed credentials to the configured server through Obsidian's internal request API, and some checks require CouchDB administrator access. The initial check is read-only. If it offers a server change, review and confirm that individual change separately.
|
||||
|
||||

|
||||
|
||||
8. Select `Create or connect to database and continue`. Onboarding requires this connection test to succeed.
|
||||
9. Review `Setup Complete: Preparing to Initialise Server`, then select `Restart and Initialise Server`.
|
||||
10. Read the final overwrite warning. Select `I Understand, Overwrite Server` only when this device is intentionally the source of truth and a current backup exists.
|
||||
|
||||
@@ -47,7 +47,10 @@ A pattern containing only `snippets` does not admit the `.obsidian` parent, so t
|
||||

|
||||
|
||||
2. Under `Enable Hidden File Sync`, select the initialisation direction chosen above.
|
||||
3. Keep Obsidian open while the initial scan and synchronisation finish.
|
||||
3. Keep Obsidian open while the initial scan and synchronisation finish. A progress Notice appears when preparation begins and remains visible while the initial scan is running.
|
||||
|
||||

|
||||
|
||||
4. Restart Obsidian when the completion Notice recommends it.
|
||||
5. Confirm that the expected hidden files, and only those files, are present in the remote synchronisation state.
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
@@ -1,4 +1,6 @@
|
||||
import { assertLocatorWithinViewport, assertNoHorizontalOverflow } from "@vrtmrz/obsidian-test-session";
|
||||
import type { ObsidianLiveSyncSettings } from "@vrtmrz/livesync-commonlib/compat/common/models/setting.type";
|
||||
import { upsertRemoteConfigurationInPlace } from "@vrtmrz/livesync-commonlib/remote-configurations";
|
||||
import type { Page } from "playwright";
|
||||
import { discoverObsidianCli, requireObsidianBinary } from "../runner/environment.ts";
|
||||
import {
|
||||
@@ -47,6 +49,17 @@ async function verifyP2PStatusPane(filename: string, mobile: boolean): Promise<s
|
||||
state: "visible",
|
||||
timeout: uiTimeoutMs,
|
||||
});
|
||||
const remoteSelector = pane.getByRole("combobox", { name: "Select active P2P remote" });
|
||||
await remoteSelector.waitFor({ state: "visible", timeout: uiTimeoutMs });
|
||||
if ((await remoteSelector.inputValue()).trim() === "") {
|
||||
throw new Error("The configured P2P status pane did not select an active P2P remote.");
|
||||
}
|
||||
if (
|
||||
(await pane.getByText("Please select an active P2P remote configuration to change P2P sync targets.").count()) !==
|
||||
0
|
||||
) {
|
||||
throw new Error("The configured P2P status pane still requested an active P2P remote.");
|
||||
}
|
||||
await assertNoHorizontalOverflow(page, pane, { label: "P2P status pane" });
|
||||
if (mobile) {
|
||||
await assertLocatorWithinViewport(page, pane, { label: "mobile P2P status pane" });
|
||||
@@ -116,25 +129,41 @@ async function dismissOpenNotices(page: Page): Promise<void> {
|
||||
throw new Error("Transient Obsidian notices did not become quiet before the P2P status screenshot.");
|
||||
}
|
||||
|
||||
const basePluginData = createE2eCouchDbPluginData(
|
||||
{
|
||||
uri: "http://127.0.0.1:5984",
|
||||
username: "",
|
||||
password: "",
|
||||
dbName: "p2p-pane-ui-only",
|
||||
},
|
||||
{
|
||||
notifyThresholdOfRemoteStorageSize: -1,
|
||||
periodicReplication: false,
|
||||
P2P_Enabled: false,
|
||||
P2P_AutoStart: false,
|
||||
syncAfterMerge: false,
|
||||
syncOnEditorSave: false,
|
||||
syncOnFileOpen: false,
|
||||
syncOnSave: false,
|
||||
syncOnStart: false,
|
||||
}
|
||||
);
|
||||
function createBaseP2PPluginData(): Record<string, unknown> {
|
||||
return createE2eCouchDbPluginData(
|
||||
{
|
||||
uri: "http://127.0.0.1:5984",
|
||||
username: "",
|
||||
password: "",
|
||||
dbName: "p2p-pane-ui-only",
|
||||
},
|
||||
{
|
||||
notifyThresholdOfRemoteStorageSize: -1,
|
||||
periodicReplication: false,
|
||||
P2P_Enabled: false,
|
||||
P2P_AutoStart: false,
|
||||
syncAfterMerge: false,
|
||||
syncOnEditorSave: false,
|
||||
syncOnFileOpen: false,
|
||||
syncOnSave: false,
|
||||
syncOnStart: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createConfiguredP2PPluginData(): Record<string, unknown> {
|
||||
const pluginData = {
|
||||
...createBaseP2PPluginData(),
|
||||
P2P_roomID: "configured-p2p-room",
|
||||
P2P_passphrase: "configured-p2p-passphrase",
|
||||
};
|
||||
upsertRemoteConfigurationInPlace(pluginData as ObsidianLiveSyncSettings, "p2p", {
|
||||
id: "e2e-p2p",
|
||||
name: "P2P Remote",
|
||||
activateForP2P: true,
|
||||
});
|
||||
return pluginData;
|
||||
}
|
||||
|
||||
async function withP2PSession(
|
||||
binary: string,
|
||||
@@ -170,18 +199,14 @@ async function main(): Promise<void> {
|
||||
throw new Error(`Could not find obsidian-cli. Checked paths: ${cli.checked.join(", ")}`);
|
||||
}
|
||||
|
||||
await withP2PSession(binary, cli.binary, basePluginData, async () => {
|
||||
await withP2PSession(binary, cli.binary, createBaseP2PPluginData(), async () => {
|
||||
await assertP2PUIIsOptIn();
|
||||
});
|
||||
|
||||
await withP2PSession(
|
||||
binary,
|
||||
cli.binary,
|
||||
{
|
||||
...basePluginData,
|
||||
P2P_roomID: "configured-p2p-room",
|
||||
P2P_passphrase: "configured-p2p-passphrase",
|
||||
},
|
||||
createConfiguredP2PPluginData(),
|
||||
async () => {
|
||||
await assertConfiguredP2PUIIsAvailable();
|
||||
const desktopScreenshot = await verifyP2PStatusPane("p2p-status-pane.png", false);
|
||||
|
||||