Limit commands to applicable contexts

This commit is contained in:
vorotamoroz
2026-07-24 16:13:49 +00:00
parent 6afeb0b409
commit 0e5475b7e3
27 changed files with 727 additions and 75 deletions
+1 -1
View File
@@ -81,7 +81,7 @@ The underlying `test:e2e:obsidian:<scenario>` scripts remain available for an im
`test:contract:context:cli` builds the Node CLI and runs its existing Deno setup, put, read, list, information, remove, conflict-resolution, and revision workflow. `test:contract:context:obsidian` builds the plug-in and runs the real-Obsidian smoke test, including the Context inspection. These runtime scripts are local validation entry points and are not added to the default CI gate by this change.
`test:e2e:obsidian:onboarding-invitation` starts an unconfigured temporary Vault with no plug-in data and verifies that startup selects Commonlib's new-Vault recommendations, offers the setup wizard without opening it, and does not scan Vault files automatically. It checks the invitation action and introduction in mobile test mode, then uses the permanent command to reopen the wizard on the desktop. This scenario owns the unconfigured-startup boundary only; configured compatibility review remains covered by `settings-ui`, and the setup workflows remain covered by their dedicated scenarios.
`test:e2e:obsidian:onboarding-invitation` starts an unconfigured temporary Vault with no plug-in data and verifies that startup selects Commonlib's new-Vault recommendations, offers the setup wizard without opening it, and does not scan Vault files automatically. It checks the invitation action and introduction in mobile test mode, then reopens the wizard from **Self-hosted LiveSync settings****Setup** on the desktop. This scenario owns the unconfigured-startup boundary only; configured compatibility review remains covered by `settings-ui`, and the setup workflows remain covered by their dedicated scenarios.
`test:e2e:obsidian:dialog-mounts` starts a temporary real Obsidian session and exercises remote selection and CouchDB settings through `SetupManager`, plus Setup URI entry through the registered command. It verifies the compatibility pause and remote-size review, the distinction between a central data-storage server and P2P signalling, the explicit tested and untested CouchDB save actions, the internal-API warning, the Setup URI controls, automatic adjustment when differences are limited to compatible chunk settings, and both manual configuration-mismatch routes. The same session opens the live log and generated full report, reaches the `Hatch` recovery controls, writes and removes its own persistent log, and runs the missing-chunk recreation and file-verification actions against the empty disposable Vault. It captures representative desktop and mobile dialogues, checks the mobile layout and vertically stacked actions, closes each route through its normal controls, and verifies that each mounted operation settles without an error. It does not apply a remote configuration, contact a remote service, or claim to repair a deliberately damaged database.
@@ -26,7 +26,10 @@ type UnconfiguredStartupEvidence = {
};
type ObsidianTestApp = {
commands?: { executeCommandById(commandId: string): boolean };
setting?: {
open(): void;
openTabById(tabId: string): void;
};
};
type ObsidianTestGlobal = typeof globalThis & { app?: ObsidianTestApp };
@@ -151,14 +154,38 @@ async function captureAndCloseIntro(filename: string, mobile: boolean): Promise<
return screenshot;
}
async function openPermanentCommand(): Promise<void> {
const opened = await withObsidianPage(obsidianRemoteDebuggingPort(), async (page) => {
return await page.evaluate(
(commandId) => (globalThis as ObsidianTestGlobal).app?.commands?.executeCommandById(commandId) === true,
"obsidian-livesync:livesync-open-onboarding"
);
async function openOnboardingFromSettings(): Promise<void> {
await withObsidianPage(obsidianRemoteDebuggingPort(), async (page) => {
await page.evaluate(() => {
const setting = (globalThis as ObsidianTestGlobal).app?.setting;
if (setting === undefined) throw new Error("Obsidian settings are unavailable");
setting.open();
setting.openTabById("obsidian-livesync");
});
const liveSyncSettings = page.locator(".sls-setting");
await liveSyncSettings.waitFor({ state: "visible", timeout: uiTimeoutMs });
await liveSyncSettings.locator('.sls-setting-menu-btn[title="Setup"]').click({ timeout: uiTimeoutMs });
const onboardingSetting = liveSyncSettings.locator(".setting-item").filter({
has: page.locator(".setting-item-name").filter({ hasText: "Rerun Onboarding Wizard" }),
});
await onboardingSetting.waitFor({ state: "visible", timeout: uiTimeoutMs });
await onboardingSetting
.getByRole("button", { name: "Rerun Wizard", exact: true })
.click({ timeout: uiTimeoutMs });
await onboardingDialogue(page).waitFor({ state: "visible", timeout: uiTimeoutMs });
});
}
async function closeSettings(): Promise<void> {
await withObsidianPage(obsidianRemoteDebuggingPort(), async (page) => {
const settingsContainer = page.locator(".modal-container").filter({
has: page.locator(".sls-setting"),
});
await settingsContainer.locator(".modal-close-button").click({ timeout: uiTimeoutMs });
await settingsContainer.waitFor({ state: "hidden", timeout: uiTimeoutMs });
});
if (!opened) throw new Error("The permanent onboarding command was not registered.");
}
async function main(): Promise<void> {
@@ -190,8 +217,9 @@ async function main(): Promise<void> {
console.log(`Fresh Vault startup evidence: ${JSON.stringify(evidence)}`);
const desktopInvitation = await captureDesktopInvitation();
await openPermanentCommand();
const commandIntro = await captureAndCloseIntro("onboarding-intro-command-desktop.png", false);
await openOnboardingFromSettings();
const settingsIntro = await captureAndCloseIntro("onboarding-intro-settings-desktop.png", false);
await closeSettings();
const mobileInvitation = await captureAndSelectMobileInvitation();
const mobileIntro = await captureAndCloseIntro("onboarding-intro-mobile.png", true);
@@ -200,7 +228,7 @@ async function main(): Promise<void> {
desktopInvitation,
mobileInvitation,
mobileIntro,
commandIntro,
settingsIntro,
].join(", ")}`
);
} finally {