Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions tests/e2e-vault-config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { readFileSync, readdirSync } from "node:fs";
import { join, relative, resolve } from "node:path";
import { expect, it } from "vitest";

const ROOT = resolve(__dirname, "..");
const E2E = join(ROOT, "tests/e2e");

it("sets vault options in e2e specs without writing app.json", () => {
const hits = readdirSync(E2E, { recursive: true, encoding: "utf8" })
.filter((file) => file.endsWith(".ts"))
.flatMap((file) =>
readFileSync(join(E2E, file), "utf8")
.split("\n")
.flatMap((line, i) => (/\b(setConfig|saveConfig|requestSaveConfig)\s*\(/.test(line) ? [`${relative(ROOT, join(E2E, file))}:${i + 1}`] : [])),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
);
expect(
hits,
"Use setVaultConfig from tests/e2e/uiHelpers.ts: setConfig and saveConfig write app.json, which Obsidian can read back under load after the spec restores the option, leaking it into every later spec (#2207).",
).toEqual([]);
});
3 changes: 2 additions & 1 deletion tests/e2e/conditional-branch-persistence.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
acquireQuickAddVaultRunLock,
createQuickAddObsidianClient,
} from "./e2eVault";
import { setVaultConfig } from "./uiHelpers";

const PLUGIN_ID = "quickadd";
const CHOICE_ID = "qa-e2e-cond-branch";
Expand Down Expand Up @@ -77,7 +78,7 @@ beforeAll(async () => {
// the helpers above stay window-agnostic, so if a runner-side fix ever
// makes popouts reliable, deleting this line is the whole migration.
await obsidian.dev.eval(
`app.vault.setConfig('settingsPopoutWindow', false)`,
setVaultConfig("settingsPopoutWindow", false),
);
qa = obsidian.plugin(PLUGIN_ID);
await qa.reload({ waitUntilReady: true });
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/daily-note-token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { CaptureChoice } from "../../src/types/choices/CaptureChoice";
import type IChoice from "../../src/types/choices/IChoice";
import { createQuickAddE2EHarness, seedVaultFile } from "./e2eVault";
import { setVaultConfig } from "./uiHelpers";

const getContext = createQuickAddE2EHarness("daily-note-token");

Expand Down Expand Up @@ -233,7 +234,7 @@ describe("{{DAILY}} in native Obsidian", () => {
choice.format = { enabled: true, format: "{{DAILY|link}}" };
await saveChoice(choice);
const useMarkdownLinks = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('useMarkdownLinks')");
await obsidian.dev.evalJson("(() => { app.vault.setConfig('useMarkdownLinks', true); return true; })()");
await obsidian.dev.evalJson(`${setVaultConfig("useMarkdownLinks", true)}, true`);
try {
await obsidian.execJson("quickadd:run", { id: choice.id, verify: true, date: "2031-02-18" });
await expect.poll(() => read(inbox), { timeout: 10000, interval: 100 })
Expand All @@ -249,8 +250,7 @@ describe("{{DAILY}} in native Obsidian", () => {
})()`);
expect(opened).toBe(`${folder}/2031-02-18.md`);
} finally {
// Saved now: the debounced save of `true` would otherwise reach disk after the restore.
await obsidian.dev.evalJsonAsync(`(async () => { app.vault.setConfig('useMarkdownLinks', ${useMarkdownLinks === true}); await app.vault.saveConfig(); return true; })()`);
await obsidian.dev.evalJson(`${setVaultConfig("useMarkdownLinks", useMarkdownLinks === true)}, true`);
}
});

Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/drag-pill-bounds.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, it } from "vitest";
import { CaptureChoice } from "../../src/types/choices/CaptureChoice";
import type IChoice from "../../src/types/choices/IChoice";
import { createQuickAddE2EHarness } from "./e2eVault";
import { waitForElement } from "./uiHelpers";
import { setVaultConfig, waitForElement } from "./uiHelpers";

const getContext = createQuickAddE2EHarness("drag-pill-bounds");

Expand All @@ -26,7 +26,7 @@ it("keeps the drag pill inside a narrow window with the grip under the cursor",
// Narrow enough that a pill growing right from the handle runs off the window.
await obsidian.dev.evalJson(`require("@electron/remote").getCurrentWindow().setSize(900, 700), true`);
await expect.poll(() => obsidian.dev.evalJson<number>("innerWidth")).toBe(900);
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), app.setting.open(), app.setting.openTabById('quickadd'), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, app.setting.open(), app.setting.openTabById('quickadd'), true`);
const handleSelector = `[aria-label=${JSON.stringify(`Reorder ${LONG_NAME}`)}]`;
await waitForElement(obsidian, handleSelector);
const [x, y] = await obsidian.dev.evalJson<number[]>(`(() => {
Expand All @@ -53,7 +53,7 @@ it("keeps the drag pill inside a narrow window with the grip under the cursor",
if (pressedAt) await mouse("mouseReleased", pressedAt[0], pressedAt[1], 1);
await obsidian.dev.evalJson(`(() => {
app.setting.close();
app.vault.setConfig('settingsPopoutWindow', ${JSON.stringify(popout)});
${setVaultConfig("settingsPopoutWindow", popout)};
require("@electron/remote").getCurrentWindow().setSize(${originalSize[0]}, ${originalSize[1]});
return true;
})()`);
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/package-import-destination.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, it } from "vitest";
import type { QuickAddPackage } from "../../src/types/packages/QuickAddPackage";
import { encodeToBase64 } from "../../src/utils/base64";
import { createQuickAddE2EHarness, seedVaultFile } from "./e2eVault";
import { POLL_OPTS, jsLiteral, pressKey, typeInto, waitForElement } from "./uiHelpers";
import { POLL_OPTS, jsLiteral, pressKey, setVaultConfig, typeInto, waitForElement } from "./uiHelpers";

// #1865: typing a file's Destination past a path that names a folder regrouped
// the row, which re-created it and dropped focus, and a folder destination
Expand Down Expand Up @@ -32,7 +32,7 @@ it("keeps focus while you type a destination, and blocks a folder destination",
};

const popout = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('settingsPopoutWindow') ?? true");
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, true`);
const state = () => obsidian.dev.evalJson<{ focused: boolean; value: string; folder: boolean; importDisabled: boolean }>(`(() => {
const input = document.querySelector(${jsLiteral(DESTINATION)});
return {
Expand Down Expand Up @@ -67,6 +67,6 @@ it("keeps focus while you type a destination, and blocks a folder destination",
} finally {
await pressKey(obsidian, "Escape");
await obsidian.dev.evalJson("app.setting.close(); true");
await obsidian.dev.evalJson(`app.vault.setConfig('settingsPopoutWindow', ${jsLiteral(popout)}), true`);
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", popout)}, true`);
}
});
6 changes: 3 additions & 3 deletions tests/e2e/package-import-existing.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, it } from "vitest";
import type IChoice from "../../src/types/choices/IChoice";
import { createQuickAddE2EHarness, seedVaultFile } from "./e2eVault";
import { jsLiteral, POLL_OPTS, pressKey, typeInto } from "./uiHelpers";
import { jsLiteral, POLL_OPTS, pressKey, setVaultConfig, typeInto } from "./uiHelpers";

// "Import" adds a choice and never replaces one: the CLI refuses it for a
// choice already in the vault, and the modal only offers it for new choices.
Expand Down Expand Up @@ -47,7 +47,7 @@ it("offers Overwrite, not Import, for a choice already in the vault", async () =
await obsidian.execJson("quickadd:package-import", { path: mine });

const popout = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('settingsPopoutWindow') ?? true");
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, true`);
try {
await obsidian.dev.evalJson(`(() => { app.setting.open(); app.setting.openTabById("quickadd"); return true; })()`);
await expect.poll(() => obsidian.dev.evalJson<boolean>(`(() => {
Expand All @@ -65,6 +65,6 @@ it("offers Overwrite, not Import, for a choice already in the vault", async () =
} finally {
await pressKey(obsidian, "Escape");
await obsidian.dev.evalJson("app.setting.close(); true");
await obsidian.dev.evalJson(`app.vault.setConfig('settingsPopoutWindow', ${jsLiteral(popout)}), true`);
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", popout)}, true`);
}
});
6 changes: 3 additions & 3 deletions tests/e2e/package-import-inline-code.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, it } from "vitest";
import type IChoice from "../../src/types/choices/IChoice";
import { createQuickAddE2EHarness } from "./e2eVault";
import { clickAt, POLL_OPTS, pressKey, typeInto, waitForElement } from "./uiHelpers";
import { clickAt, POLL_OPTS, pressKey, setVaultConfig, typeInto, waitForElement } from "./uiHelpers";

// #1912: the import review shows JavaScript written into a choice setting, counts
// viewing it like opening a bundled script, and says beside Import what is left.
Expand Down Expand Up @@ -67,7 +67,7 @@ it("shows a choice's inline code and says beside Import what is left", async ()
};

const popout = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('settingsPopoutWindow') ?? true");
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, true`);
try {
await obsidian.dev.evalJson(`(() => { app.setting.open(); app.setting.openTabById("quickadd"); return true; })()`);
await expect.poll(() => obsidian.dev.evalJson<boolean>(`(() => {
Expand Down Expand Up @@ -116,6 +116,6 @@ it("shows a choice's inline code and says beside Import what is left", async ()
} finally {
await pressKey(obsidian, "Escape");
await obsidian.dev.evalJson("app.setting.close(); true");
await obsidian.dev.evalJson(`app.vault.setConfig('settingsPopoutWindow', ${JSON.stringify(popout)}), true`);
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", popout)}, true`);
}
});
6 changes: 3 additions & 3 deletions tests/e2e/package-import-result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type IChoice from "../../src/types/choices/IChoice";
import type { QuickAddPackage } from "../../src/types/packages/QuickAddPackage";
import { encodeToBase64 } from "../../src/utils/base64";
import { createQuickAddE2EHarness } from "./e2eVault";
import { POLL_OPTS, pressKey, typeInto, waitForElement } from "./uiHelpers";
import { POLL_OPTS, pressKey, setVaultConfig, typeInto, waitForElement } from "./uiHelpers";

// #1880: after Import package, the result callout sat half hidden behind the
// footer, and Cancel stayed next to Close.
Expand Down Expand Up @@ -31,7 +31,7 @@ it("shows the import result in view, with a single Close", async () => {
};

const popout = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('settingsPopoutWindow') ?? true");
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, true`);
try {
await obsidian.dev.evalJson(`(() => { app.setting.open(); app.setting.openTabById("quickadd"); return true; })()`);
await expect.poll(() => obsidian.dev.evalJson<boolean>(`(() => {
Expand Down Expand Up @@ -64,6 +64,6 @@ it("shows the import result in view, with a single Close", async () => {
} finally {
await pressKey(obsidian, "Escape");
await obsidian.dev.evalJson("app.setting.close(); true");
await obsidian.dev.evalJson(`app.vault.setConfig('settingsPopoutWindow', ${JSON.stringify(popout)}), true`);
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", popout)}, true`);
}
});
6 changes: 3 additions & 3 deletions tests/e2e/prompt-cancellation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ChoiceCommand } from "../../src/types/macros/ChoiceCommand";
import { ConditionalCommand } from "../../src/types/macros/Conditional/ConditionalCommand";
import { UserScript } from "../../src/types/macros/UserScript";
import { createQuickAddE2EHarness, seedVaultFile } from "./e2eVault";
import { insertText, jsLiteral, POLL_OPTS, pressKey } from "./uiHelpers";
import { insertText, jsLiteral, POLL_OPTS, pressKey, setVaultConfig } from "./uiHelpers";

// Pressing Escape in a prompt is a normal way to stop a run. It must not land in
// Obsidian's `dev:errors`, which records every unhandled promise rejection (even one
Expand Down Expand Up @@ -246,7 +246,7 @@ it("Escape in the macro builder's script pickers leaves dev:errors empty", async
// Settings in the main window, as in conditional-branch-persistence.test.ts:
// the popout's DOM adoption is nondeterministic under CLI automation.
const popout = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('settingsPopoutWindow') ?? true");
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, true`);
const click = (selector: string, text?: string) => obsidian.dev.evalJson<boolean>(`(() => {
const all = Array.from(document.querySelectorAll(${jsLiteral(selector)}))
.filter((el) => ${jsLiteral(text ?? null)} === null || el.textContent.trim() === ${jsLiteral(text ?? null)});
Expand Down Expand Up @@ -286,6 +286,6 @@ it("Escape in the macro builder's script pickers leaves dev:errors empty", async
expect(await devErrors(obsidian)).toBe(NO_ERRORS);
} finally {
await escapeUntilClosed(obsidian);
await obsidian.dev.evalJson(`(() => { app.setting.close(); app.vault.setConfig('settingsPopoutWindow', ${popout}); return true; })()`);
await obsidian.dev.evalJson(`(() => { app.setting.close(); ${setVaultConfig("settingsPopoutWindow", popout)}; return true; })()`);
}
});
6 changes: 3 additions & 3 deletions tests/e2e/script-picker-paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, it } from "vitest";
import { MacroChoice } from "../../src/types/choices/MacroChoice";
import type IChoice from "../../src/types/choices/IChoice";
import { createQuickAddE2EHarness, seedVaultFile } from "./e2eVault";
import { leaveSettingsPage, POLL_OPTS, pressKey, typeInto } from "./uiHelpers";
import { leaveSettingsPage, POLL_OPTS, pressKey, setVaultConfig, typeInto } from "./uiHelpers";

// #941/#942: two `view.js` files in different folders were identical "view" rows
// in both script pickers, and picking the second one from the inline typeahead
Expand All @@ -28,7 +28,7 @@ it("adds same-named scripts by path from the typeahead and Browse, and runs each
// Settings in the main window, as in conditional-branch-persistence.test.ts:
// the popout's DOM adoption is nondeterministic under CLI automation.
const popout = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('settingsPopoutWindow') ?? true");
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, true`);
const click = (selector: string, text?: string) => obsidian.dev.evalJson<boolean>(`(() => {
const target = Array.from(document.querySelectorAll(${JSON.stringify(selector)}))
.filter((el) => ${JSON.stringify(text ?? null)} === null || el.textContent.trim() === ${JSON.stringify(text ?? null)})
Expand Down Expand Up @@ -105,7 +105,7 @@ it("adds same-named scripts by path from the typeahead and Browse, and runs each
return data.choices[0].macro.commands.map((c) => c.path);
})()`), POLL_OPTS).toEqual([progress, books]);
} finally {
await obsidian.dev.evalJson(`(() => { app.setting.close(); app.vault.setConfig('settingsPopoutWindow', ${popout}); return true; })()`);
await obsidian.dev.evalJson(`(() => { app.setting.close(); ${setVaultConfig("settingsPopoutWindow", popout)}; return true; })()`);
}

await obsidian.dev.evalJson("(() => { window.__qaScriptPickerRuns = []; return true; })()");
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/script-syntax-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type IChoice from "../../src/types/choices/IChoice";
import { MacroChoice } from "../../src/types/choices/MacroChoice";
import { UserScript } from "../../src/types/macros/UserScript";
import { createQuickAddE2EHarness, seedVaultFile } from "./e2eVault";
import { jsLiteral, leaveSettingsPage, POLL_OPTS } from "./uiHelpers";
import { jsLiteral, leaveSettingsPage, POLL_OPTS, setVaultConfig } from "./uiHelpers";

const getContext = createQuickAddE2EHarness("script-syntax-error");

Expand Down Expand Up @@ -39,7 +39,7 @@ it("names the file and line of a user script syntax error on run, in the CLI, an

await obsidian.dev.evalJson(clearNotices);
const popout = await obsidian.dev.evalJson<boolean>("app.vault.getConfig('settingsPopoutWindow') ?? true");
await obsidian.dev.evalJson("app.vault.setConfig('settingsPopoutWindow', false), true");
await obsidian.dev.evalJson(`${setVaultConfig("settingsPopoutWindow", false)}, true`);
try {
await obsidian.dev.evalJson(`(() => { app.setting.open(); app.setting.openTabById("quickadd"); return true; })()`);
await expect.poll(() => obsidian.dev.evalJson<boolean>(`(() => {
Expand All @@ -53,6 +53,6 @@ it("names the file and line of a user script syntax error on run, in the CLI, an
]);
await leaveSettingsPage(obsidian);
} finally {
await obsidian.dev.evalJson(`(() => { app.setting.close(); app.vault.setConfig('settingsPopoutWindow', ${popout}); return true; })()`);
await obsidian.dev.evalJson(`(() => { app.setting.close(); ${setVaultConfig("settingsPopoutWindow", popout)}; return true; })()`);
}
});
5 changes: 3 additions & 2 deletions tests/e2e/settings-popout-save.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { expect, it } from "vitest";
import type IChoice from "../../src/types/choices/IChoice";
import { TemplateChoice } from "../../src/types/choices/TemplateChoice";
import { createQuickAddE2EHarness } from "./e2eVault";
import { setVaultConfig } from "./uiHelpers";

const getContext = createQuickAddE2EHarness("settings-popout-save");

Expand All @@ -25,7 +26,7 @@ for (const mainWindow of ["visible", "hidden"] as const) {
const inMemory = await obsidian.dev.evalJsonAsync<string[]>(`(async () => {
const remote = require("@electron/remote");
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
app.vault.setConfig("settingsPopoutWindow", true);
${setVaultConfig("settingsPopoutWindow", true)};
app.setting.open();
app.setting.openTabById("quickadd");
let doc;
Expand Down Expand Up @@ -76,7 +77,7 @@ for (const mainWindow of ["visible", "hidden"] as const) {
await obsidian.dev.evalJson(`(() => {
require("@electron/remote").getCurrentWindow().show();
app.setting.close();
app.vault.setConfig("settingsPopoutWindow", ${JSON.stringify(popout)});
${setVaultConfig("settingsPopoutWindow", popout)};
return true;
})()`);
}
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/template-cursor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { afterEach, describe, expect, it } from "vitest";
import { TemplateChoice } from "../../src/types/choices/TemplateChoice";
import type IChoice from "../../src/types/choices/IChoice";
import { createQuickAddE2EHarness, seedVaultFile } from "./e2eVault";
import { insertText, POLL_OPTS, pressKey, typeInto, waitForElement, expectNoPrompt } from "./uiHelpers";
import { insertText, POLL_OPTS, pressKey, setVaultConfig, typeInto, waitForElement, expectNoPrompt } from "./uiHelpers";

const getContext = createQuickAddE2EHarness("template-cursor");

Expand Down Expand Up @@ -375,7 +375,7 @@ describe("Template cursor markers in native Obsidian", () => {
const previousUpdateLinks = await obsidian.dev.evalJson<boolean>('app.vault.getConfig("alwaysUpdateLinks")');
try {
await obsidian.dev.evalJsonAsync(`(async () => {
app.vault.setConfig("alwaysUpdateLinks", true);
${setVaultConfig("alwaysUpdateLinks", true)};
const leaf = app.workspace.activeLeaf;
await leaf.setViewState({ type: "markdown", state: { file: ${JSON.stringify(path)}, mode: "source", source: false } });
leaf.view.editor.focus();
Expand Down Expand Up @@ -408,7 +408,7 @@ describe("Template cursor markers in native Obsidian", () => {
expect(await obsidian.dev.evalJson("app.workspace.activeLeaf.view.getState().source")).toBe(false);
} finally {
await obsidian.dev.evalJson(`(() => {
app.vault.setConfig("alwaysUpdateLinks", ${JSON.stringify(previousUpdateLinks)});
${setVaultConfig("alwaysUpdateLinks", previousUpdateLinks)};
for (const close of document.querySelectorAll(".modal-close-button")) close.click();
return true;
})()`);
Expand Down
Loading
Loading