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
6 changes: 3 additions & 3 deletions tests/e2e/audit-gaps.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "vitest";
import { createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID, WAIT_OPTS } from "./harness";
import { CLOSE_ALL_MODALS_JS, createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID, WAIT_OPTS } from "./harness";

const getContext = createMetaEditE2EHarness("audit-gaps");

Expand Down Expand Up @@ -62,8 +62,8 @@ describe("MetaEdit audit gap coverage", () => {
if (items.length) break;
}
const texts = items.map(el => ((el.querySelector(".suggestion-item-text") || el).textContent || "").trim());
app.workspace.activeModal?.close?.();
for (const el of Array.from(document.querySelectorAll(".suggestion-container, .suggestion-item"))) el.remove();
${CLOSE_ALL_MODALS_JS}
await closeAllModals();
return texts.filter(t => t.startsWith("#dup"));
})()
`,
Expand Down
62 changes: 37 additions & 25 deletions tests/e2e/audit-modals.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "vitest";
import { createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID } from "./harness";
import { CLOSE_ALL_MODALS_JS, createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID } from "./harness";

const getContext = createMetaEditE2EHarness("audit-modals");

Expand All @@ -25,12 +25,7 @@ const HELPERS = `
};
const itemByName = (root, name) => Array.from(root.querySelectorAll(".setting-item"))
.find((el) => el.querySelector(".setting-item-name")?.textContent.trim() === name);
const closeAll = async () => {
app.setting?.close?.();
document.querySelectorAll(".modal-container .modal-close-button").forEach((b) => b.dispatchEvent(new MouseEvent("click", { bubbles: true })));
document.querySelectorAll(".modal-container, .suggestion-container, .prompt").forEach((el) => el.remove());
await sleep(120);
};
${CLOSE_ALL_MODALS_JS}
`;

describe("MetaEdit modal + kanban flows", () => {
Expand All @@ -41,7 +36,7 @@ describe("MetaEdit modal + kanban flows", () => {
`
(async () => {
${HELPERS}
await closeAll();
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const prevEnabled = plugin.settings.AutoProperties.enabled;
const prevProps = plugin.settings.AutoProperties.properties;
Expand Down Expand Up @@ -75,7 +70,7 @@ describe("MetaEdit modal + kanban flows", () => {
`
(async () => {
${HELPERS}
await closeAll();
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const path = ${JSON.stringify(notePath)};
let f = app.vault.getAbstractFileByPath(path);
Expand All @@ -91,11 +86,9 @@ describe("MetaEdit modal + kanban flows", () => {
try {
const p = plugin.api.autoprop("mood");
const titleEl = await waitFor(".metaedit-ap-prompt-title");
// Cancel by clicking the modal's close button (the X).
const modalEl = titleEl.closest(".modal-container") || document;
const closeBtn = modalEl.querySelector(".modal-close-button");
if (closeBtn) closeBtn.dispatchEvent(new MouseEvent("click", { bubbles: true }));
else document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true }));
// Cancel the way a user does: Escape through Obsidian's keymap
// scope (1.13 removed the .modal-close-button affordance).
document.body.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", keyCode: 27, which: 27, bubbles: true }));
const resolved = await p;
await sleep(150);
return { resolved, content: await app.vault.read(f), before };
Expand All @@ -118,7 +111,7 @@ describe("MetaEdit modal + kanban flows", () => {
`
(async () => {
${HELPERS}
await closeAll();
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const root = await openTab();
const item = itemByName(root, "Progress Properties");
Expand Down Expand Up @@ -155,40 +148,59 @@ describe("MetaEdit modal + kanban flows", () => {
expect(await obsidian.dev.runtimeErrors()).toEqual([]);
});

test("PROMPT-02: a date-typed YAML property opens a native date picker in the prompt", async () => {
// PROMPT-02: a date-typed YAML property opens Obsidian's native date widget.
// Since PR #168 a top-level YAML property is edited in the
// NativePropertyPrompt, so the date affordance is the native widget's
// input[type=date] - the legacy .metaEditPromptInput date picker no longer
// participates in this flow.
test("PROMPT-02: a date-typed YAML property opens a native date input in the edit prompt", async () => {
const { obsidian, sandbox } = getContext();
const notePath = sandbox.path("date-prop.md");
const result = await evalJsonAsync<{ inputType: string; hasDateClass: boolean }>(
const result = await evalJsonAsync<{
inputType: string | null;
hasDateClass: boolean;
legacyPromptOpened: boolean;
modalsAfter: number;
}>(
obsidian,
`
(async () => {
${HELPERS}
const itemText = (item) => ((item.querySelector(".suggestion-item-text") || item).textContent || "").trim();
await closeAll();
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const path = ${JSON.stringify(notePath)};
let f = app.vault.getAbstractFileByPath(path);
const body = "---\\ndue: 2026-01-01\\n---\\nbody\\n";
if (f) { await app.vault.modify(f, body); } else { f = await app.vault.create(path, body); }
await sleep(300);
// Assign Obsidian's "date" property type so getDateInputType returns "date".
// Assign Obsidian's "date" property type so the native prompt mounts the date widget.
app.metadataTypeManager.setType("due", "date");
await sleep(200);

await plugin.runMetaEditForFile(f);
const row = await waitFor(".suggestion-item", (i) => itemText(i).startsWith("due"));
row.dispatchEvent(new MouseEvent("mousedown", { bubbles: true }));
row.dispatchEvent(new MouseEvent("click", { bubbles: true }));
const input = await waitFor(".metaEditPromptInput");
const inputType = input.getAttribute("type");
const hasDateClass = input.classList.contains("mod-date");
await closeAll();
return { inputType, hasDateClass };
const host = await waitFor(".metaedit-native-property-host");
const input = host.querySelector("input");
const inputType = input?.getAttribute("type") ?? null;
const hasDateClass = input?.classList.contains("mod-date") ?? false;
const legacyPromptOpened = Boolean(document.querySelector(".metaEditPromptInput"));
await closeAllModals();
return {
inputType,
hasDateClass,
legacyPromptOpened,
modalsAfter: document.querySelectorAll(".modal-container").length,
};
})()
`,
);
expect(result.inputType).toBe("date");
expect(result.hasDateClass).toBe(true);
expect(result.legacyPromptOpened).toBe(false);
expect(result.modalsAfter).toBe(0);
expect(await obsidian.dev.runtimeErrors()).toEqual([]);
});

Expand All @@ -200,7 +212,7 @@ describe("MetaEdit modal + kanban flows", () => {
`
(async () => {
${HELPERS}
await closeAll();
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const path = ${JSON.stringify(boardPath)};
let f = app.vault.getAbstractFileByPath(path);
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/audit-settings.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "vitest";
import { createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID } from "./harness";
import { CLOSE_ALL_MODALS_JS, createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID } from "./harness";

const getContext = createMetaEditE2EHarness("audit-settings");

Expand Down Expand Up @@ -290,8 +290,8 @@ describe("MetaEdit settings tab", () => {
opt.dispatchEvent(new MouseEvent("click", { bubbles: true }));
}
await sleep(300);
app.workspace.activeModal?.close?.();
for (const el of Array.from(document.querySelectorAll(".suggestion-container, .suggestion-item, .prompt"))) el.remove();
${CLOSE_ALL_MODALS_JS}
await closeAllModals();
return { suggestValues: captured ?? [], captured: captured !== null };
} finally {
plugin.controller.createNewYamlPropertyFluid = orig;
Expand Down
22 changes: 9 additions & 13 deletions tests/e2e/audit-suggester.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "vitest";
import { createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID } from "./harness";
import { CLOSE_ALL_MODALS_JS, createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID } from "./harness";

const getContext = createMetaEditE2EHarness("audit-suggester");

Expand Down Expand Up @@ -29,11 +29,7 @@ const HELPERS = `
input.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter", code: "Enter", keyCode: 13, which: 13, bubbles: true, cancelable: true }));
return input;
};
const closeModals = () => {
app.workspace.activeModal?.close?.();
for (const b of Array.from(document.querySelectorAll(".modal-close-button"))) b.dispatchEvent(new MouseEvent("click", { bubbles: true }));
for (const el of Array.from(document.querySelectorAll(".suggestion-container, .suggestion-item, .prompt"))) el.remove();
};
${CLOSE_ALL_MODALS_JS}
`;

describe("MetaEdit Edit Meta suggester flows", () => {
Expand All @@ -45,7 +41,7 @@ describe("MetaEdit Edit Meta suggester flows", () => {
`
(async () => {
${HELPERS}
closeModals(); await sleep(150);
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const path = ${JSON.stringify(notePath)};
let f = app.vault.getAbstractFileByPath(path);
Expand All @@ -72,7 +68,7 @@ describe("MetaEdit Edit Meta suggester flows", () => {
await sleep(150);
Array.from(modal.querySelectorAll("button")).find((b) => b.textContent.trim() === "Add").click();
await waitFor("body", () => (app.metadataCache.getFileCache(f)?.frontmatter ?? {}).freshKey === "freshValue");
closeModals();
await closeAllModals();
await sleep(100);
return await app.vault.read(f);
})()
Expand All @@ -91,7 +87,7 @@ describe("MetaEdit Edit Meta suggester flows", () => {
`
(async () => {
${HELPERS}
closeModals(); await sleep(150);
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const path = ${JSON.stringify(notePath)};
let f = app.vault.getAbstractFileByPath(path);
Expand All @@ -118,7 +114,7 @@ describe("MetaEdit Edit Meta suggester flows", () => {
`
(async () => {
${HELPERS}
closeModals(); await sleep(150);
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const path = ${JSON.stringify(notePath)};
let f = app.vault.getAbstractFileByPath(path);
Expand All @@ -138,7 +134,7 @@ describe("MetaEdit Edit Meta suggester flows", () => {
await waitFor("body", () => !("deleteMe" in (app.metadataCache.getFileCache(f)?.frontmatter ?? {})));
await sleep(200);
const modalOpen = !!document.querySelector(".suggestion-container .suggestion-item");
closeModals();
await closeAllModals();
return { content: await app.vault.read(f), modalOpen };
})()
`,
Expand All @@ -158,7 +154,7 @@ describe("MetaEdit Edit Meta suggester flows", () => {
`
(async () => {
${HELPERS}
closeModals(); await sleep(150);
await closeAllModals();
const plugin = app.plugins.plugins.${PLUGIN_ID};
const path = ${JSON.stringify(notePath)};
let f = app.vault.getAbstractFileByPath(path);
Expand All @@ -177,7 +173,7 @@ describe("MetaEdit Edit Meta suggester flows", () => {
// Transform deletes the YAML key, then appends the inline field.
await waitFor("body", () => !("mover" in (app.metadataCache.getFileCache(f)?.frontmatter ?? {})));
await sleep(250);
closeModals();
await closeAllModals();
await sleep(100);
return await app.vault.read(f);
})()
Expand Down
4 changes: 3 additions & 1 deletion tests/e2e/auto-properties.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, test } from "vitest";
import {
CLOSE_ALL_MODALS_JS,
createMetaEditE2EHarness,
evalJsonAsync,
PLUGIN_ID,
Expand Down Expand Up @@ -77,7 +78,8 @@ async function runAutoPropertyEdit(
return { content, choices: saved ? saved.choices : undefined };
} finally {
// Make sure no modal is left open to leak into the next test.
document.querySelectorAll(".modal-close-button").forEach((b) => b.click());
${CLOSE_ALL_MODALS_JS}
await closeAllModals();
plugin.settings.AutoProperties = snapshot.auto;
plugin.settings.EditMode.mode = snapshot.mode;
await plugin.saveSettings();
Expand Down
5 changes: 3 additions & 2 deletions tests/e2e/bulk-metadata.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "vitest";
import { createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID, WAIT_OPTS } from "./harness";
import { CLOSE_ALL_MODALS_JS, createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID, WAIT_OPTS } from "./harness";

const getContext = createMetaEditE2EHarness("bulk-metadata");

Expand Down Expand Up @@ -107,7 +107,8 @@ describe("MetaEdit bulk metadata edit", () => {
return { content: await app.vault.read(file), conflictTitle };
} finally {
app.metadataCache.getFileCache = originalGetFileCache;
document.querySelectorAll(".modal-close-button").forEach((button) => button.click());
${CLOSE_ALL_MODALS_JS}
await closeAllModals();
}
})()
`,
Expand Down
5 changes: 3 additions & 2 deletions tests/e2e/fluid-create.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID} from "./harness";
import {CLOSE_ALL_MODALS_JS, createMetaEditE2EHarness, evalJsonAsync, PLUGIN_ID} from "./harness";

const getContext = createMetaEditE2EHarness("fluid-create");

Expand Down Expand Up @@ -132,7 +132,8 @@ describe("MetaEdit fluid property creation", () => {
out.coversCancel = dd ? intersects(dd.getBoundingClientRect(), cancelBtn.getBoundingClientRect()) : true;
cancel(modal);
await promise;
document.querySelectorAll(".suggestion-container").forEach(e => e.remove());
${CLOSE_ALL_MODALS_JS}
await closeAllModals();
return out;
})()
`,
Expand Down
Loading