Files
discourse/app/assets/javascripts/discourse/tests/unit/models/composer-test.js
Jarek Radosz b81055a6d4 DEV: Convert more equal assertions (#29554)
…to either qunit-dom or `strictEqual`
2024-11-03 21:04:38 +01:00

489 lines
14 KiB
JavaScript

import { getOwner } from "@ember/owner";
import { setupTest } from "ember-qunit";
import { module, test } from "qunit";
import {
CREATE_TOPIC,
EDIT,
PRIVATE_MESSAGE,
REPLY,
} from "discourse/models/composer";
import pretender, {
parsePostData,
response,
} from "discourse/tests/helpers/create-pretender";
import { currentUser } from "discourse/tests/helpers/qunit-helpers";
function createComposer(opts = {}) {
opts.user ??= currentUser();
const store = getOwner(this).lookup("service:store");
return store.createRecord("composer", opts);
}
function openComposer(opts) {
const composer = createComposer.call(this, opts);
composer.open(opts);
return composer;
}
module("Unit | Model | composer", function (hooks) {
setupTest(hooks);
hooks.beforeEach(function () {
this.siteSettings = getOwner(this).lookup("service:site-settings");
});
test("replyLength", function (assert) {
const replyLength = (val, expectedLength) => {
const composer = createComposer.call(this, { reply: val });
assert.strictEqual(composer.replyLength, expectedLength);
};
replyLength("basic reply", 11, "basic reply length");
replyLength(" \nbasic reply\t", 11, "trims whitespaces");
replyLength("ba sic\n\nreply", 12, "count only significant whitespaces");
replyLength(
"1[quote=]not counted[/quote]2[quote=]at all[/quote]3",
3,
"removes quotes"
);
replyLength(
"1[quote=]not[quote=]counted[/quote]yay[/quote]2",
2,
"handles nested quotes correctly"
);
replyLength("<!-- a comment -->", 0, "remove comments");
replyLength(
"<!-- a comment -->\n more text \n<!-- a comment -->",
9,
"remove multiple comments"
);
replyLength(
"<!-- <!-- a comment --> -->more text",
12,
"remove multiple comments"
);
});
test("missingReplyCharacters", function (assert) {
this.siteSettings.min_first_post_length = 40;
const missingReplyCharacters = (
val,
isPM,
isFirstPost,
expected,
message
) => {
let action;
if (isFirstPost) {
action = CREATE_TOPIC;
} else if (isPM) {
action = PRIVATE_MESSAGE;
} else {
action = REPLY;
}
const composer = createComposer.call(this, { reply: val, action });
assert.strictEqual(composer.missingReplyCharacters, expected, message);
};
missingReplyCharacters(
"hi",
false,
false,
this.siteSettings.min_post_length - 2,
"too short public post"
);
missingReplyCharacters(
"hi",
false,
true,
this.siteSettings.min_first_post_length - 2,
"too short first post"
);
missingReplyCharacters(
"hi",
true,
false,
this.siteSettings.min_personal_message_post_length - 2,
"too short private message"
);
const link = "http://imgur.com/gallery/grxX8";
this.siteSettings.topic_featured_link_enabled = true;
this.siteSettings.topic_featured_link_allowed_category_ids = 12345;
const composer = createComposer.call(this, {
title: link,
categoryId: 12345,
featuredLink: link,
action: CREATE_TOPIC,
reply: link,
});
assert.strictEqual(
composer.missingReplyCharacters,
0,
"don't require any post content"
);
});
test("missingTitleCharacters", function (assert) {
const missingTitleCharacters = (val, isPM, expected, message) => {
const composer = createComposer.call(this, {
title: val,
action: isPM ? PRIVATE_MESSAGE : REPLY,
});
assert.strictEqual(composer.missingTitleCharacters, expected, message);
};
missingTitleCharacters(
"hi",
false,
this.siteSettings.min_topic_title_length - 2,
"too short post title"
);
missingTitleCharacters(
"z",
true,
this.siteSettings.min_personal_message_title_length - 1,
"too short pm title"
);
});
test("replyDirty", function (assert) {
const composer = createComposer.call(this);
assert.ok(!composer.replyDirty, "by default it's false");
composer.setProperties({
originalText: "hello",
reply: "hello",
});
assert.ok(
!composer.replyDirty,
"it's false when the originalText is the same as the reply"
);
composer.set("reply", "hello world");
assert.ok(composer.replyDirty, "it's true when the reply changes");
});
test("appendText", function (assert) {
const composer = createComposer.call(this);
assert.blank(composer.reply, "the reply is blank by default");
composer.appendText("hello");
assert.strictEqual(composer.reply, "hello", "it appends text to nothing");
composer.appendText(" world");
assert.strictEqual(
composer.reply,
"hello world",
"it appends text to existing text"
);
composer.clearState();
composer.appendText("a\n\n\n\nb");
composer.appendText("c", 3, { block: true });
assert.strictEqual(composer.reply, "a\n\nc\n\nb");
composer.clearState();
composer.appendText("ab");
composer.appendText("c", 1, { block: true });
assert.strictEqual(composer.reply, "a\n\nc\n\nb");
composer.clearState();
composer.appendText("\nab");
composer.appendText("c", 0, { block: true });
assert.strictEqual(composer.reply, "c\n\nab");
});
test("prependText", function (assert) {
const composer = createComposer.call(this);
assert.blank(composer.reply, "the reply is blank by default");
composer.prependText("hello");
assert.strictEqual(composer.reply, "hello", "it prepends text to nothing");
composer.prependText("world ");
assert.strictEqual(
composer.reply,
"world hello",
"it prepends text to existing text"
);
composer.prependText("before new line", { new_line: true });
assert.strictEqual(
composer.reply,
"before new line\n\nworld hello",
"it prepends text with new line to existing text"
);
});
test("Title length for regular topics", function (assert) {
this.siteSettings.min_topic_title_length = 5;
this.siteSettings.max_topic_title_length = 10;
const composer = createComposer.call(this);
composer.set("title", "asdf");
assert.ok(!composer.titleLengthValid, "short titles are not valid");
composer.set("title", "this is a long title");
assert.ok(!composer.titleLengthValid, "long titles are not valid");
composer.set("title", "just right");
assert.ok(composer.titleLengthValid, "in the range is okay");
});
test("Title length for private messages", function (assert) {
this.siteSettings.min_personal_message_title_length = 5;
this.siteSettings.max_topic_title_length = 10;
const composer = createComposer.call(this, { action: PRIVATE_MESSAGE });
composer.set("title", "asdf");
assert.ok(!composer.titleLengthValid, "short titles are not valid");
composer.set("title", "this is a long title");
assert.ok(!composer.titleLengthValid, "long titles are not valid");
composer.set("title", "just right");
assert.ok(composer.titleLengthValid, "in the range is okay");
});
test("Post length for private messages with non human users", function (assert) {
const store = getOwner(this).lookup("service:store");
const topic = store.createRecord("topic", { pm_with_non_human_user: true });
const composer = createComposer.call(this, {
topic,
});
assert.strictEqual(composer.minimumPostLength, 1);
});
test("editingFirstPost", function (assert) {
const composer = createComposer.call(this);
assert.ok(!composer.editingFirstPost, "it's false by default");
const store = getOwner(this).lookup("service:store");
const post = store.createRecord("post", { id: 123, post_number: 2 });
composer.setProperties({ post, action: EDIT });
assert.ok(
!composer.editingFirstPost,
"it's false when not editing the first post"
);
post.set("post_number", 1);
assert.ok(
composer.editingFirstPost,
"it's true when editing the first post"
);
});
test("clearState", function (assert) {
const store = getOwner(this).lookup("service:store");
const composer = createComposer.call(this, {
originalText: "asdf",
reply: "asdf2",
post: store.createRecord("post", { id: 1 }),
title: "wat",
});
composer.clearState();
assert.blank(composer.originalText);
assert.blank(composer.reply);
assert.blank(composer.post);
assert.blank(composer.title);
});
test("initial category when uncategorized is allowed", function (assert) {
this.siteSettings.allow_uncategorized_topics = true;
const composer = openComposer.call(this, {
action: CREATE_TOPIC,
draftKey: "abcd",
draftSequence: 1,
});
assert.ok(!composer.categoryId, "Uncategorized by default");
});
test("initial category when uncategorized is not allowed", function (assert) {
this.siteSettings.allow_uncategorized_topics = false;
const composer = openComposer.call(this, {
action: CREATE_TOPIC,
draftKey: "abcd",
draftSequence: 1,
});
assert.ok(
!composer.categoryId,
"Uncategorized by default. Must choose a category."
);
});
test("initial category when creating PM and there is a default composer category", function (assert) {
this.siteSettings.default_composer_category = 2;
const composer = openComposer.call(this, {
action: PRIVATE_MESSAGE,
draftKey: "abcd",
draftSequence: 1,
});
assert.strictEqual(
composer.categoryId,
null,
"it doesn't save the category"
);
});
test("open with a quote", function (assert) {
const quote =
'[quote="neil, post:5, topic:413"]\nSimmer down you two.\n[/quote]';
const newComposer = () => {
return openComposer.call(this, {
action: REPLY,
draftKey: "abcd",
draftSequence: 1,
quote,
});
};
assert.strictEqual(
newComposer().originalText,
quote,
"originalText is the quote"
);
assert.strictEqual(
newComposer().replyDirty,
false,
"replyDirty is initially false with a quote"
);
});
test("Title length for static page topics as admin", function (assert) {
this.siteSettings.min_topic_title_length = 5;
this.siteSettings.max_topic_title_length = 10;
const composer = createComposer.call(this);
const store = getOwner(this).lookup("service:store");
const post = store.createRecord("post", {
id: 123,
post_number: 2,
static_doc: true,
});
composer.setProperties({ post, action: EDIT });
composer.set("title", "asdf");
assert.ok(composer.titleLengthValid, "admins can use short titles");
composer.set("title", "this is a long title");
assert.ok(composer.titleLengthValid, "admins can use long titles");
composer.set("title", "just right");
assert.ok(composer.titleLengthValid, "in the range is okay");
composer.set("title", "");
assert.ok(
!composer.titleLengthValid,
"admins must set title to at least 1 character"
);
});
test("title placeholder depends on what you're doing", function (assert) {
this.siteSettings.topic_featured_link_enabled = false;
let composer = createComposer.call(this, { action: CREATE_TOPIC });
assert.strictEqual(
composer.titlePlaceholder,
"composer.title_placeholder",
"placeholder for normal topic"
);
composer = createComposer.call(this, { action: PRIVATE_MESSAGE });
assert.strictEqual(
composer.titlePlaceholder,
"composer.title_placeholder",
"placeholder for private message"
);
this.siteSettings.topic_featured_link_enabled = true;
composer = createComposer.call(this, { action: CREATE_TOPIC });
assert.strictEqual(
composer.titlePlaceholder,
"composer.title_or_link_placeholder",
"placeholder invites you to paste a link"
);
composer = createComposer.call(this, { action: PRIVATE_MESSAGE });
assert.strictEqual(
composer.titlePlaceholder,
"composer.title_placeholder",
"placeholder for private message with topic links enabled"
);
});
test("allows featured link before choosing a category", function (assert) {
this.siteSettings.topic_featured_link_enabled = true;
this.siteSettings.allow_uncategorized_topics = false;
const composer = createComposer.call(this, { action: CREATE_TOPIC });
assert.strictEqual(
composer.titlePlaceholder,
"composer.title_or_link_placeholder",
"placeholder invites you to paste a link"
);
assert.ok(composer.canEditTopicFeaturedLink, "can paste link");
});
test("targetRecipientsArray contains types", function (assert) {
const composer = createComposer.call(this, {
targetRecipients: "test,codinghorror,staff,foo@bar.com",
});
assert.deepEqual(composer.targetRecipientsArray, [
{ name: "test", type: "user" },
{ name: "codinghorror", type: "user" },
{ name: "staff", type: "group" },
{ name: "foo@bar.com", type: "email" },
]);
});
test("can add meta_data", async function (assert) {
let saved = false;
pretender.post("/posts", function (request) {
const data = parsePostData(request.requestBody);
assert.strictEqual(data.meta_data.some_custom_field, "some_value");
saved = true;
return response(200, {
success: true,
action: "create_post",
post: {
id: 12345,
topic_id: 280,
topic_slug: "internationalization-localization",
},
});
});
const composer = createComposer.call(this, {});
await composer.open({
action: CREATE_TOPIC,
title: "some topic title here",
categoryId: 1,
reply: "some reply here some reply here some reply here",
draftKey: "abcd",
draftSequence: 1,
});
assert.false(composer.loading);
composer.metaData = { some_custom_field: "some_value" };
await composer.save({});
assert.true(saved);
});
});