2023-11-28 17:53:38 +08:00
|
|
|
import $ from "jquery";
|
2023-08-02 17:17:24 +08:00
|
|
|
import { test } from "qunit";
|
2023-10-11 02:38:59 +08:00
|
|
|
import { Promise } from "rsvp";
|
2023-10-10 00:22:46 +08:00
|
|
|
import { cook } from "discourse/lib/text";
|
2023-08-02 17:17:24 +08:00
|
|
|
import Post from "discourse/models/post";
|
2023-10-11 02:38:59 +08:00
|
|
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
2023-08-02 17:17:24 +08:00
|
|
|
import { checklistSyntax } from "discourse/plugins/checklist/discourse/initializers/checklist";
|
|
|
|
|
|
|
|
let currentRaw;
|
|
|
|
|
|
|
|
async function prepare(raw) {
|
2023-10-10 00:22:46 +08:00
|
|
|
const cooked = await cook(raw, {
|
2024-04-07 04:35:24 +08:00
|
|
|
siteSettings: {
|
|
|
|
checklist_enabled: true,
|
|
|
|
discourse_local_dates_enabled: true,
|
|
|
|
},
|
2023-08-02 17:17:24 +08:00
|
|
|
});
|
2023-08-03 05:24:20 +08:00
|
|
|
|
|
|
|
const widget = { attrs: {}, scheduleRerender() {} };
|
2023-08-02 17:17:24 +08:00
|
|
|
const model = Post.create({ id: 42, can_edit: true });
|
2023-08-03 05:24:20 +08:00
|
|
|
const decoratorHelper = { widget, getModel: () => model };
|
2023-08-02 17:17:24 +08:00
|
|
|
|
2023-09-15 05:04:57 +08:00
|
|
|
const $elem = $(`<div>${cooked.toString()}</div>`);
|
2023-08-02 17:17:24 +08:00
|
|
|
checklistSyntax($elem[0], decoratorHelper);
|
|
|
|
|
|
|
|
currentRaw = raw;
|
|
|
|
|
|
|
|
const updated = new Promise((resolve) => {
|
2023-08-03 05:24:20 +08:00
|
|
|
model.save = async (fields) => resolve(fields.raw);
|
2023-08-02 17:17:24 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
return [$elem, updated];
|
|
|
|
}
|
|
|
|
|
|
|
|
acceptance("discourse-checklist | checklist", function (needs) {
|
|
|
|
needs.pretender((server) => {
|
|
|
|
server.get("/posts/42", () => [
|
|
|
|
200,
|
|
|
|
{ "Content-Type": "application/json" },
|
|
|
|
{ raw: currentRaw },
|
|
|
|
]);
|
|
|
|
});
|
|
|
|
|
2024-04-07 04:35:24 +08:00
|
|
|
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"));
|
|
|
|
});
|
|
|
|
|
2024-04-06 23:17:19 +08:00
|
|
|
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"));
|
|
|
|
});
|
|
|
|
|
2023-08-02 17:17:24 +08:00
|
|
|
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`"
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|