diff --git a/src/pat/contentbrowser/contentbrowser-selection.test.js b/src/pat/contentbrowser/contentbrowser-selection.test.js new file mode 100644 index 000000000..ede08cf6d --- /dev/null +++ b/src/pat/contentbrowser/contentbrowser-selection.test.js @@ -0,0 +1,69 @@ +import "./contentbrowser"; +import registry from "@patternslib/patternslib/src/core/registry"; +import utils from "@patternslib/patternslib/src/core/utils"; + +const vocabularyUrl = "http://localhost/plone/@@getVocabulary"; + +const item = (uid, title) => ({ + UID: uid, + Title: title, + "@id": `http://localhost/plone/${uid}`, + path: `/plone/${uid}`, + portal_type: "Document", + getIcon: "", + is_folderish: false, + review_state: "published", + getURL: `http://localhost/plone/${uid}`, +}); + +function mockVocabulary(items) { + global.fetch = jest.fn(async () => ({ + ok: true, + json: async () => ({ results: items, total: items.length }), + })); +} + +async function mountField(value) { + const options = { vocabularyUrl }; + document.body.innerHTML = ` +
+ +
+ `; + const input = document.getElementById("field"); + const changes = []; + input.addEventListener("change", () => changes.push(input.value)); + registry.scan(document.body); + await utils.timeout(1); + return { input, changes }; +} + +describe("Content Browser selection", () => { + afterEach(() => { + document.body.innerHTML = ""; + delete global.fetch; + }); + + it("does not fire change while rendering the initial selection", async () => { + mockVocabulary([item("uid-1", "One"), item("uid-2", "Two")]); + const { input, changes } = await mountField("uid-1,uid-2"); + await utils.timeout(1); + + expect(document.querySelectorAll(".selected-item").length).toEqual(2); + expect(input.value).toEqual("uid-1,uid-2"); + expect(changes).toEqual([]); + }); + + it("fires change when an item is unselected", async () => { + mockVocabulary([item("uid-1", "One"), item("uid-2", "Two")]); + const { input, changes } = await mountField("uid-1,uid-2"); + await utils.timeout(1); + + document.querySelector(".selected-item button[aria-label=remove]").click(); + await utils.timeout(1); + + expect(input.value).toEqual("uid-2"); + expect(changes).toEqual(["uid-2"]); + }); +}); diff --git a/src/pat/contentbrowser/src/SelectedItems.svelte b/src/pat/contentbrowser/src/SelectedItems.svelte index 026c454f8..babaf42cd 100644 --- a/src/pat/contentbrowser/src/SelectedItems.svelte +++ b/src/pat/contentbrowser/src/SelectedItems.svelte @@ -101,6 +101,12 @@ function setNodeValue(selectedUids) { const node_val = selectedUids.join($config.separator); + if (selectedItemsNode.value === node_val) { + // Nothing changed — the initial selection being written back + // on mount must not look like an edit (pat-formunloadalert + // would otherwise warn on every page leave). + return; + } selectedItemsNode.value = node_val; selectedItemsNode.dispatchEvent(events.change_event()); }