diff --git a/app/assets/javascripts/discourse-common/addon/config/environment.js b/app/assets/javascripts/discourse-common/addon/config/environment.js index 409b6af0663..d2a47b12478 100644 --- a/app/assets/javascripts/discourse-common/addon/config/environment.js +++ b/app/assets/javascripts/discourse-common/addon/config/environment.js @@ -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"; } diff --git a/app/assets/javascripts/discourse-common/addon/lib/debounce.js b/app/assets/javascripts/discourse-common/addon/lib/debounce.js index 541498fda63..5e30864574f 100644 --- a/app/assets/javascripts/discourse-common/addon/lib/debounce.js +++ b/app/assets/javascripts/discourse-common/addon/lib/debounce.js @@ -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); } diff --git a/app/assets/javascripts/discourse/app/app.js b/app/assets/javascripts/discourse/app/app.js index 093dfe5eea4..b28effdddb4 100644 --- a/app/assets/javascripts/discourse/app/app.js +++ b/app/assets/javascripts/discourse/app/app.js @@ -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; }, diff --git a/app/assets/javascripts/discourse/app/initializers/inject-objects.js b/app/assets/javascripts/discourse/app/initializers/inject-objects.js index abcf14a574c..533e9134af9 100644 --- a/app/assets/javascripts/discourse/app/initializers/inject-objects.js +++ b/app/assets/javascripts/discourse/app/initializers/inject-objects.js @@ -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__); + }, }; diff --git a/app/assets/javascripts/discourse/app/pre-initializers/map-routes.js b/app/assets/javascripts/discourse/app/pre-initializers/map-routes.js index 8c4b69dd0f6..d064dd3b325 100644 --- a/app/assets/javascripts/discourse/app/pre-initializers/map-routes.js +++ b/app/assets/javascripts/discourse/app/pre-initializers/map-routes.js @@ -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; diff --git a/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs b/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs index 353f1be1302..60f5047be7a 100644 --- a/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs +++ b/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs @@ -71,7 +71,7 @@
{{i18n "category.foreground_color"}}: -
+
#{{text-field value=category.text_color placeholderKey="category.color_placeholder" maxlength="6"}} {{color-picker colors=foregroundColors value=category.text_color id="edit-text-color"}}
diff --git a/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js b/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js index 3df14fd12eb..7393d1dbb59 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/category-edit-test.js @@ -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"); diff --git a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js index 1cec7ceb8c6..1514688695f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/composer-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/composer-test.js @@ -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); diff --git a/app/assets/javascripts/discourse/tests/acceptance/create-account-user-fields-test.js b/app/assets/javascripts/discourse/tests/acceptance/create-account-user-fields-test.js index 9bbefe93133..c85cb272c5c 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/create-account-user-fields-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/create-account-user-fields-test.js @@ -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"); diff --git a/app/assets/javascripts/discourse/tests/acceptance/enforce-second-factor-test.js b/app/assets/javascripts/discourse/tests/acceptance/enforce-second-factor-test.js index eaf9ca48960..86ce29be17f 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/enforce-second-factor-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/enforce-second-factor-test.js @@ -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(), diff --git a/app/assets/javascripts/discourse/tests/acceptance/group-test.js b/app/assets/javascripts/discourse/tests/acceptance/group-test.js index 2e92868be17..6fba32ebd5b 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/group-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/group-test.js @@ -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( diff --git a/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js b/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js index a03c92e3a4b..814e7277563 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/invite-show-user-fields-test.js @@ -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"), diff --git a/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js b/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js index 4a517fae5b2..42bacdd5f24 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/plugin-keyboard-shortcut-test.js @@ -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"); diff --git a/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js b/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js index e22cfa10002..c95e9559914 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js @@ -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); diff --git a/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js b/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js index 13a2f52e1e5..24d8055fb7e 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/raw-plugin-outlet-test.js @@ -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"; diff --git a/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js b/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js index de8eaab54db..e4cfa4745fd 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/search-full-test.js @@ -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")'), diff --git a/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js b/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js index 62df079754f..9b6136663aa 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/sign-in-test.js @@ -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( diff --git a/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js b/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js index c3ab9d85d8e..6d8de06da14 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/tag-groups-test.js @@ -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); }); diff --git a/app/assets/javascripts/discourse/tests/acceptance/tags-test.js b/app/assets/javascripts/discourse/tests/acceptance/tags-test.js index a3d339afece..31b22fc6536 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/tags-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/tags-test.js @@ -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" diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js index 627da729122..f71e25020d7 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-discovery-test.js @@ -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" ); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-test.js index 351d39e5738..845d58e45d7 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-test.js @@ -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( diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js index 3dff64d71db..2e9281f368d 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-card-test.js @@ -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"), diff --git a/app/assets/javascripts/discourse/tests/acceptance/user-test.js b/app/assets/javascripts/discourse/tests/acceptance/user-test.js index 2c747253a65..ae7603bf4dd 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/user-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/user-test.js @@ -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"); }); diff --git a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js index b75d641d33e..80997d6f075 100644 --- a/app/assets/javascripts/discourse/tests/helpers/create-pretender.js +++ b/app/assets/javascripts/discourse/tests/helpers/create-pretender.js @@ -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(); diff --git a/app/assets/javascripts/discourse/tests/unit/controllers/bookmark-test.js b/app/assets/javascripts/discourse/tests/unit/controllers/bookmark-test.js index ca8a6b18569..e67342fbb4c 100644 --- a/app/assets/javascripts/discourse/tests/unit/controllers/bookmark-test.js +++ b/app/assets/javascripts/discourse/tests/unit/controllers/bookmark-test.js @@ -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({ diff --git a/app/assets/javascripts/discourse/tests/unit/localization-test.js b/app/assets/javascripts/discourse/tests/unit/localization-test.js index 4939746aed6..f2bf2f3c0f6 100644 --- a/app/assets/javascripts/discourse/tests/unit/localization-test.js +++ b/app/assets/javascripts/discourse/tests/unit/localization-test.js @@ -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]"); }); diff --git a/app/assets/javascripts/handlebars-shim.js b/app/assets/javascripts/handlebars-shim.js index fb191149a1e..d73b33ce451 100644 --- a/app/assets/javascripts/handlebars-shim.js +++ b/app/assets/javascripts/handlebars-shim.js @@ -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); + }; } });