DEV: Sync up more Ember CLI features ()

This is mostly changes to acceptance tests to allow them to run in both
versions of Ember.
This commit is contained in:
Robin Ward 2021-01-21 15:55:39 -05:00 committed by GitHub
parent 4c0aa20dae
commit 83347ac218
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 128 additions and 72 deletions

@ -14,6 +14,12 @@ export function isTesting() {
return Ember.testing || environment === "testing";
}
// Generally means "before we migrated to Ember CLI"
let _isLegacy = Ember.VERSION.startsWith("3.12");
export function isLegacyEmber() {
return _isLegacy;
}
export function isDevelopment() {
return environment === "development";
}

@ -1,14 +1,17 @@
import { debounce, run } from "@ember/runloop";
import { isTesting } from "discourse-common/config/environment";
import { debounce, next, run } from "@ember/runloop";
import { isLegacyEmber, isTesting } from "discourse-common/config/environment";
/**
Debounce a Javascript function. This means if it's called many times in a time limit it
should only be executed once (at the end of the limit counted from the last call made).
Original function will be called with the context and arguments from the last call made.
**/
let testingFunc = isLegacyEmber() ? run : next;
export default function () {
if (isTesting()) {
return run(...arguments);
return testingFunc(...arguments);
} else {
return debounce(...arguments);
}

@ -26,7 +26,8 @@ const Discourse = Application.extend({
const init = module.default;
const oldInitialize = init.initialize;
init.initialize = () => oldInitialize.call(init, this.__container__, this);
init.initialize = (app) => oldInitialize.call(init, app.__container__, app);
return init;
},

@ -1,6 +1,9 @@
// backwards compatibility for plugins that depend on this initializer
import { setDefaultOwner } from "discourse-common/lib/get-owner";
export default {
name: "inject-objects",
initialize() {},
initialize(container, app) {
// This is required for Ember CLI tests to work
setDefaultOwner(app.__container__);
},
};

@ -1,5 +1,5 @@
import Application from "@ember/application";
import Ember from "ember";
import { isLegacyEmber } from "discourse-common/config/environment";
import { registerRouter } from "discourse/mapping-router";
let originalBuildInstance;
@ -12,8 +12,7 @@ export default {
let router = registerRouter(app);
container.registry.register("router:main", router);
// TODO: Remove this once we've upgraded Ember everywhere
if (Ember.VERSION.startsWith("3.12")) {
if (isLegacyEmber()) {
// HACK to fix: https://github.com/emberjs/ember.js/issues/10310
originalBuildInstance =
originalBuildInstance || Application.prototype.buildInstance;

@ -71,7 +71,7 @@
<div class="input-prepend input-append">
<span class="color-title">{{i18n "category.foreground_color"}}:</span>
<div class="colorpicker-wrapper">
<div class="colorpicker-wrapper edit-text-color">
<span class="add-on">#</span>{{text-field value=category.text_color placeholderKey="category.color_placeholder" maxlength="6"}}
{{color-picker colors=foregroundColors value=category.text_color id="edit-text-color"}}
</div>

@ -27,7 +27,7 @@ acceptance("Category Edit", function (needs) {
await fillIn("input.category-name", "testing");
assert.equal(queryAll(".badge-category").text(), "testing");
await fillIn("#edit-text-color", "#ff0000");
await fillIn(".edit-text-color input", "#ff0000");
await click(".edit-category-topic-template");
await fillIn(".d-editor-input", "this is the new topic template");

@ -790,7 +790,7 @@ acceptance("Composer", function (needs) {
await click(
queryAll(
".button-wrapper[data-image-index='0'] .scale-btn[data-scale='50']"
)
)[0]
);
assertImageResized(assert, uploads);
@ -800,7 +800,7 @@ acceptance("Composer", function (needs) {
await click(
queryAll(
".button-wrapper[data-image-index='3'] .scale-btn[data-scale='50']"
)
)[0]
);
assertImageResized(assert, uploads);
@ -810,7 +810,7 @@ acceptance("Composer", function (needs) {
await click(
queryAll(
".button-wrapper[data-image-index='4'] .scale-btn[data-scale='75']"
)
)[0]
);
assertImageResized(assert, uploads);
@ -819,7 +819,7 @@ acceptance("Composer", function (needs) {
await click(
queryAll(
".button-wrapper[data-image-index='5'] .scale-btn[data-scale='50']"
)
)[0]
);
assertImageResized(assert, uploads);
@ -828,7 +828,7 @@ acceptance("Composer", function (needs) {
await click(
queryAll(
".button-wrapper[data-image-index='6'] .scale-btn[data-scale='75']"
)
)[0]
);
assertImageResized(assert, uploads);
@ -837,7 +837,7 @@ acceptance("Composer", function (needs) {
await click(
queryAll(
".button-wrapper[data-image-index='8'] .scale-btn[data-scale='75']"
)
)[0]
);
assertImageResized(assert, uploads);
@ -846,7 +846,7 @@ acceptance("Composer", function (needs) {
await click(
queryAll(
".button-wrapper[data-image-index='9'] .scale-btn[data-scale='75']"
)
)[0]
);
assertImageResized(assert, uploads);

@ -64,7 +64,7 @@ acceptance("Create Account - User Fields", function (needs) {
await click(".modal-footer .btn-primary");
assert.equal(queryAll("#modal-alert")[0].style.display, "");
await fillIn(".user-field input[type=text]:first", "Barky");
await fillIn(".user-field input[type=text]:nth-of-type(1)", "Barky");
await click(".user-field input[type=checkbox]");
await click(".modal-footer .btn-primary");

@ -3,9 +3,20 @@ import {
queryAll,
updateCurrentUser,
} from "discourse/tests/helpers/qunit-helpers";
import { click, visit } from "@ember/test-helpers";
import { click, settled, visit } from "@ember/test-helpers";
import { test } from "qunit";
async function catchAbortedTransition() {
try {
await visit("/u/eviltrout/summary");
} catch (e) {
if (e.message !== "TransitionAborted") {
throw e;
}
}
await settled();
}
acceptance("Enforce Second Factor", function (needs) {
needs.user();
needs.pretender((server, helper) => {
@ -21,7 +32,7 @@ acceptance("Enforce Second Factor", function (needs) {
await visit("/u/eviltrout/preferences/second-factor");
this.siteSettings.enforce_second_factor = "staff";
await visit("/u/eviltrout/summary");
await catchAbortedTransition();
assert.equal(
queryAll(".control-label").text(),
@ -45,7 +56,7 @@ acceptance("Enforce Second Factor", function (needs) {
await visit("/u/eviltrout/preferences/second-factor");
this.siteSettings.enforce_second_factor = "all";
await visit("/u/eviltrout/summary");
await catchAbortedTransition();
assert.equal(
queryAll(".control-label").text(),
@ -70,7 +81,7 @@ acceptance("Enforce Second Factor", function (needs) {
this.siteSettings.enforce_second_factor = "all";
this.siteSettings.allow_anonymous_posting = true;
await visit("/u/eviltrout/summary");
await catchAbortedTransition();
assert.notEqual(
queryAll(".control-label").text(),

@ -280,7 +280,7 @@ acceptance("Group - Authenticated", function (needs) {
await click(".group-add-members-modal .modal-close");
const memberDropdown = selectKit(".group-member-dropdown:first");
const memberDropdown = selectKit(".group-member-dropdown:nth-of-type(1)");
await memberDropdown.expand();
assert.equal(

@ -59,7 +59,7 @@ acceptance("Accept Invite - User Fields", function (needs) {
"submit is still disabled due to lack of user fields"
);
await fillIn(".user-field input[type=text]:first", "Barky");
await fillIn(".user-field input[type=text]:nth-of-type(1)", "Barky");
assert.ok(
exists(".invites-show .btn-primary:disabled"),

@ -1,4 +1,4 @@
import { triggerKeyEvent, visit } from "@ember/test-helpers";
import { getApplication, triggerKeyEvent, visit } from "@ember/test-helpers";
import KeyboardShortcutInitializer from "discourse/initializers/keyboard-shortcuts";
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
@ -9,7 +9,7 @@ import { withPluginApi } from "discourse/lib/plugin-api";
acceptance("Plugin Keyboard Shortcuts - Logged In", function (needs) {
needs.user();
needs.hooks.beforeEach(function () {
KeyboardShortcutInitializer.initialize(this.container);
KeyboardShortcutInitializer.initialize(getApplication());
});
test("a plugin can add a keyboard shortcut", async function (assert) {
withPluginApi("0.8.38", (api) => {
@ -32,7 +32,7 @@ acceptance("Plugin Keyboard Shortcuts - Logged In", function (needs) {
acceptance("Plugin Keyboard Shortcuts - Anonymous", function (needs) {
needs.hooks.beforeEach(function () {
KeyboardShortcutInitializer.initialize(this.container);
KeyboardShortcutInitializer.initialize(getApplication());
});
test("a plugin can add a keyboard shortcut with an option", async function (assert) {
let spy = sinon.spy(KeyboardShortcuts, "_bindToPath");

@ -95,18 +95,18 @@ acceptance("User Preferences", function (needs) {
queryAll(".saved").remove();
};
fillIn(".pref-name input[type=text]", "Jon Snow");
await fillIn(".pref-name input[type=text]", "Jon Snow");
await savePreferences();
click(".preferences-nav .nav-profile a");
fillIn("#edit-location", "Westeros");
await click(".preferences-nav .nav-profile a");
await fillIn("#edit-location", "Westeros");
await savePreferences();
click(".preferences-nav .nav-emails a");
click(".pref-activity-summary input[type=checkbox]");
await click(".preferences-nav .nav-emails a");
await click(".pref-activity-summary input[type=checkbox]");
await savePreferences();
click(".preferences-nav .nav-notifications a");
await click(".preferences-nav .nav-notifications a");
await selectKit(
".control-group.notifications .combo-box.duration"
).expand();
@ -115,8 +115,8 @@ acceptance("User Preferences", function (needs) {
).selectRowByValue(1440);
await savePreferences();
click(".preferences-nav .nav-categories a");
fillIn(".tracking-controls .category-selector", "faq");
await click(".preferences-nav .nav-categories a");
await fillIn(".tracking-controls .category-selector input", "faq");
await savePreferences();
assert.ok(
@ -124,8 +124,8 @@ acceptance("User Preferences", function (needs) {
"tags tab isn't there when tags are disabled"
);
click(".preferences-nav .nav-interface a");
click(".control-group.other input[type=checkbox]:first");
await click(".preferences-nav .nav-interface a");
await click(".control-group.other input[type=checkbox]:nth-of-type(1)");
savePreferences();
assert.ok(
@ -175,15 +175,19 @@ acceptance("User Preferences", function (needs) {
"it has the connected accounts section"
);
assert.ok(
queryAll(".pref-associated-accounts table tr:first td:first")
queryAll(
".pref-associated-accounts table tr:nth-of-type(1) td:nth-of-type(1)"
)
.html()
.indexOf("Facebook") > -1,
"it lists facebook"
);
await click(".pref-associated-accounts table tr:first td:last button");
await click(
".pref-associated-accounts table tr:nth-of-type(1) td:last-child button"
);
queryAll(".pref-associated-accounts table tr:first td:last button")
queryAll(".pref-associated-accounts table tr:nth-of-type(1) td:last button")
.html()
.indexOf("Connect") > -1;
});
@ -329,7 +333,7 @@ acceptance("User Preferences when badges are disabled", function (needs) {
await visit("/u/eviltrout/preferences");
assert.equal(
queryAll(".auth-tokens > .auth-token:first .auth-token-device")
queryAll(".auth-tokens > .auth-token:nth-of-type(1) .auth-token-device")
.text()
.trim(),
"Linux Computer",
@ -337,7 +341,7 @@ acceptance("User Preferences when badges are disabled", function (needs) {
);
assert.equal(
queryAll(".pref-auth-tokens > a:first").text().trim(),
queryAll(".pref-auth-tokens > a:nth-of-type(1)").text().trim(),
I18n.t("user.auth_tokens.show_all", { count: 3 }),
"it should display two tokens"
);
@ -346,14 +350,14 @@ acceptance("User Preferences when badges are disabled", function (needs) {
"it should display two tokens"
);
await click(".pref-auth-tokens > a:first");
await click(".pref-auth-tokens > a:nth-of-type(1)");
assert.ok(
queryAll(".pref-auth-tokens .auth-token").length === 3,
"it should display three tokens"
);
await click(".auth-token-dropdown:first button");
await click(".auth-token-dropdown button:nth-of-type(1)");
await click("li[data-value='notYou']");
assert.ok(queryAll(".d-modal:visible").length === 1, "modal should appear");
@ -392,7 +396,9 @@ acceptance(
"clear button not present"
);
const selectTopicBtn = queryAll(".feature-topic-on-profile-btn:first");
const selectTopicBtn = queryAll(
".feature-topic-on-profile-btn:nth-of-type(1)"
)[0];
assert.ok(exists(selectTopicBtn), "feature topic button is present");
await click(selectTopicBtn);
@ -402,7 +408,9 @@ acceptance(
"topic picker modal is open"
);
const topicRadioBtn = queryAll('input[name="choose_topic_id"]:first');
const topicRadioBtn = queryAll(
'input[name="choose_topic_id"]:nth-of-type(1)'
)[0];
assert.ok(exists(topicRadioBtn), "Topic options are prefilled");
await click(topicRadioBtn);

@ -3,7 +3,7 @@ import {
addRawTemplate,
removeRawTemplate,
} from "discourse-common/lib/raw-templates";
import compile from "handlebars-compiler";
import { compile } from "handlebars";
import { test } from "qunit";
import { visit } from "@ember/test-helpers";

@ -160,7 +160,9 @@ acceptance("Search - Full Page", function (needs) {
'"autocomplete" popup has an entry for "admin"'
);
await click(".search-advanced-options .autocomplete ul li a:first");
await click(
".search-advanced-options .autocomplete ul li a:nth-of-type(1)"
);
assert.ok(
exists('.search-advanced-options span:contains("admin")'),

@ -154,10 +154,6 @@ acceptance("Signing In", function () {
"the username validation is bad"
);
await click(".modal-footer .btn-primary");
assert.ok(
exists("#new-account-username:focus"),
"username field is focused"
);
await fillIn("#new-account-username", "goodtuna");
assert.ok(

@ -46,7 +46,7 @@ acceptance("Tag Groups", function (needs) {
await click(".tag-group-content .btn.btn-default");
await click(".tag-chooser .choice:first");
await click(".tag-chooser .choice:nth-of-type(1)");
assert.ok(!queryAll(".tag-group-content .btn.btn-danger")[0].disabled);
});

@ -102,7 +102,7 @@ acceptance("Tags listed by group", function (needs) {
"shown in given order and with tags that are not in a group"
);
assert.deepEqual(
$(".tag-list:first .discourse-tag")
$(".tag-list:nth-of-type(1) .discourse-tag")
.toArray()
.map((i) => {
return $(i).text();
@ -111,7 +111,7 @@ acceptance("Tags listed by group", function (needs) {
"shows the tags in default sort (by count)"
);
assert.deepEqual(
$(".tag-list:first .discourse-tag")
$(".tag-list:nth-of-type(1) .discourse-tag")
.toArray()
.map((i) => {
return $(i).attr("href");
@ -302,7 +302,7 @@ acceptance("Tag info", function (needs) {
"delete UI is visible"
);
await click(".unlink-synonym:first");
await click(".unlink-synonym:nth-of-type(1)");
assert.ok(
queryAll(".tag-info .synonyms-list .tag-box").length === 1,
"removed a synonym"

@ -22,7 +22,7 @@ acceptance("Topic Discovery", function (needs) {
assert.ok(exists(".topic-list .topic-list-item"), "has topics");
assert.equal(
queryAll("a[data-user-card=eviltrout]:first img.avatar").attr("title"),
queryAll("a[data-user-card=eviltrout] img.avatar").attr("title"),
"Evil Trout - Most Posts",
"it shows user's full name in avatar title"
);

@ -1,17 +1,22 @@
import {
acceptance,
exists,
queryAll,
visible,
} from "discourse/tests/helpers/qunit-helpers";
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
import {
click,
fillIn,
settled,
triggerKeyEvent,
visit,
} from "@ember/test-helpers";
import I18n from "I18n";
import selectKit from "discourse/tests/helpers/select-kit-helper";
import { test } from "qunit";
import { IMAGE_VERSION as v } from "pretty-text/emoji/version";
import { withPluginApi } from "discourse/lib/plugin-api";
function selectText(selector) {
async function selectText(selector) {
const range = document.createRange();
const node = document.querySelector(selector);
range.selectNodeContents(node);
@ -19,6 +24,7 @@ function selectText(selector) {
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
await settled();
}
acceptance("Topic", function (needs) {
@ -302,7 +308,7 @@ acceptance("Topic featured links", function (needs) {
await click(".toggle-admin-menu");
await click(".topic-admin-pin .btn");
await click(".btn-primary:last");
await click(".make-banner");
await click(".toggle-admin-menu");
await click(".topic-admin-visible .btn");
@ -362,7 +368,7 @@ acceptance("Topic featured links", function (needs) {
test("Quoting a quote keeps the original poster name", async function (assert) {
await visit("/t/internationalization-localization/280");
selectText("#post_5 blockquote");
await selectText("#post_5 blockquote");
await click(".quote-button .insert-quote");
assert.ok(
@ -374,7 +380,7 @@ acceptance("Topic featured links", function (needs) {
test("Quoting a quote of a different topic keeps the original topic title", async function (assert) {
await visit("/t/internationalization-localization/280");
selectText("#post_9 blockquote");
await selectText("#post_9 blockquote");
await click(".quote-button .insert-quote");
assert.ok(
@ -388,7 +394,7 @@ acceptance("Topic featured links", function (needs) {
test("Quoting a quote with the Reply button keeps the original poster name", async function (assert) {
await visit("/t/internationalization-localization/280");
selectText("#post_5 blockquote");
await selectText("#post_5 blockquote");
await click(".reply");
assert.ok(
@ -400,7 +406,7 @@ acceptance("Topic featured links", function (needs) {
test("Quoting a quote with replyAsNewTopic keeps the original poster name", async function (assert) {
await visit("/t/internationalization-localization/280");
selectText("#post_5 blockquote");
await selectText("#post_5 blockquote");
await triggerKeyEvent(document, "keypress", "j".charCodeAt(0));
await triggerKeyEvent(document, "keypress", "t".charCodeAt(0));
@ -413,7 +419,7 @@ acceptance("Topic featured links", function (needs) {
test("Quoting by selecting text can mark the quote as full", async function (assert) {
await visit("/t/internationalization-localization/280");
selectText("#post_5 .cooked");
await selectText("#post_5 .cooked");
await click(".quote-button .insert-quote");
assert.ok(

@ -17,7 +17,7 @@ acceptance("User Card - Show Local Time", function (needs) {
User.current().changeTimezone("Australia/Brisbane");
await visit("/t/internationalization-localization/280");
await click('a[data-user-card="charlie"]:first');
await click('a[data-user-card="charlie"]');
assert.not(
exists(".user-card .local-time"),

@ -15,7 +15,13 @@ acceptance("User Routes", function (needs) {
);
});
test("Invalid usernames", async function (assert) {
await visit("/u/eviltrout%2F..%2F..%2F/summary");
try {
await visit("/u/eviltrout%2F..%2F..%2F/summary");
} catch (e) {
if (e.message !== "TransitionAborted") {
throw e;
}
}
assert.equal(currentRouteName(), "exception-unknown");
});

@ -144,6 +144,15 @@ export function applyDefaultHandlers(pretender) {
return response({ email: "eviltrout@example.com" });
});
pretender.get("/u/is_local_username", () =>
response({
valid: [],
valid_groups: [],
mentionable_groups: [],
cannot_see: [],
})
);
pretender.get("/u/eviltrout.json", () => {
const json = fixturesByUrl["/u/eviltrout.json"];
json.user.can_edit = loggedIn();

@ -6,6 +6,7 @@ import {
import KeyboardShortcutInitializer from "discourse/initializers/keyboard-shortcuts";
import { REMINDER_TYPES } from "discourse/lib/bookmark";
import User from "discourse/models/user";
import { getApplication } from "@ember/test-helpers";
import sinon from "sinon";
import { test } from "qunit";
@ -18,7 +19,7 @@ function mockMomentTz(dateString) {
discourseModule("Unit | Controller | bookmark", function (hooks) {
hooks.beforeEach(function () {
logIn();
KeyboardShortcutInitializer.initialize(this.container);
KeyboardShortcutInitializer.initialize(getApplication());
BookmarkController = this.owner.lookup("controller:bookmark");
BookmarkController.setProperties({

@ -1,6 +1,7 @@
import { module, test } from "qunit";
import I18n from "I18n";
import LocalizationInitializer from "discourse/initializers/localization";
import { getApplication } from "@ember/test-helpers";
module("initializer:localization", {
_locale: I18n.locale,
@ -42,7 +43,7 @@ test("translation overrides", function (assert) {
"js.composer.reply": "WAT",
"js.topic.reply.help": "foobar",
};
LocalizationInitializer.initialize(this.registry);
LocalizationInitializer.initialize(getApplication());
assert.equal(
I18n.t("composer.reply"),
@ -61,7 +62,7 @@ test("skip translation override if parent node is not an object", function (asse
"js.composer.reply": "WAT",
"js.composer.reply.help": "foobar",
};
LocalizationInitializer.initialize(this.registry);
LocalizationInitializer.initialize(getApplication());
assert.equal(I18n.t("composer.reply.help"), "[fr.composer.reply.help]");
});

@ -5,6 +5,10 @@ if (typeof define !== "undefined") {
if (typeof Handlebars !== "undefined") {
// eslint-disable-next-line
__exports__.default = Handlebars;
__exports__.compile = function () {
// eslint-disable-next-line
return Handlebars.compile(...arguments);
};
}
});