mirror of
https://github.com/hanzoai/forum.git
synced 2026-09-30 21:51:19 +00:00
400 lines
14 KiB
JavaScript
400 lines
14 KiB
JavaScript
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
|
|
import { test } from "qunit";
|
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
|
|
|
acceptance("Composer - Image Preview", function (needs) {
|
|
needs.user({});
|
|
needs.settings({ allow_uncategorized_topics: true });
|
|
needs.site({ can_tag_topics: true });
|
|
needs.pretender((server, helper) => {
|
|
server.post("/uploads/lookup-urls", () => {
|
|
return helper.response([]);
|
|
});
|
|
server.get("/posts/419", () => {
|
|
return helper.response({ id: 419 });
|
|
});
|
|
server.get("/composer/mentions", () => {
|
|
return helper.response({
|
|
users: [],
|
|
user_reasons: {},
|
|
groups: { staff: { user_count: 30 } },
|
|
group_reasons: {},
|
|
max_users_notified_per_group_mention: 100,
|
|
});
|
|
});
|
|
});
|
|
|
|
const assertImageResized = (assert, uploads) => {
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue(uploads.join("\n"), "resizes uploaded image");
|
|
};
|
|
|
|
test("Image resizing buttons", async function (assert) {
|
|
await visit("/");
|
|
await click("#create-topic");
|
|
|
|
let uploads = [
|
|
// 0 Default markdown with dimensions- should work
|
|
"<a href='https://example.com'></a>",
|
|
// 1 Image with scaling percentage, should work
|
|
"",
|
|
// 2 image with scaling percentage and a proceeding whitespace, should work
|
|
"",
|
|
// 3 No dimensions, should not work
|
|
"",
|
|
// 4 Wrapped in backticks should not work
|
|
"``",
|
|
// 5 html image - should not work
|
|
"<img src='/images/avatar.png' wight='20' height='20'>",
|
|
// 6 two images one the same line, but both are syntactically correct - both should work
|
|
" ",
|
|
// 7 & 8 Identical images - both should work
|
|
"",
|
|
"",
|
|
// 9 Image with whitespaces in alt - should work
|
|
"",
|
|
// 10 Image with markdown title - should work
|
|
``,
|
|
// 11 bbcode - should not work
|
|
"[img]/images/avatar.png[/img]",
|
|
// 12 Image with data attributes
|
|
"",
|
|
];
|
|
|
|
await fillIn(".d-editor-input", uploads.join("\n"));
|
|
|
|
assert
|
|
.dom(".button-wrapper")
|
|
.exists({ count: 10 }, "adds correct number of scaling button groups");
|
|
|
|
// Default
|
|
uploads[0] =
|
|
"<a href='https://example.com'></a>";
|
|
await click(
|
|
".button-wrapper[data-image-index='0'] .scale-btn[data-scale='50']"
|
|
);
|
|
assertImageResized(assert, uploads);
|
|
|
|
// Targets the correct image if two on the same line
|
|
uploads[6] =
|
|
" ";
|
|
await click(
|
|
".button-wrapper[data-image-index='3'] .scale-btn[data-scale='50']"
|
|
);
|
|
assertImageResized(assert, uploads);
|
|
|
|
// Try the other image on the same line
|
|
uploads[6] =
|
|
" ";
|
|
await click(
|
|
".button-wrapper[data-image-index='4'] .scale-btn[data-scale='75']"
|
|
);
|
|
assertImageResized(assert, uploads);
|
|
|
|
// Make sure we target the correct image if there are duplicates
|
|
uploads[7] = "";
|
|
await click(
|
|
".button-wrapper[data-image-index='5'] .scale-btn[data-scale='50']"
|
|
);
|
|
assertImageResized(assert, uploads);
|
|
|
|
// Try the other dupe
|
|
uploads[8] = "";
|
|
await click(
|
|
".button-wrapper[data-image-index='6'] .scale-btn[data-scale='75']"
|
|
);
|
|
assertImageResized(assert, uploads);
|
|
|
|
// Don't mess with image titles
|
|
uploads[10] = ``;
|
|
await click(
|
|
".button-wrapper[data-image-index='8'] .scale-btn[data-scale='75']"
|
|
);
|
|
assertImageResized(assert, uploads);
|
|
|
|
// Keep data attributes
|
|
uploads[12] = ``;
|
|
await click(
|
|
".button-wrapper[data-image-index='9'] .scale-btn[data-scale='75']"
|
|
);
|
|
assertImageResized(assert, uploads);
|
|
|
|
await fillIn(
|
|
".d-editor-input",
|
|
`
|
|

|
|
|
|
\`<script>alert("xss")</script>\`
|
|
`
|
|
);
|
|
|
|
// don't add controls to video uploads with dimensions in name
|
|
await fillIn(
|
|
".d-editor-input",
|
|
""
|
|
);
|
|
assert.dom(".button-wrapper").doesNotExist();
|
|
|
|
assert
|
|
.dom("script")
|
|
.doesNotExist("it does not unescape script tags in code blocks");
|
|
});
|
|
|
|
test("Editing alt text (with enter key) for single image in preview updates alt text in composer", async function (assert) {
|
|
const scaleButtonContainer = ".scale-btn-container";
|
|
|
|
const editAltTextButton = ".alt-text-edit-btn";
|
|
|
|
const altTextEditOk = ".alt-text-edit-ok";
|
|
const altTextEditCancel = ".alt-text-edit-cancel";
|
|
|
|
await visit("/");
|
|
|
|
await click("#create-topic");
|
|
await fillIn(".d-editor-input", ``);
|
|
|
|
assert.dom(".alt-text").hasText("zorro", "correct alt text");
|
|
assert.dom(".alt-text").isVisible("alt text is visible");
|
|
assert.dom(editAltTextButton).isVisible("alt text edit button is visible");
|
|
assert.dom(".alt-text-input").isNotVisible("alt text input is hidden");
|
|
assert.dom(altTextEditOk).isNotVisible("alt text edit ok button is hidden");
|
|
assert
|
|
.dom(altTextEditCancel)
|
|
.isNotVisible("alt text edit cancel is hidden");
|
|
|
|
await click(editAltTextButton);
|
|
|
|
assert.dom(scaleButtonContainer).isNotVisible("scale buttons are hidden");
|
|
assert.dom(".alt-text").isNotVisible("alt text is hidden");
|
|
assert
|
|
.dom(editAltTextButton)
|
|
.isNotVisible("alt text edit button is hidden");
|
|
assert.dom(".alt-text-input").isVisible("alt text input is visible");
|
|
assert.dom(altTextEditOk).isVisible("alt text edit ok button is visible");
|
|
assert.dom(altTextEditCancel).isVisible("alt text edit cancel is hidden");
|
|
assert
|
|
.dom(".alt-text-input")
|
|
.hasValue("zorro", "correct alt text in input");
|
|
|
|
await triggerKeyEvent(".alt-text-input", "keypress", "[");
|
|
await triggerKeyEvent(".alt-text-input", "keypress", "]");
|
|
assert.dom(".alt-text-input").hasValue("zorro", "does not input [ ] keys");
|
|
|
|
await fillIn(".alt-text-input", "steak");
|
|
await triggerKeyEvent(".alt-text-input", "keypress", 13);
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue("", "alt text updated");
|
|
assert.dom(".alt-text").hasText("steak", "shows the alt text");
|
|
assert.dom(editAltTextButton).isVisible("alt text edit button is visible");
|
|
assert.dom(scaleButtonContainer).isVisible("scale buttons are visible");
|
|
assert.dom(editAltTextButton).isVisible("alt text edit button is visible");
|
|
assert.dom(".alt-text-input").isNotVisible("alt text input is hidden");
|
|
assert.dom(altTextEditOk).isNotVisible("alt text edit ok button is hidden");
|
|
assert
|
|
.dom(altTextEditCancel)
|
|
.isNotVisible("alt text edit cancel is hidden");
|
|
});
|
|
|
|
test("Editing alt text (with check button) in preview updates alt text in composer", async function (assert) {
|
|
const scaleButtonContainer = ".scale-btn-container";
|
|
const editAltTextButton = ".alt-text-edit-btn";
|
|
|
|
const altTextInput = ".alt-text-input";
|
|
const altTextEditOk = ".alt-text-edit-ok";
|
|
const altTextEditCancel = ".alt-text-edit-cancel";
|
|
|
|
await visit("/");
|
|
|
|
await click("#create-topic");
|
|
await fillIn(".d-editor-input", ``);
|
|
|
|
await click(editAltTextButton);
|
|
|
|
await fillIn(altTextInput, "steak");
|
|
await click(altTextEditOk);
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue("", "alt text updated");
|
|
assert.dom(".alt-text").hasText("steak", "shows the alt text");
|
|
|
|
assert.dom(editAltTextButton).isVisible("alt text edit button is visible");
|
|
assert.dom(scaleButtonContainer).isVisible("scale buttons are visible");
|
|
assert.dom(editAltTextButton).isVisible("alt text edit button is visible");
|
|
assert.dom(altTextInput).isNotVisible("alt text input is hidden");
|
|
assert.dom(altTextEditOk).isNotVisible("alt text edit ok button is hidden");
|
|
assert
|
|
.dom(altTextEditCancel)
|
|
.isNotVisible("alt text edit cancel is hidden");
|
|
});
|
|
|
|
test("Cancel alt text edit in preview does not update alt text in composer", async function (assert) {
|
|
const scaleButtonContainer = ".scale-btn-container";
|
|
|
|
const editAltTextButton = ".alt-text-edit-btn";
|
|
|
|
const altTextInput = ".alt-text-input";
|
|
const altTextEditOk = ".alt-text-edit-ok";
|
|
const altTextEditCancel = ".alt-text-edit-cancel";
|
|
|
|
await visit("/");
|
|
|
|
await click("#create-topic");
|
|
await fillIn(".d-editor-input", ``);
|
|
|
|
await click(editAltTextButton);
|
|
|
|
await fillIn(altTextInput, "steak");
|
|
await click(altTextEditCancel);
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue("", "alt text not updated");
|
|
assert.dom(".alt-text").hasText("zorro", "shows the unedited alt text");
|
|
|
|
assert.dom(editAltTextButton).isVisible("alt text edit button is visible");
|
|
assert.dom(scaleButtonContainer).isVisible("scale buttons are visible");
|
|
assert.dom(editAltTextButton).isVisible("alt text edit button is visible");
|
|
assert.dom(altTextInput).isNotVisible("alt text input is hidden");
|
|
assert.dom(altTextEditOk).isNotVisible("alt text edit ok button is hidden");
|
|
assert
|
|
.dom(altTextEditCancel)
|
|
.isNotVisible("alt text edit cancel is hidden");
|
|
});
|
|
|
|
test("Editing alt text for one of two images in preview updates correct alt text in composer", async function (assert) {
|
|
const editAltTextButton = ".alt-text-edit-btn";
|
|
const altTextInput = ".alt-text-input";
|
|
|
|
await visit("/");
|
|
await click("#create-topic");
|
|
|
|
await fillIn(
|
|
".d-editor-input",
|
|
` `
|
|
);
|
|
await click(editAltTextButton);
|
|
|
|
await fillIn(altTextInput, "tomtom");
|
|
await triggerKeyEvent(altTextInput, "keypress", "Enter");
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue(
|
|
` `,
|
|
"the correct image's alt text updated"
|
|
);
|
|
});
|
|
|
|
test("Deleting alt text for image empties alt text in composer and allows further modification", async function (assert) {
|
|
const editAltTextButton = ".alt-text-edit-btn";
|
|
const altTextInput = ".alt-text-input";
|
|
|
|
await visit("/");
|
|
|
|
await click("#create-topic");
|
|
await fillIn(".d-editor-input", ``);
|
|
|
|
await click(editAltTextButton);
|
|
|
|
await fillIn(altTextInput, "");
|
|
await triggerKeyEvent(altTextInput, "keypress", "Enter");
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue("", "alt text updated");
|
|
assert.dom(".alt-text").hasText("", "shows the alt text");
|
|
|
|
await click(editAltTextButton);
|
|
|
|
await fillIn(altTextInput, "tomtom");
|
|
await triggerKeyEvent(altTextInput, "keypress", "Enter");
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue("", "alt text updated");
|
|
});
|
|
|
|
test("Image delete button", async function (assert) {
|
|
await visit("/");
|
|
await click("#create-topic");
|
|
|
|
let uploads = [
|
|
"",
|
|
"",
|
|
];
|
|
|
|
await fillIn(".d-editor-input", uploads.join("\n"));
|
|
|
|
uploads[0] = ""; // delete the first image.
|
|
|
|
//click on the remove button of the first image
|
|
await click(".button-wrapper[data-image-index='0'] .delete-image-button");
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue(uploads.join("\n"), "Image should be removed from the editor");
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.doesNotIncludeValue("image_example_0", "does not have the first image");
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue(/image_example_1/, "has the second image");
|
|
});
|
|
});
|
|
|
|
acceptance("Composer - Image Preview - Plugin API", function (needs) {
|
|
needs.user({});
|
|
needs.settings({ allow_uncategorized_topics: true });
|
|
needs.site({ can_tag_topics: true });
|
|
needs.pretender((server, helper) => {
|
|
server.post("/uploads/lookup-urls", () => {
|
|
return helper.response([]);
|
|
});
|
|
});
|
|
|
|
needs.hooks.beforeEach(() => {
|
|
withPluginApi("1.25.0", (api) => {
|
|
api.addComposerImageWrapperButton(
|
|
"My Custom Button",
|
|
"custom-button-class",
|
|
"lock",
|
|
async (event) => {
|
|
if (event.target.classList.contains("custom-button-class")) {
|
|
await fillIn(".d-editor-input", "custom button change");
|
|
}
|
|
}
|
|
);
|
|
});
|
|
});
|
|
|
|
test("image wrapper includes extra API button and is functional", async function (assert) {
|
|
await visit("/");
|
|
await click("#create-topic");
|
|
|
|
await fillIn(
|
|
".d-editor-input",
|
|
""
|
|
);
|
|
|
|
assert
|
|
.dom(".image-wrapper .custom-button-class")
|
|
.exists("The custom button is added to the image preview wrapper");
|
|
|
|
await click(".custom-button-class");
|
|
|
|
assert
|
|
.dom(".d-editor-input")
|
|
.hasValue(
|
|
"custom button change",
|
|
"The custom button changes the editor input"
|
|
);
|
|
});
|
|
});
|