Our method of loading a subset of client settings into tests via
tests/helpers/site-settings.js can be improved upon. Currently we have a
hardcoded subset of the client settings, which may get out of date and not have
the correct defaults. As well as this plugins do not get their settings into the
tests, so whenever you need a setting from a plugin, even if it has a default,
you have to do needs.setting({ ... }) which is inconvenient.
This commit introduces an ember CLI build step to take the site_settings.yml and
all the plugin settings.yml files, pull out the client settings, and dump them
into a variable in a single JS file we can load in our tests, so we have the
correct selection of settings and default values in our JS tests. It also fixes
many, many tests that were operating under incorrect assumptions or old
settings.
Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
379 lines
13 KiB
JavaScript
379 lines
13 KiB
JavaScript
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
|
|
import {
|
|
acceptance,
|
|
count,
|
|
exists,
|
|
invisible,
|
|
query,
|
|
visible,
|
|
} from "discourse/tests/helpers/qunit-helpers";
|
|
import { test } from "qunit";
|
|
|
|
acceptance("Composer - Image Preview", function (needs) {
|
|
needs.user();
|
|
needs.settings({ enable_whispers: true, 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("/u/is_local_username", () => {
|
|
return helper.response({
|
|
valid: [],
|
|
valid_groups: ["staff"],
|
|
mentionable_groups: [{ name: "staff", user_count: 30 }],
|
|
cannot_see: [],
|
|
max_users_notified_per_group_mention: 100,
|
|
});
|
|
});
|
|
});
|
|
|
|
const assertImageResized = (assert, uploads) => {
|
|
assert.strictEqual(
|
|
query(".d-editor-input").value,
|
|
uploads.join("\n"),
|
|
"it 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.strictEqual(
|
|
count(".button-wrapper"),
|
|
10,
|
|
"it adds correct amount 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>\`
|
|
`
|
|
);
|
|
|
|
assert.ok(
|
|
!exists("script"),
|
|
"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 readonlyAltText = ".alt-text";
|
|
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", ``);
|
|
|
|
assert.equal(query(readonlyAltText).innerText, "zorro", "correct alt text");
|
|
assert.ok(visible(readonlyAltText), "alt text is visible");
|
|
assert.ok(visible(editAltTextButton), "alt text edit button is visible");
|
|
assert.ok(invisible(altTextInput), "alt text input is hidden");
|
|
assert.ok(invisible(altTextEditOk), "alt text edit ok button is hidden");
|
|
assert.ok(invisible(altTextEditCancel), "alt text edit cancel is hidden");
|
|
|
|
await click(editAltTextButton);
|
|
|
|
assert.ok(invisible(scaleButtonContainer), "scale buttons are hidden");
|
|
assert.ok(invisible(readonlyAltText), "alt text is hidden");
|
|
assert.ok(invisible(editAltTextButton), "alt text edit button is hidden");
|
|
assert.ok(visible(altTextInput), "alt text input is visible");
|
|
assert.ok(visible(altTextEditOk), "alt text edit ok button is visible");
|
|
assert.ok(visible(altTextEditCancel), "alt text edit cancel is hidden");
|
|
assert.equal(
|
|
query(altTextInput).value,
|
|
"zorro",
|
|
"correct alt text in input"
|
|
);
|
|
|
|
await triggerKeyEvent(altTextInput, "keypress", "[");
|
|
await triggerKeyEvent(altTextInput, "keypress", "]");
|
|
assert.equal(query(altTextInput).value, "zorro", "does not input [ ] keys");
|
|
|
|
await fillIn(altTextInput, "steak");
|
|
await triggerKeyEvent(altTextInput, "keypress", 13);
|
|
|
|
assert.equal(
|
|
query(".d-editor-input").value,
|
|
"",
|
|
"alt text updated"
|
|
);
|
|
assert.equal(
|
|
query(readonlyAltText).innerText,
|
|
"steak",
|
|
"shows the alt text"
|
|
);
|
|
assert.ok(visible(editAltTextButton), "alt text edit button is visible");
|
|
assert.ok(visible(scaleButtonContainer), "scale buttons are visible");
|
|
assert.ok(visible(editAltTextButton), "alt text edit button is visible");
|
|
assert.ok(invisible(altTextInput), "alt text input is hidden");
|
|
assert.ok(invisible(altTextEditOk), "alt text edit ok button is hidden");
|
|
assert.ok(invisible(altTextEditCancel), "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 readonlyAltText = ".alt-text";
|
|
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.equal(
|
|
query(".d-editor-input").value,
|
|
"",
|
|
"alt text updated"
|
|
);
|
|
assert.equal(
|
|
query(readonlyAltText).innerText,
|
|
"steak",
|
|
"shows the alt text"
|
|
);
|
|
|
|
assert.ok(visible(editAltTextButton), "alt text edit button is visible");
|
|
assert.ok(visible(scaleButtonContainer), "scale buttons are visible");
|
|
assert.ok(visible(editAltTextButton), "alt text edit button is visible");
|
|
assert.ok(invisible(altTextInput), "alt text input is hidden");
|
|
assert.ok(invisible(altTextEditOk), "alt text edit ok button is hidden");
|
|
assert.ok(invisible(altTextEditCancel), "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 readonlyAltText = ".alt-text";
|
|
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.equal(
|
|
query(".d-editor-input").value,
|
|
"",
|
|
"alt text not updated"
|
|
);
|
|
assert.equal(
|
|
query(readonlyAltText).innerText,
|
|
"zorro",
|
|
"shows the unedited alt text"
|
|
);
|
|
|
|
assert.ok(visible(editAltTextButton), "alt text edit button is visible");
|
|
assert.ok(visible(scaleButtonContainer), "scale buttons are visible");
|
|
assert.ok(visible(editAltTextButton), "alt text edit button is visible");
|
|
assert.ok(invisible(altTextInput), "alt text input is hidden");
|
|
assert.ok(invisible(altTextEditOk), "alt text edit ok button is hidden");
|
|
assert.ok(invisible(altTextEditCancel), "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.equal(
|
|
query(".d-editor-input").value,
|
|
` `,
|
|
"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 altText = ".alt-text";
|
|
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.equal(
|
|
query(".d-editor-input").value,
|
|
"",
|
|
"alt text updated"
|
|
);
|
|
assert.equal(query(altText).innerText, "", "shows the alt text");
|
|
|
|
await click(editAltTextButton);
|
|
|
|
await fillIn(altTextInput, "tomtom");
|
|
await triggerKeyEvent(altTextInput, "keypress", "Enter");
|
|
|
|
assert.equal(
|
|
query(".d-editor-input").value,
|
|
"",
|
|
"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.strictEqual(
|
|
query(".d-editor-input").value,
|
|
uploads.join("\n"),
|
|
"Image should be removed from the editor"
|
|
);
|
|
|
|
assert.equal(
|
|
query(".d-editor-input").value.includes("image_example_0"),
|
|
false,
|
|
"It shouldn't have the first image"
|
|
);
|
|
|
|
assert.equal(
|
|
query(".d-editor-input").value.includes("image_example_1"),
|
|
true,
|
|
"It should have the second image"
|
|
);
|
|
});
|
|
});
|