import $ from "jquery"; import { test } from "qunit"; import { Promise } from "rsvp"; import { cook } from "discourse/lib/text"; import Post from "discourse/models/post"; import { acceptance } from "discourse/tests/helpers/qunit-helpers"; import { checklistSyntax } from "discourse/plugins/checklist/discourse/initializers/checklist"; let currentRaw; async function prepare(raw) { const cooked = await cook(raw, { siteSettings: { checklist_enabled: true, discourse_local_dates_enabled: true, }, }); const widget = { attrs: {}, scheduleRerender() {} }; const model = Post.create({ id: 42, can_edit: true }); const decoratorHelper = { widget, getModel: () => model }; const $elem = $(`
${cooked.toString()}
`); checklistSyntax($elem[0], decoratorHelper); currentRaw = raw; const updated = new Promise((resolve) => { model.save = async (fields) => resolve(fields.raw); }); return [$elem, updated]; } acceptance("discourse-checklist | checklist", function (needs) { needs.pretender((server) => { server.get("/posts/42", () => [ 200, { "Content-Type": "application/json" }, { raw: currentRaw }, ]); }); test("does not clash with date-range bbcode", async function (assert) { const [$elem, updated] = await prepare(` [date-range from=2024-03-22 to=2024-03-23] [ ] task 1 [ ] task 2 [x] task 3 `); assert.equal($elem.find(".discourse-local-date").length, 2); assert.equal($elem.find(".chcklst-box").length, 3); $elem.find(".chcklst-box")[0].click(); const output = await updated; assert.ok(output.includes("[x] task 1")); }); test("does not check an image URL", async function (assert) { const [$elem, updated] = await prepare(` ![](upload://zLd8FtsWc2ZSg3cZKIhwvhYxTcn.jpg) [] first [] second `); $elem.find(".chcklst-box")[0].click(); const output = await updated; assert.ok(output.includes("[x] first")); }); test("make checkboxes readonly while updating", async function (assert) { const [$elem, updated] = await prepare(` [ ] first [x] second `); const $checklist = $elem.find(".chcklst-box"); $checklist.get(0).click(); const checkbox = $checklist.get(1); assert.ok(checkbox.classList.contains("readonly")); checkbox.click(); const output = await updated; assert.ok(output.includes("[x] first")); assert.ok(output.includes("[x] second")); }); test("checkbox before a code block", async function (assert) { const [$elem, updated] = await prepare(` [ ] first [x] actual \`[x] nope\` `); assert.equal($elem.find(".chcklst-box").length, 2); $elem.find(".chcklst-box")[1].click(); const output = await updated; assert.ok(output.includes("[ ] first")); assert.ok(output.includes("[ ] actual")); assert.ok(output.includes("[x] nope")); }); test("permanently checked checkbox", async function (assert) { const [$elem, updated] = await prepare(` [X] perma [x] not perma `); assert.equal($elem.find(".chcklst-box").length, 2); $elem.find(".chcklst-box")[0].click(); $elem.find(".chcklst-box")[1].click(); const output = await updated; assert.ok(output.includes("[X] perma")); assert.ok(output.includes("[ ] not perma")); }); test("checkbox before a multiline code block", async function (assert) { const [$elem, updated] = await prepare(` [ ] first [x] actual \`\`\` [x] nope [x] neither \`\`\` `); assert.equal($elem.find(".chcklst-box").length, 2); $elem.find(".chcklst-box")[1].click(); const output = await updated; assert.ok(output.includes("[ ] first")); assert.ok(output.includes("[ ] actual")); assert.ok(output.includes("[x] nope")); }); test("checkbox before italic/bold sequence", async function (assert) { const [$elem, updated] = await prepare(` [x] *test* `); assert.equal($elem.find(".chcklst-box").length, 1); $elem.find(".chcklst-box")[0].click(); const output = await updated; assert.ok(output.includes("[ ] *test*")); }); test("checkboxes in an unordered list", async function (assert) { const [$elem, updated] = await prepare(` * [x] checked * [] test * [] two `); assert.equal($elem.find(".chcklst-box").length, 3); $elem.find(".chcklst-box")[1].click(); const output = await updated; assert.ok(output.includes("* [x] checked")); assert.ok(output.includes("* [x] test")); assert.ok(output.includes("* [] two")); }); test("checkboxes in italic/bold-like blocks", async function (assert) { const [$elem, updated] = await prepare(` *[x *a [*] x]* [*x] ~~[*]~~ * []* 0 ~~[] ~~ 1 ~~ [x]~~ 2 * [x] 3 `); assert.equal($elem.find(".chcklst-box").length, 4); $elem.find(".chcklst-box")[3].click(); const output = await updated; assert.ok(output.includes("* [ ] 3")); }); test("correct checkbox is selected", async function (assert) { const [$elem, updated] = await prepare(` \`[x]\` *[x]* **[x]** _[x]_ __[x]__ ~~[x]~~ [code] [x] [ ] [ ] [x] [/code] \`\`\` [x] [ ] [ ] [x] \`\`\` Actual checkboxes: [] first [x] second * test[x]*thrid* [x] fourth [x] fifth `); assert.equal($elem.find(".chcklst-box").length, 5); $elem.find(".chcklst-box")[3].click(); const output = await updated; assert.ok(output.includes("[ ] fourth")); }); test("rendering in bullet lists", async function (assert) { const [$elem] = await prepare(` - [ ] LI 1 - LI 2 [ ] with checkbox in middle - [ ] LI 3 1. [ ] Ordered LI with checkbox `); const elem = $elem[0]; const listItems = [...elem.querySelector("ul").children]; assert.equal(listItems.length, 3); assert.true( listItems[0].classList.contains("has-checkbox"), "LI 1 has `.has-checkbox` class" ); assert.true( listItems[0] .querySelector(".chcklst-box") .classList.contains("list-item-checkbox"), "LI 1 checkbox has `.list-item-checkbox`" ); assert.false( listItems[1].classList.contains("has-checkbox"), "LI 2 does not have `.has-checkbox` class" ); assert.false( listItems[1] .querySelector(".chcklst-box") .classList.contains("list-item-checkbox"), "LI 2 checkbox does not have `.list-item-checkbox`" ); assert.true( listItems[2].classList.contains("has-checkbox"), "LI 3 has `.has-checkbox` class" ); assert.true( listItems[2] .querySelector(".chcklst-box") .classList.contains("list-item-checkbox"), "LI 3 checkbox has `.list-item-checkbox`" ); const orderedListItems = [...elem.querySelector("ol").children]; assert.false( orderedListItems[0].classList.contains("has-checkbox"), "OL does not have `.has-checkbox` class" ); assert.false( orderedListItems[0] .querySelector(".chcklst-box") .classList.contains("list-item-checkbox"), "OL checkbox does not have `.list-item-checkbox`" ); }); });