DEV: select-kit 2 (#7998)

This new iteration of select-kit focuses on following best principales and disallowing mutations inside select-kit components. A best effort has been made to avoid breaking changes, however if you content was a flat array, eg: ["foo", "bar"] You will need to set valueProperty=null and nameProperty=null on the component.

Also almost every component should have an `onChange` handler now to decide what to do with the updated data. **select-kit will not mutate your data by itself anymore**
This commit is contained in:
Joffrey JAFFEUX
2020-02-03 14:22:14 +01:00
committed by GitHub
parent 0e2cbee339
commit 0431942f3d
278 changed files with 7566 additions and 6957 deletions
@@ -0,0 +1,141 @@
import componentTest from "helpers/component-test";
import { testSelectKitModule } from "./select-kit-test-helper";
testSelectKitModule("category-chooser");
function template(options = []) {
return `
{{category-chooser
value=value
options=(hash
${options.join("\n")}
)
}}
`;
}
componentTest("with value", {
template: template(),
beforeEach() {
this.set("value", 2);
},
async test(assert) {
assert.equal(this.subject.header().value(), 2);
assert.equal(this.subject.header().label(), "feature");
}
});
componentTest("with excludeCategoryId", {
template: template(["excludeCategoryId=2"]),
async test(assert) {
await this.subject.expand();
assert.notOk(this.subject.rowByValue(2).exists());
}
});
componentTest("with scopedCategoryId", {
template: template(["scopedCategoryId=2"]),
async test(assert) {
await this.subject.expand();
assert.equal(
this.subject.rowByIndex(0).title(),
"Discussion about features or potential features of Discourse: how they work, why they work, etc."
);
assert.equal(this.subject.rowByIndex(0).value(), 2);
assert.equal(
this.subject.rowByIndex(1).title(),
"My idea here is to have mini specs for features we would like built but have no bandwidth to build"
);
assert.equal(this.subject.rowByIndex(1).value(), 26);
assert.equal(this.subject.rows().length, 2);
await this.subject.fillInFilter("spec");
assert.equal(this.subject.rows().length, 1);
}
});
componentTest("with allowUncategorized=null", {
template: template(["allowUncategorized=null"]),
beforeEach() {
this.siteSettings.allow_uncategorized_topics = false;
},
test(assert) {
assert.equal(this.subject.header().value(), null);
assert.equal(this.subject.header().label(), "category…");
}
});
componentTest("with allowUncategorized=null rootNone=true", {
template: template(["allowUncategorized=null", "none=true"]),
beforeEach() {
this.siteSettings.allow_uncategorized_topics = false;
},
test(assert) {
assert.equal(this.subject.header().value(), null);
assert.equal(this.subject.header().label(), "(no category)");
}
});
componentTest("with disallowed uncategorized, none", {
template: template(["allowUncategorized=null", "none='test.root'"]),
beforeEach() {
I18n.translations[I18n.locale].js.test = { root: "root none label" };
this.siteSettings.allow_uncategorized_topics = false;
},
test(assert) {
assert.equal(this.subject.header().value(), null);
assert.equal(this.subject.header().label(), "root none label");
}
});
componentTest("with allowed uncategorized", {
template: template(["allowUncategorized=true"]),
beforeEach() {
this.siteSettings.allow_uncategorized_topics = true;
},
test(assert) {
assert.equal(this.subject.header().value(), null);
assert.equal(this.subject.header().label(), "uncategorized");
}
});
componentTest("with allowed uncategorized and none=true", {
template: template(["allowUncategorized=true", "none=true"]),
beforeEach() {
this.siteSettings.allow_uncategorized_topics = true;
},
test(assert) {
assert.equal(this.subject.header().value(), null);
assert.equal(this.subject.header().label(), "(no category)");
}
});
componentTest("with allowed uncategorized and none", {
template: template(["allowUncategorized=true", "none='test.root'"]),
beforeEach() {
I18n.translations[I18n.locale].js.test = { root: "root none label" };
this.siteSettings.allow_uncategorized_topics = true;
},
test(assert) {
assert.equal(this.subject.header().value(), null);
assert.equal(this.subject.header().label(), "root none label");
}
});
@@ -0,0 +1,336 @@
import Category from "discourse/models/category";
import componentTest from "helpers/component-test";
import { testSelectKitModule } from "./select-kit-test-helper";
import {
NO_CATEGORIES_ID,
ALL_CATEGORIES_ID
} from "select-kit/components/category-drop";
testSelectKitModule("category-drop");
function initCategories(context) {
const categories = context.site.categoriesList;
context.setProperties({
category: categories.firstObject,
categories
});
}
function initCategoriesWithParentCategory(context) {
const parentCategory = Category.findById(2);
const childCategories = context.site.categoriesList.filter(c => {
return c.parentCategory === parentCategory;
});
context.setProperties({
parentCategory,
category: null,
categories: childCategories
});
}
function template(options = []) {
return `
{{category-drop
category=category
categories=categories
parentCategory=parentCategory
options=(hash
${options.join("\n")}
)
}}
`;
}
componentTest("caretUpIcon", {
template: `
{{category-drop
category=value
categories=content
}}
`,
async test(assert) {
const $header = this.subject.header().el();
assert.ok(
exists($header.find(`.d-icon-caret-right`)),
"it uses the correct default icon"
);
}
});
componentTest("none", {
template: `
{{category-drop
category=value
categories=content
}}
`,
async test(assert) {
const text = this.subject.header().label();
assert.equal(
text,
I18n.t("category.all").toLowerCase(),
"it uses the noneLabel"
);
}
});
componentTest("[not staff - TL0] displayCategoryDescription", {
template: template(),
beforeEach() {
Ember.set(this.currentUser, "staff", false);
Ember.set(this.currentUser, "trustLevel", 0);
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const row = this.subject.rowByValue(this.category.id);
assert.ok(
exists(row.el().find(".category-desc")),
"it shows category description for newcomers"
);
}
});
componentTest("[not staff - TL1] displayCategoryDescription", {
template: template(),
beforeEach() {
Ember.set(this.currentUser, "staff", false);
Ember.set(this.currentUser, "trustLevel", 1);
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const row = this.subject.rowByValue(this.category.id);
assert.ok(
exists(row.el().find(".category-desc")),
"it doesn't show category description for TL0+"
);
}
});
componentTest("[staff - TL0] displayCategoryDescription", {
template: template(),
beforeEach() {
Ember.set(this.currentUser, "staff", true);
Ember.set(this.currentUser, "trustLevel", 0);
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const row = this.subject.rowByValue(this.category.id);
assert.ok(
exists(row.el().find(".category-desc")),
"it doesn't show category description for staff"
);
}
});
componentTest("hideParentCategory (default: false)", {
template: template(),
beforeEach() {
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const row = this.subject.rowByValue(this.category.id);
assert.equal(row.value(), this.category.id);
assert.equal(this.category.parent_category_id, null);
}
});
componentTest("hideParentCategory (true)", {
template: template(["hideParentCategory=true"]),
beforeEach() {
initCategoriesWithParentCategory(this);
},
async test(assert) {
await this.subject.expand();
const parentRow = this.subject.rowByValue(this.parentCategory.id);
assert.notOk(parentRow.exists(), "the parent row is not showing");
const childCategory = this.categories.firstObject;
const childCategoryId = childCategory.id;
const childRow = this.subject.rowByValue(childCategoryId);
assert.ok(childRow.exists(), "the child row is showing");
const $categoryStatus = childRow.el().find(".category-status");
assert.ok(
$categoryStatus
.text()
.trim()
.match(/^spec/)
);
}
});
componentTest("allowUncategorized (default: true)", {
template: template(),
beforeEach() {
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const uncategorizedCategoryId = this.site.uncategorized_category_id;
const row = this.subject.rowByValue(uncategorizedCategoryId);
assert.ok(row.exists(), "the uncategorized row is showing");
}
});
componentTest("allowUncategorized (false)", {
template: template(["allowUncategorized=false"]),
beforeEach() {
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const uncategorizedCategoryId = this.site.uncategorized_category_id;
const row = this.subject.rowByValue(uncategorizedCategoryId);
assert.notOk(row.exists(), "the uncategorized row is not showing");
}
});
componentTest("countSubcategories (default: false)", {
template: template(),
beforeEach() {
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const category = Category.findById(7);
const row = this.subject.rowByValue(category.id);
const topicCount = row
.el()
.find(".topic-count")
.text()
.trim();
assert.equal(
topicCount,
"× 481",
"it doesn't include the topic count of subcategories"
);
}
});
componentTest("countSubcategories (true)", {
template: template(["countSubcategories=true"]),
beforeEach() {
initCategories(this);
},
async test(assert) {
await this.subject.expand();
const category = Category.findById(7);
const row = this.subject.rowByValue(category.id);
const topicCount = row
.el()
.find(".topic-count")
.text()
.trim();
assert.equal(
topicCount,
"× 584",
"it includes the topic count of subcategories"
);
}
});
componentTest("shortcuts:default", {
template: template(),
beforeEach() {
initCategories(this);
this.set("category", null);
},
async test(assert) {
await this.subject.expand();
assert.equal(
this.subject.rowByIndex(0).value(),
this.categories.firstObject.id,
"Shortcuts are not prepended when no category is selected"
);
}
});
componentTest("shortcuts:category is set", {
template: template(),
beforeEach() {
initCategories(this);
},
async test(assert) {
await this.subject.expand();
assert.equal(this.subject.rowByIndex(0).value(), ALL_CATEGORIES_ID);
}
});
componentTest("shortcuts with parentCategory/subCategory=true:default", {
template: template(["subCategory=true"]),
beforeEach() {
initCategoriesWithParentCategory(this);
},
async test(assert) {
await this.subject.expand();
assert.equal(this.subject.rowByIndex(0).value(), NO_CATEGORIES_ID);
}
});
componentTest(
"shortcuts with parentCategory/subCategory=true:category is selected",
{
template: template(["subCategory=true"]),
beforeEach() {
initCategoriesWithParentCategory(this);
this.set("category", this.categories.firstObject);
},
async test(assert) {
await this.subject.expand();
assert.equal(this.subject.rowByIndex(0).value(), ALL_CATEGORIES_ID);
assert.equal(this.subject.rowByIndex(1).value(), NO_CATEGORIES_ID);
}
}
);
@@ -0,0 +1,102 @@
import selectKit from "helpers/select-kit-helper";
import componentTest from "helpers/component-test";
moduleForComponent("select-kit/combo-box", {
integration: true,
beforeEach() {
this.set("subject", selectKit());
}
});
const DEFAULT_CONTENT = [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" }
];
const DEFAULT_VALUE = 1;
const setDefaultState = (ctx, options) => {
const properties = Object.assign(
{
content: DEFAULT_CONTENT,
value: DEFAULT_VALUE
},
options || {}
);
ctx.setProperties(properties);
};
componentTest("options.clearable", {
template: `
{{combo-box
value=value
content=content
onChange=onChange
options=(hash clearable=clearable)
}}
`,
beforeEach() {
setDefaultState(this, {
clearable: true,
onChange: value => {
this.set("value", value);
}
});
},
async test(assert) {
const $header = this.subject.header();
assert.ok(
exists($header.el().find(".btn-clear")),
"it shows the clear button"
);
assert.equal($header.value(), DEFAULT_VALUE);
await click($header.el().find(".btn-clear"));
assert.notOk(
exists($header.el().find(".btn-clear")),
"it hides the clear button"
);
assert.equal($header.value(), null);
}
});
componentTest("options.{caretUpIcon,caretDownIcon}", {
template: `
{{combo-box
value=value
content=content
options=(hash
caretUpIcon=caretUpIcon
caretDownIcon=caretDownIcon
)
}}
`,
beforeEach() {
setDefaultState(this, {
caretUpIcon: "pencil-alt",
caretDownIcon: "trash-alt"
});
},
async test(assert) {
const $header = this.subject.header().el();
assert.ok(
exists($header.find(`.d-icon-${this.caretDownIcon}`)),
"it uses the icon provided"
);
await this.subject.expand();
assert.ok(
exists($header.find(`.d-icon-${this.caretUpIcon}`)),
"it uses the icon provided"
);
}
});
@@ -0,0 +1,111 @@
import selectKit from "helpers/select-kit-helper";
import componentTest from "helpers/component-test";
moduleForComponent("select-kit/dropdown-select-box", {
integration: true,
beforeEach() {
this.set("subject", selectKit());
}
});
const DEFAULT_CONTENT = [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" }
];
const DEFAULT_VALUE = 1;
const setDefaultState = (ctx, options) => {
const properties = Object.assign(
{
content: DEFAULT_CONTENT,
value: DEFAULT_VALUE,
onChange: value => {
this.set("value", value);
}
},
options || {}
);
ctx.setProperties(properties);
};
componentTest("selection behavior", {
template: `
{{dropdown-select-box
value=value
content=content
}}
`,
beforeEach() {
setDefaultState(this);
},
async test(assert) {
await this.subject.expand();
assert.ok(this.subject.isExpanded());
await this.subject.selectRowByValue(DEFAULT_VALUE);
assert.notOk(
this.subject.isExpanded(),
"it collapses the dropdown on select"
);
}
});
componentTest("options.showFullTitle=false", {
template: `
{{dropdown-select-box
value=value
content=content
options=(hash
showFullTitle=showFullTitle
)
}}
`,
beforeEach() {
setDefaultState(this, { showFullTitle: false });
},
async test(assert) {
assert.ok(
!exists(
this.subject
.header()
.el()
.find(".selected-name .body")
),
"it hides the text of the selected item"
);
}
});
componentTest("options.showFullTitle=true", {
template: `
{{dropdown-select-box
value=value
content=content
options=(hash
showFullTitle=showFullTitle
)
}}
`,
beforeEach() {
setDefaultState(this, { showFullTitle: true });
},
async test(assert) {
assert.ok(
exists(
this.subject
.header()
.el()
.find(".selected-name")
),
"it shows the text of the selected item"
);
}
});
@@ -0,0 +1,35 @@
import componentTest from "helpers/component-test";
import { testSelectKitModule } from "./select-kit-test-helper";
testSelectKitModule("list-setting");
function template(options = []) {
return `
{{list-setting
value=value
choices=choices
options=(hash
${options.join("\n")}
)
}}
`;
}
componentTest("default", {
template: template(),
beforeEach() {
this.set("value", ["bold", "italic"]);
this.set("choices", ["bold", "italic", "underline"]);
},
async test(assert) {
assert.equal(this.subject.header().name(), "bold,italic");
assert.equal(this.subject.header().value(), "bold,italic");
await this.subject.expand();
assert.equal(this.subject.rows().length, 1);
assert.equal(this.subject.rowByIndex(0).value(), "underline");
}
});
@@ -0,0 +1,63 @@
import componentTest from "helpers/component-test";
import { testSelectKitModule } from "./select-kit-test-helper";
testSelectKitModule("multi-select");
function template(options = []) {
return `
{{multi-select
value=value
content=content
options=(hash
${options.join("\n")}
)
}}
`;
}
const DEFAULT_CONTENT = [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" }
];
const setDefaultState = (ctx, options) => {
const properties = Object.assign(
{
content: DEFAULT_CONTENT,
value: null
},
options || {}
);
ctx.setProperties(properties);
};
componentTest("content", {
template: template(),
beforeEach() {
setDefaultState(this);
},
async test(assert) {
await this.subject.expand();
const content = this.subject.displayedContent();
assert.equal(content.length, 3, "it shows rows");
assert.equal(
content[0].name,
this.content.firstObject.name,
"it has the correct name"
);
assert.equal(
content[0].id,
this.content.firstObject.id,
"it has the correct value"
);
assert.equal(
this.subject.header().value(),
null,
"it doesn't set a value from the content"
);
}
});
@@ -0,0 +1,40 @@
import componentTest from "helpers/component-test";
import { testSelectKitModule, setDefaultState } from "./select-kit-test-helper";
testSelectKitModule("notifications-button");
componentTest("default", {
template: `
{{notifications-button
value=value
options=(hash
i18nPrefix=i18nPrefix
i18nPostfix=i18nPostfix
)
}}
`,
beforeEach() {
this.set("value", 1);
setDefaultState(this, 1, { i18nPrefix: "pre", i18nPostfix: "post" });
},
async test(assert) {
assert.ok(this.subject.header().value());
assert.ok(
this.subject
.header()
.label()
.includes(`${this.i18nPrefix}.regular${this.i18nPostfix}`),
"it shows the regular choice when value is not set"
);
const icon = this.subject.header().icon()[0];
assert.ok(
icon.classList.contains("d-icon-d-regular"),
"it shows the correct icon"
);
}
});
@@ -0,0 +1,38 @@
import selectKit from "helpers/select-kit-helper";
import componentTest from "helpers/component-test";
import Topic from "discourse/models/topic";
const buildTopic = function() {
return Topic.create({
id: 1234,
title: "Qunit Test Topic",
deleted: false,
pinned: true
});
};
moduleForComponent("select-kit/pinned-options", {
integration: true,
beforeEach: function() {
this.set("subject", selectKit());
}
});
componentTest("updating the content refreshes the list", {
template: "{{pinned-options value=pinned topic=topic}}",
beforeEach() {
this.siteSettings.automatically_unpin_topics = false;
this.set("topic", buildTopic());
this.set("pinned", "pinned");
},
async test(assert) {
assert.equal(this.subject.header().name(), "pinned");
// we do it manually as clearPin is an ajax call
await this.set("pinned", false);
assert.equal(this.subject.header().name(), "unpinned");
}
});
@@ -0,0 +1,33 @@
import selectKit from "helpers/select-kit-helper";
export function testSelectKitModule(moduleName, options = {}) {
moduleForComponent(`select-kit/${moduleName}`, {
integration: true,
beforeEach() {
this.set("subject", selectKit());
options.beforeEach && options.beforeEach.call(this);
},
afterEach() {
options.afterEach && options.afterEach.call(this);
}
});
}
export const DEFAULT_CONTENT = [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" }
];
export function setDefaultState(ctx, value, options = {}) {
const properties = Object.assign(
{
onChange: v => {
this.set("value", v);
}
},
options || {}
);
ctx.setProperties(properties);
}
@@ -0,0 +1,217 @@
import componentTest from "helpers/component-test";
import { testSelectKitModule } from "./select-kit-test-helper";
testSelectKitModule("single-select");
function template(options = []) {
return `
{{single-select
value=value
content=content
nameProperty=nameProperty
valueProperty=valueProperty
onChange=onChange
options=(hash
${options.join("\n")}
)
}}
`;
}
const DEFAULT_CONTENT = [
{ id: 1, name: "foo" },
{ id: 2, name: "bar" },
{ id: 3, name: "baz" }
];
const DEFAULT_VALUE = 1;
const setDefaultState = (ctx, options) => {
const properties = Object.assign(
{
content: DEFAULT_CONTENT,
value: DEFAULT_VALUE,
nameProperty: "name",
valueProperty: "id",
onChange: value => {
ctx.set("value", value);
}
},
options || {}
);
ctx.setProperties(properties);
};
componentTest("content", {
template: "{{single-select content=content}}",
beforeEach() {
setDefaultState(this);
},
async test(assert) {
await this.subject.expand();
const content = this.subject.displayedContent();
assert.equal(content.length, 3, "it shows rows");
assert.equal(
content[0].name,
this.content.firstObject.name,
"it has the correct name"
);
assert.equal(
content[0].id,
this.content.firstObject.id,
"it has the correct value"
);
assert.equal(
this.subject.header().value(),
null,
"it doesn't set a value from the content"
);
}
});
componentTest("value", {
template: template(),
beforeEach() {
setDefaultState(this);
},
test(assert) {
assert.equal(
this.subject.header().value(this.content),
1,
"it selects the correct content to display"
);
}
});
componentTest("options.filterable", {
template: template(["filterable=filterable"]),
beforeEach() {
setDefaultState(this, { filterable: true });
},
async test(assert) {
await this.subject.expand();
assert.ok(this.subject.filter().exists(), "it shows the filter");
const filter = this.subject.displayedContent()[1].name;
await this.subject.fillInFilter(filter);
assert.equal(
this.subject.displayedContent()[0].name,
filter,
"it filters the list"
);
}
});
componentTest("options.limitMatches", {
template: template(["limitMatches=limitMatches", "filterable=filterable"]),
beforeEach() {
setDefaultState(this, { limitMatches: 1, filterable: true });
},
async test(assert) {
await this.subject.expand();
await this.subject.fillInFilter("ba");
assert.equal(
this.subject.displayedContent().length,
1,
"it returns only 1 result"
);
}
});
componentTest("valueAttribute (deprecated)", {
template: `
{{single-select
value=value
content=content
valueAttribute="value"
}}
`,
beforeEach() {
this.set("value", "normal");
const content = [
{ name: "Smaller", value: "smaller" },
{ name: "Normal", value: "normal" },
{ name: "Larger", value: "larger" },
{ name: "Largest", value: "largest" }
];
this.set("content", content);
},
async test(assert) {
await this.subject.expand();
assert.equal(this.subject.selectedRow().value(), this.value);
}
});
componentTest("none:string", {
template: template(['none="test.none"']),
beforeEach() {
I18n.translations[I18n.locale].js.test = { none: "(default)" };
setDefaultState(this, { value: 1 });
},
async test(assert) {
await this.subject.expand();
const noneRow = this.subject.rowByIndex(0);
assert.equal(noneRow.value(), null);
assert.equal(noneRow.name(), I18n.t("test.none"));
}
});
componentTest("none:object", {
template: template(["none=none"]),
beforeEach() {
setDefaultState(this, { none: { value: null, name: "(default)" } });
},
async test(assert) {
await this.subject.expand();
const noneRow = this.subject.rowByIndex(0);
assert.equal(noneRow.value(), null);
assert.equal(noneRow.name(), "(default)");
}
});
componentTest("content is a basic array", {
template: template(['none="test.none"']),
beforeEach() {
I18n.translations[I18n.locale].js.test = { none: "(default)" };
setDefaultState(this, {
nameProperty: null,
valueProperty: null,
value: "foo",
content: ["foo", "bar", "baz"]
});
},
async test(assert) {
await this.subject.expand();
const noneRow = this.subject.rowByIndex(0);
assert.equal(noneRow.value(), I18n.t("test.none"));
assert.equal(noneRow.name(), I18n.t("test.none"));
assert.equal(this.value, "foo");
await this.subject.selectRowByIndex(0);
assert.equal(this.value, null);
}
});
@@ -0,0 +1,78 @@
import componentTest from "helpers/component-test";
import { testSelectKitModule } from "./select-kit-test-helper";
import Site from "discourse/models/site";
testSelectKitModule("tag-drop", {
beforeEach() {
const site = Site.current();
Ember.set(site, "top_tags", ["jeff", "neil", "arpit", "régis"]);
const response = object => {
return [200, { "Content-Type": "application/json" }, object];
};
// prettier-ignore
server.get("/tags/filter/search", (params) => { //eslint-disable-line
if (params.queryParams.q === "rég") {
return response({
"results": [
{ "id": "régis", "text": "régis", "count": 2, "pm_count": 0 }
]
});
}else if (params.queryParams.q === "dav") {
return response({
"results": [
{ "id": "David", "text": "David", "count": 2, "pm_count": 0 }
]
});
}
});
}
});
function initTags(context) {
const categories = context.site.categoriesList;
const parentCategory = categories.findBy("id", 2);
const childCategories = categories.filter(
c => c.parentCategory === parentCategory
);
// top_tags
context.setProperties({
firstCategory: parentCategory,
secondCategory: childCategories.firstObject,
tagId: "jeff"
});
}
function template(options = []) {
return `
{{tag-drop
firstCategory=firstCategory
secondCategory=secondCategory
tagId=tagId
options=(hash
${options.join("\n")}
)
}}
`;
}
componentTest("default", {
template: template(["tagId=tagId"]),
beforeEach() {
initTags(this);
},
async test(assert) {
await this.subject.expand();
assert.ok(true);
// const row = this.subject.rowByValue(this.category.id);
// assert.ok(
// exists(row.el().find(".category-desc")),
// "it shows category description for newcomers"
// );
}
});
@@ -0,0 +1,74 @@
import selectKit from "helpers/select-kit-helper";
import componentTest from "helpers/component-test";
import Topic from "discourse/models/topic";
const buildTopic = function(level, archetype = "regular") {
return Topic.create({
id: 4563,
title: "Qunit Test Topic",
details: {
notification_level: level
},
archetype
});
};
const originalTranslation =
I18n.translations.en.js.topic.notifications.tracking_pm.title;
moduleForComponent("select-kit/topic-notifications-button", {
integration: true,
afterEach() {
I18n.translations.en.js.topic.notifications.tracking_pm.title = originalTranslation;
}
});
componentTest("the header has a localized title", {
template:
"{{topic-notifications-button notificationLevel=topic.details.notification_level topic=topic}}",
beforeEach() {
this.set("topic", buildTopic(1));
},
async test(assert) {
assert.equal(
selectKit()
.header()
.label(),
"Normal",
"it has the correct label"
);
await this.set("topic", buildTopic(2));
assert.equal(
selectKit()
.header()
.label(),
"Tracking",
"it correctly changes the label"
);
}
});
componentTest("the header has a localized title", {
template:
"{{topic-notifications-button notificationLevel=topic.details.notification_level topic=topic}}",
beforeEach() {
I18n.translations.en.js.topic.notifications.tracking_pm.title = `${originalTranslation} PM`;
this.set("topic", buildTopic(2, "private_message"));
},
test(assert) {
assert.equal(
selectKit()
.header()
.label(),
`${originalTranslation} PM`,
"it has the correct label for PMs"
);
}
});
@@ -0,0 +1,91 @@
import selectKit from "helpers/select-kit-helper";
import componentTest from "helpers/component-test";
import Topic from "discourse/models/topic";
const buildTopic = function(archetype) {
return Topic.create({
id: 4563,
title: "Qunit Test Topic",
details: {
notification_level: 1
},
archetype
});
};
function extractDescs(rows) {
return Array.from(
rows.find(".desc").map(function() {
return this.textContent.trim();
})
);
}
function getTranslations(type = "") {
return ["watching", "tracking", "regular", "muted"].map(key => {
return I18n.t(`topic.notifications.${key}${type}.description`);
});
}
moduleForComponent("select-kit/topic-notifications-options", {
integration: true
});
componentTest("regular topic notification level descriptions", {
template:
"{{topic-notifications-options value=topic.details.notification_level topic=topic}}",
beforeEach() {
this.set("topic", buildTopic("regular"));
},
async test(assert) {
await selectKit().expand();
const uiTexts = extractDescs(selectKit().rows());
const descriptions = getTranslations();
assert.equal(
uiTexts.length,
descriptions.length,
"it has the correct copy"
);
uiTexts.forEach((text, index) => {
assert.equal(
text.trim(),
descriptions[index].trim(),
"it has the correct copy"
);
});
}
});
componentTest("PM topic notification level descriptions", {
template:
"{{topic-notifications-options value=topic.details.notification_level topic=topic}}",
beforeEach() {
this.set("topic", buildTopic("private_message"));
},
async test(assert) {
await selectKit().expand();
const uiTexts = extractDescs(selectKit().rows());
const descriptions = getTranslations("_pm");
assert.equal(
uiTexts.length,
descriptions.length,
"it has the correct copy"
);
uiTexts.forEach((text, index) => {
assert.equal(
text.trim(),
descriptions[index].trim(),
"it has the correct copy"
);
});
}
});