discourse/test/javascripts/components/single-select-test.js.es6

913 lines
19 KiB
Plaintext
Raw Normal View History

2018-06-15 11:03:24 -04:00
import componentTest from "helpers/component-test";
import { withPluginApi } from "discourse/lib/plugin-api";
import { clearCallbacks } from "select-kit/mixins/plugin-api";
2018-06-15 11:03:24 -04:00
moduleForComponent("single-select", {
integration: true,
beforeEach: function() {
2018-06-15 11:03:24 -04:00
this.set("subject", selectKit());
}
});
2018-06-15 11:03:24 -04:00
componentTest("updating the content refreshes the list", {
template: "{{single-select value=1 content=content}}",
beforeEach() {
this.set("content", [{ id: 1, name: "BEFORE" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.rowByValue(1)
.name(),
"BEFORE"
);
2018-07-29 16:51:32 -04:00
await this.set("content", [{ id: 1, name: "AFTER" }]);
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.rowByValue(1)
.name(),
"AFTER"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("accepts a value by reference", {
template: "{{single-select value=value content=content}}",
beforeEach() {
this.set("value", 1);
this.set("content", [{ id: 1, name: "robin" }, { id: 2, name: "regis" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.selectedRow()
.name(),
"robin",
"it highlights the row corresponding to the value"
);
2018-07-29 16:51:32 -04:00
await this.get("subject").selectRowByValue(1);
2018-07-29 16:51:32 -04:00
assert.equal(this.get("value"), 1, "it mutates the value");
}
});
2018-06-15 11:03:24 -04:00
componentTest("no default icon", {
template: "{{single-select}}",
test(assert) {
assert.equal(
2018-06-15 11:03:24 -04:00
this.get("subject")
.header()
.icon().length,
0,
"it doesnt have an icon if not specified"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("default search icon", {
template: "{{single-select filterable=true}}",
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
assert.ok(
exists(
this.get("subject")
.filter()
.icon()
),
"it has an icon"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("with no search icon", {
template: "{{single-select filterable=true filterIcon=null}}",
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
assert.notOk(
exists(
this.get("subject")
.filter()
.icon()
),
"it has no icon"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("custom search icon", {
template: '{{single-select filterable=true filterIcon="shower"}}',
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.ok(
this.get("subject")
.filter()
.icon()
.hasClass("d-icon-shower"),
"it has a the correct icon"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("is expandable", {
template: "{{single-select}}",
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.ok(this.get("subject").isExpanded());
2018-07-29 16:51:32 -04:00
await this.get("subject").collapse();
2018-07-29 16:51:32 -04:00
assert.notOk(this.get("subject").isExpanded());
}
});
2018-06-15 11:03:24 -04:00
componentTest("accepts custom value/name keys", {
template:
'{{single-select value=value nameProperty="item" content=content valueAttribute="identifier"}}',
beforeEach() {
this.set("value", 1);
this.set("content", [{ identifier: 1, item: "robin" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.selectedRow()
.name(),
"robin"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("doesnt render collection content before first expand", {
template: "{{single-select value=1 content=content}}",
beforeEach() {
this.set("content", [{ value: 1, name: "robin" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
assert.notOk(exists(find(".select-kit-collection")));
2018-07-29 16:51:32 -04:00
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.ok(exists(find(".select-kit-collection")));
}
});
2018-06-15 11:03:24 -04:00
componentTest("dynamic headerText", {
template: "{{single-select value=1 content=content}}",
beforeEach() {
this.set("content", [{ id: 1, name: "robin" }, { id: 2, name: "regis" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.name(),
"robin"
);
2018-07-29 16:51:32 -04:00
await this.get("subject").selectRowByValue(2);
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.name(),
"regis",
"it changes header text"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("supports custom row template", {
template: "{{single-select content=content templateForRow=templateForRow}}",
beforeEach() {
this.set("content", [{ id: 1, name: "robin" }]);
this.set("templateForRow", rowComponent => {
return `<b>${rowComponent.get("computedContent.name")}</b>`;
});
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.rowByValue(1)
.el()
.html()
.trim(),
"<b>robin</b>"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("supports converting select value to integer", {
template: "{{single-select value=value content=content castInteger=true}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
this.set("value", 2);
this.set("content", [
{ id: "1", name: "robin" },
{ id: "2", name: "régis" }
]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.selectedRow()
.name(),
"régis"
2018-06-15 11:03:24 -04:00
);
2018-07-29 16:51:32 -04:00
await this.set("value", 1);
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.selectedRow()
.name(),
"robin",
"it works with dynamic content"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("supports converting string as boolean to boolean", {
template: "{{single-select value=value content=content castBoolean=true}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
this.set("value", true);
this.set("content", [
{ id: "true", name: "ASC" },
{ id: "false", name: "DESC" }
]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.selectedRow()
.name(),
"ASC"
2018-06-15 11:03:24 -04:00
);
2018-07-29 16:51:32 -04:00
await this.set("value", false);
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.selectedRow()
.name(),
"DESC",
"it works with dynamic content"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("supports keyboard events", {
template: "{{single-select content=content filterable=true}}",
beforeEach() {
this.set("content", [{ id: 1, name: "robin" }, { id: 2, name: "regis" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
await this.get("subject").keyboard("down");
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.highlightedRow()
.title(),
"regis",
"the next row is highlighted"
);
2018-07-29 16:51:32 -04:00
await this.get("subject").keyboard("down");
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.highlightedRow()
.title(),
"robin",
"it returns to the first row"
);
2018-07-29 16:51:32 -04:00
await this.get("subject").keyboard("up");
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.highlightedRow()
.title(),
"regis",
"it highlights the last row"
);
2018-07-29 16:51:32 -04:00
await this.get("subject").keyboard("enter");
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.selectedRow()
.title(),
"regis",
"it selects the row when pressing enter"
);
assert.notOk(
this.get("subject").isExpanded(),
"it collapses the select box when selecting a row"
);
2018-07-29 16:51:32 -04:00
await this.get("subject").expand();
await this.get("subject").keyboard("escape");
2018-07-29 16:51:32 -04:00
assert.notOk(
this.get("subject").isExpanded(),
"it collapses the select box"
);
2018-07-29 16:51:32 -04:00
await this.get("subject").expand();
await this.get("subject").fillInFilter("regis");
await this.get("subject").keyboard("tab");
assert.notOk(
this.get("subject").isExpanded(),
"it collapses the select box when selecting a row"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("with allowInitialValueMutation", {
template:
"{{single-select value=value content=content allowInitialValueMutation=true}}",
beforeEach() {
this.set("value", "");
2018-06-15 11:03:24 -04:00
this.set("content", [
{ id: "1", name: "robin" },
{ id: "2", name: "régis" }
]);
},
test(assert) {
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("value"),
"1",
"it mutates the value on initial rendering"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("support appending content through plugin api", {
template: "{{single-select content=content}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
withPluginApi("0.8.13", api => {
api
.modifySelectKit("select-kit")
.appendContent([{ id: "2", name: "regis" }]);
});
2018-06-15 11:03:24 -04:00
this.set("content", [{ id: "1", name: "robin" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(this.get("subject").rows().length, 2);
assert.equal(
this.get("subject")
.rowByIndex(1)
.name(),
"regis"
);
2018-07-29 16:51:32 -04:00
clearCallbacks();
}
});
2018-06-15 11:03:24 -04:00
componentTest("support modifying content through plugin api", {
template: "{{single-select content=content}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
withPluginApi("0.8.13", api => {
api
.modifySelectKit("select-kit")
.modifyContent((context, existingContent) => {
existingContent.splice(1, 0, { id: "2", name: "sam" });
return existingContent;
});
});
2018-06-15 11:03:24 -04:00
this.set("content", [
{ id: "1", name: "robin" },
{ id: "3", name: "regis" }
]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(this.get("subject").rows().length, 3);
assert.equal(
this.get("subject")
.rowByIndex(1)
.name(),
"sam"
);
2018-07-29 16:51:32 -04:00
clearCallbacks();
}
});
2018-06-15 11:03:24 -04:00
componentTest("support prepending content through plugin api", {
template: "{{single-select content=content}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
withPluginApi("0.8.13", api => {
api
.modifySelectKit("select-kit")
.prependContent([{ id: "2", name: "regis" }]);
});
2018-06-15 11:03:24 -04:00
this.set("content", [{ id: "1", name: "robin" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(this.get("subject").rows().length, 2);
assert.equal(
this.get("subject")
.rowByIndex(0)
.name(),
"regis"
);
2018-07-29 16:51:32 -04:00
clearCallbacks();
}
});
2018-06-15 11:03:24 -04:00
componentTest("support modifying on select behavior through plugin api", {
template:
'<span class="on-select-test"></span>{{single-select content=content}}',
beforeEach() {
2018-06-15 11:03:24 -04:00
withPluginApi("0.8.13", api => {
api.modifySelectKit("select-kit").onSelect((context, value) => {
find(".on-select-test").html(value);
});
});
2018-06-15 11:03:24 -04:00
this.set("content", [{ id: "1", name: "robin" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
await this.get("subject").selectRowByValue(1);
2018-07-29 16:51:32 -04:00
assert.equal(find(".on-select-test").html(), "1");
2018-07-29 16:51:32 -04:00
clearCallbacks();
}
});
componentTest("support modifying on select none behavior through plugin api", {
template:
'<span class="on-select-none-test"></span>{{single-select none="none" content=content}}',
beforeEach() {
withPluginApi("0.8.25", api => {
api.modifySelectKit("select-kit").onSelectNone(() => {
find(".on-select-none-test").html("NONE");
});
});
this.set("content", [{ id: "1", name: "robin" }]);
},
async test(assert) {
await this.get("subject").expand();
await this.get("subject").selectRowByValue(1);
await this.get("subject").expand();
await this.get("subject").selectNoneRow();
assert.equal(find(".on-select-none-test").html(), "NONE");
clearCallbacks();
}
});
2018-06-15 11:03:24 -04:00
componentTest("with nameChanges", {
template: "{{single-select content=content nameChanges=true}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
this.set("robin", { id: "1", name: "robin" });
this.set("content", [this.get("robin")]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.name(),
"robin"
);
2018-07-29 16:51:32 -04:00
await this.set("robin.name", "robin2");
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.name(),
"robin2"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("with null value", {
template: "{{single-select content=content}}",
beforeEach() {
this.set("content", [{ name: "robin" }]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.name(),
"robin"
);
assert.equal(
this.get("subject")
.header()
.value(),
undefined
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("with collection header", {
template: "{{single-select collectionHeader=collectionHeader}}",
beforeEach() {
this.set("collectionHeader", "<h2>Hello</h2>");
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.ok(exists(".collection-header h2"));
}
});
2018-06-15 11:03:24 -04:00
componentTest("with title", {
template: '{{single-select title=(i18n "test.title")}}',
beforeEach() {
2018-06-15 11:03:24 -04:00
I18n.translations[I18n.locale].js.test = { title: "My title" };
},
test(assert) {
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.title(),
"My title"
2018-06-15 11:03:24 -04:00
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("support modifying header computed content through plugin api", {
template: "{{single-select content=content}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
withPluginApi("0.8.15", api => {
api
.modifySelectKit("select-kit")
.modifyHeaderComputedContent((context, computedContent) => {
computedContent.title = "Not so evil";
return computedContent;
});
});
2018-06-15 11:03:24 -04:00
this.set("content", [{ id: "1", name: "robin" }]);
},
test(assert) {
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.title(),
"Not so evil"
);
2018-07-29 16:51:32 -04:00
clearCallbacks();
}
});
2018-01-11 03:54:39 -05:00
2018-06-15 11:03:24 -04:00
componentTest("with limitMatches", {
template: "{{single-select content=content limitMatches=2}}",
2018-01-11 03:54:39 -05:00
beforeEach() {
2018-06-15 11:03:24 -04:00
this.set("content", ["sam", "jeff", "neil"]);
2018-01-11 03:54:39 -05:00
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-01-11 03:54:39 -05:00
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.el()
.find(".select-kit-row").length,
2
2018-06-15 11:03:24 -04:00
);
2018-01-11 03:54:39 -05:00
}
});
2018-06-15 11:03:24 -04:00
componentTest("with minimum", {
template:
"{{single-select content=content minimum=1 allowAutoSelectFirst=false}}",
beforeEach() {
2018-06-15 11:03:24 -04:00
this.set("content", ["sam", "jeff", "neil"]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject").validationMessage(),
"Select at least 1 item."
2018-06-15 11:03:24 -04:00
);
2018-07-29 16:51:32 -04:00
await this.get("subject").selectRowByValue("sam");
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.label(),
"sam"
);
}
});
2018-06-15 11:03:24 -04:00
componentTest("with minimumLabel", {
template:
'{{single-select content=content minimum=1 minimumLabel="test.minimum" allowAutoSelectFirst=false}}',
beforeEach() {
2018-06-15 11:03:24 -04:00
I18n.translations[I18n.locale].js.test = { minimum: "min %{count}" };
this.set("content", ["sam", "jeff", "neil"]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
2018-07-29 16:51:32 -04:00
assert.equal(this.get("subject").validationMessage(), "min 1");
2018-07-29 16:51:32 -04:00
await this.get("subject").selectRowByValue("jeff");
2018-07-29 16:51:32 -04:00
assert.equal(
this.get("subject")
.header()
.label(),
"jeff"
);
}
});
componentTest("with accents in filter", {
template: "{{single-select content=content filterable=true}}",
beforeEach() {
this.set("content", ["sam", "jeff", "neil"]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
await this.get("subject").fillInFilter("jéff");
2018-07-29 16:51:32 -04:00
assert.equal(this.get("subject").rows().length, 1);
assert.equal(
this.get("subject")
.rowByIndex(0)
.name(),
"jeff"
);
}
});
componentTest("with accents in content", {
template: "{{single-select content=content filterable=true}}",
beforeEach() {
this.set("content", ["sam", "jéff", "neil"]);
},
2018-07-29 16:51:32 -04:00
async test(assert) {
await this.get("subject").expand();
await this.get("subject").fillInFilter("jeff");
2018-07-29 16:51:32 -04:00
assert.equal(this.get("subject").rows().length, 1);
assert.equal(
this.get("subject")
.rowByIndex(0)
.name(),
"jéff"
);
}
});
componentTest("with no content and allowAny", {
template: "{{single-select allowAny=true}}",
async test(assert) {
await click(
this.get("subject")
.header()
.el()
);
const $filter = this.get("subject")
.filter()
.el();
assert.ok($filter.hasClass("is-focused"));
assert.ok(!$filter.hasClass("is-hidden"));
}
});
componentTest("with forceEscape", {
template: "{{single-select content=content forceEscape=true}}",
beforeEach() {
this.set("content", ["<div>sam</div>"]);
},
async test(assert) {
await this.get("subject").expand();
const row = this.get("subject").rowByIndex(0);
assert.equal(
row
.el()
.find(".name")
.html()
.trim(),
"&lt;div&gt;sam&lt;/div&gt;"
);
assert.equal(
this.get("subject")
.header()
.el()
.find(".selected-name")
.html()
.trim(),
"&lt;div&gt;sam&lt;/div&gt;"
);
}
});
componentTest("without forceEscape", {
template: "{{single-select content=content forceEscape=false}}",
beforeEach() {
this.set("content", ["<div>sam</div>"]);
},
async test(assert) {
await this.get("subject").expand();
const row = this.get("subject").rowByIndex(0);
assert.equal(
row
.el()
.find(".name")
.html()
.trim(),
"<div>sam</div>"
);
assert.equal(
this.get("subject")
.header()
.el()
.find(".selected-name")
.html()
.trim(),
"<div>sam</div>"
);
}
});
componentTest("onSelect", {
template:
"<div class='test-external-action'></div>{{single-select content=content onSelect=(action externalAction)}}",
beforeEach() {
this.set("externalAction", actual => {
find(".test-external-action").text(actual);
});
this.set("content", ["red", "blue"]);
},
async test(assert) {
await this.get("subject").expand();
await this.get("subject").selectRowByValue("red");
assert.equal(
find(".test-external-action")
.text()
.trim(),
"red"
);
}
});
componentTest("onDeselect", {
template:
"<div class='test-external-action'></div>{{single-select content=content onDeselect=(action externalAction)}}",
beforeEach() {
this.set("externalAction", actual => {
find(".test-external-action").text(actual);
});
this.set("content", ["red", "blue"]);
},
async test(assert) {
await this.get("subject").expand();
await this.get("subject").selectRowByValue("red");
await this.get("subject").expand();
await this.get("subject").selectRowByValue("blue");
assert.equal(
find(".test-external-action")
.text()
.trim(),
"red"
);
}
});
componentTest("noopRow", {
template: "{{single-select value=value content=content}}",
beforeEach() {
this.set("value", "blue");
this.set("content", [
{ id: "red", name: "Red", __sk_row_type: "noopRow" },
"blue",
"green"
]);
},
async test(assert) {
await this.get("subject").expand();
await this.get("subject").selectRowByValue("red");
assert.equal(this.get("value"), "blue", "it doesnt change the value");
await this.get("subject").expand();
await this.get("subject").selectRowByValue("green");
assert.equal(this.get("value"), "green");
}
});