DEV: Introduce default 'auto' mode for glimmer header (#26467)
This will automatically enable the glimmer header when all installed themes/plugins are ready. This replaces the old group-based site setting. In 'auto' mode, we check for calls to deprecated APIs (e.g. decorateWidget) which affect the old header. If any are present, we stick to the old header implementation and print a message to the console alongside the normal deprecation messages. To override this automatic behavior, a new `glimmer_header_mode` site setting can be set to 'disabled' or 'enabled'. This change also means that our test suite is running with the glimmer header. This unveiled a couple of small issues (e.g. some incorrect `aria-*` and `alt` text) which are now fixed. A number of selectors had to be updated to ensure the tests were clicking the actual `<button>` elements rather than the surrounding `<li>` elements.
This commit is contained in:
parent
5d0471ebe4
commit
3733db866c
|
@ -22,7 +22,10 @@ export default class Contents extends Component {
|
||||||
<div class="contents">
|
<div class="contents">
|
||||||
{{#if this.site.desktopView}}
|
{{#if this.site.desktopView}}
|
||||||
{{#if @sidebarEnabled}}
|
{{#if @sidebarEnabled}}
|
||||||
<SidebarToggle @toggleHamburger={{@toggleHamburger}} />
|
<SidebarToggle
|
||||||
|
@toggleHamburger={{@toggleHamburger}}
|
||||||
|
@showSidebar={{@showSidebar}}
|
||||||
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Component from "@glimmer/component";
|
||||||
import { hash } from "@ember/helper";
|
import { hash } from "@ember/helper";
|
||||||
import { on } from "@ember/modifier";
|
import { on } from "@ember/modifier";
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
|
import { waitForPromise } from "@ember/test-waiters";
|
||||||
import { isDocumentRTL } from "discourse/lib/text-direction";
|
import { isDocumentRTL } from "discourse/lib/text-direction";
|
||||||
import { prefersReducedMotion } from "discourse/lib/utilities";
|
import { prefersReducedMotion } from "discourse/lib/utilities";
|
||||||
import { isTesting } from "discourse-common/config/environment";
|
import { isTesting } from "discourse-common/config/environment";
|
||||||
|
@ -9,14 +10,13 @@ import discourseLater from "discourse-common/lib/later";
|
||||||
import closeOnClickOutside from "../../modifiers/close-on-click-outside";
|
import closeOnClickOutside from "../../modifiers/close-on-click-outside";
|
||||||
import HamburgerDropdown from "../sidebar/hamburger-dropdown";
|
import HamburgerDropdown from "../sidebar/hamburger-dropdown";
|
||||||
|
|
||||||
|
const CLOSE_ON_CLICK_SELECTORS =
|
||||||
|
"a[href], .sidebar-section-header-button, .sidebar-section-link-button, .sidebar-section-link";
|
||||||
|
|
||||||
export default class HamburgerDropdownWrapper extends Component {
|
export default class HamburgerDropdownWrapper extends Component {
|
||||||
@action
|
@action
|
||||||
click(e) {
|
click(e) {
|
||||||
if (
|
if (e.target.closest(CLOSE_ON_CLICK_SELECTORS)) {
|
||||||
e.target.closest(
|
|
||||||
".sidebar-section-header-button, .sidebar-section-link-button, .sidebar-section-link"
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.args.toggleHamburger();
|
this.args.toggleHamburger();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,9 @@ export default class HamburgerDropdownWrapper extends Component {
|
||||||
const panel = document.querySelector(".menu-panel");
|
const panel = document.querySelector(".menu-panel");
|
||||||
const headerCloak = document.querySelector(".header-cloak");
|
const headerCloak = document.querySelector(".header-cloak");
|
||||||
const finishPosition = isDocumentRTL() ? "340px" : "-340px";
|
const finishPosition = isDocumentRTL() ? "340px" : "-340px";
|
||||||
panel
|
const panelAnimatePromise = panel
|
||||||
.animate([{ transform: `translate3d(${finishPosition}, 0, 0)` }], {
|
.animate([{ transform: `translate3d(${finishPosition}, 0, 0)` }], {
|
||||||
duration: 200,
|
duration: isTesting() ? 0 : 200,
|
||||||
fill: "forwards",
|
fill: "forwards",
|
||||||
easing: "ease-in",
|
easing: "ease-in",
|
||||||
})
|
})
|
||||||
|
@ -43,11 +43,13 @@ export default class HamburgerDropdownWrapper extends Component {
|
||||||
discourseLater(() => this.args.toggleHamburger());
|
discourseLater(() => this.args.toggleHamburger());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
headerCloak.animate([{ opacity: 0 }], {
|
const cloakAnimatePromise = headerCloak.animate([{ opacity: 0 }], {
|
||||||
duration: 200,
|
duration: isTesting() ? 0 : 200,
|
||||||
fill: "forwards",
|
fill: "forwards",
|
||||||
easing: "ease-in",
|
easing: "ease-in",
|
||||||
});
|
}).finished;
|
||||||
|
waitForPromise(panelAnimatePromise);
|
||||||
|
waitForPromise(cloakAnimatePromise);
|
||||||
} else {
|
} else {
|
||||||
this.args.toggleHamburger();
|
this.args.toggleHamburger();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { hash } from "@ember/helper";
|
import { concat } from "@ember/helper";
|
||||||
import emoji from "discourse/helpers/emoji";
|
import emoji from "discourse/helpers/emoji";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ const UserStatusBubble = <template>
|
||||||
<div class="user-status-background">
|
<div class="user-status-background">
|
||||||
{{emoji
|
{{emoji
|
||||||
@status.emoji
|
@status.emoji
|
||||||
(hash title=(title @status.description @status.ends_at @timezone))
|
title=(title @status.description @status.ends_at @timezone)
|
||||||
|
alt=(concat ":" @status.emoji ":")
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</template>;
|
</template>;
|
||||||
|
|
|
@ -13,6 +13,7 @@ export default Controller.extend({
|
||||||
showTop: true,
|
showTop: true,
|
||||||
router: service(),
|
router: service(),
|
||||||
footer: service(),
|
footer: service(),
|
||||||
|
header: service(),
|
||||||
sidebarState: service(),
|
sidebarState: service(),
|
||||||
showSidebar: false,
|
showSidebar: false,
|
||||||
sidebarDisabledRouteOverride: false,
|
sidebarDisabledRouteOverride: false,
|
||||||
|
|
|
@ -24,6 +24,7 @@ export default {
|
||||||
applicationController.calculateShowSidebar()
|
applicationController.calculateShowSidebar()
|
||||||
);
|
);
|
||||||
applicationController.appEvents.trigger("site-header:force-refresh");
|
applicationController.appEvents.trigger("site-header:force-refresh");
|
||||||
|
owner.lookup("service:header").hamburgerVisible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -203,19 +203,6 @@ function wrapWithErrorHandler(func, messageKey) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function deprecatedHeaderWidgetOverride(widgetName, override) {
|
|
||||||
if (DEPRECATED_HEADER_WIDGETS.includes(widgetName)) {
|
|
||||||
deprecated(
|
|
||||||
`The ${widgetName} widget has been deprecated and ${override} is no longer a supported override.`,
|
|
||||||
{
|
|
||||||
since: "v3.3.0.beta1-dev",
|
|
||||||
id: "discourse.header-widget-overrides",
|
|
||||||
url: "https://meta.discourse.org/t/296544",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PluginApi {
|
class PluginApi {
|
||||||
constructor(version, container) {
|
constructor(version, container) {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
|
@ -560,7 +547,7 @@ class PluginApi {
|
||||||
**/
|
**/
|
||||||
decorateWidget(name, fn) {
|
decorateWidget(name, fn) {
|
||||||
const widgetName = name.split(":")[0];
|
const widgetName = name.split(":")[0];
|
||||||
deprecatedHeaderWidgetOverride(widgetName, "decorateWidget");
|
this.#deprecatedHeaderWidgetOverride(widgetName, "decorateWidget");
|
||||||
|
|
||||||
decorateWidget(name, fn);
|
decorateWidget(name, fn);
|
||||||
}
|
}
|
||||||
|
@ -591,7 +578,7 @@ class PluginApi {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecatedHeaderWidgetOverride(widget, "attachWidgetAction");
|
this.#deprecatedHeaderWidgetOverride(widget, "attachWidgetAction");
|
||||||
|
|
||||||
widgetClass.prototype[actionName] = fn;
|
widgetClass.prototype[actionName] = fn;
|
||||||
}
|
}
|
||||||
|
@ -910,7 +897,7 @@ class PluginApi {
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
changeWidgetSetting(widgetName, settingName, newValue) {
|
changeWidgetSetting(widgetName, settingName, newValue) {
|
||||||
deprecatedHeaderWidgetOverride(widgetName, "changeWidgetSetting");
|
this.#deprecatedHeaderWidgetOverride(widgetName, "changeWidgetSetting");
|
||||||
changeSetting(widgetName, settingName, newValue);
|
changeSetting(widgetName, settingName, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,7 +931,7 @@ class PluginApi {
|
||||||
**/
|
**/
|
||||||
|
|
||||||
reopenWidget(name, args) {
|
reopenWidget(name, args) {
|
||||||
deprecatedHeaderWidgetOverride(name, "reopenWidget");
|
this.#deprecatedHeaderWidgetOverride(name, "reopenWidget");
|
||||||
return reopenWidget(name, args);
|
return reopenWidget(name, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,6 +966,7 @@ class PluginApi {
|
||||||
url: "https://meta.discourse.org/t/296544",
|
url: "https://meta.discourse.org/t/296544",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
this.container.lookup("service:header").anyWidgetHeaderOverrides = true;
|
||||||
attachAdditionalPanel(name, toggle, transformAttrs);
|
attachAdditionalPanel(name, toggle, transformAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2952,6 +2940,20 @@ class PluginApi {
|
||||||
|
|
||||||
registerAdminPluginConfigNav(pluginId, mode, links);
|
registerAdminPluginConfigNav(pluginId, mode, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#deprecatedHeaderWidgetOverride(widgetName, override) {
|
||||||
|
if (DEPRECATED_HEADER_WIDGETS.includes(widgetName)) {
|
||||||
|
this.container.lookup("service:header").anyWidgetHeaderOverrides = true;
|
||||||
|
deprecated(
|
||||||
|
`The ${widgetName} widget has been deprecated and ${override} is no longer a supported override.`,
|
||||||
|
{
|
||||||
|
since: "v3.3.0.beta1-dev",
|
||||||
|
id: "discourse.header-widget-overrides",
|
||||||
|
url: "https://meta.discourse.org/t/296544",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// from http://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number
|
// from http://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number
|
||||||
|
|
|
@ -26,7 +26,7 @@ export default class CloseOnClickOutside extends Modifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
document.querySelector(this.targetSelector).contains(event.target) ||
|
document.querySelector(this.targetSelector)?.contains(event.target) ||
|
||||||
(this.secondaryTargetSelector &&
|
(this.secondaryTargetSelector &&
|
||||||
document
|
document
|
||||||
.querySelector(this.secondaryTargetSelector)
|
.querySelector(this.secondaryTargetSelector)
|
||||||
|
|
|
@ -1,10 +1,32 @@
|
||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
import Service from "@ember/service";
|
import Service, { service } from "@ember/service";
|
||||||
import { disableImplicitInjections } from "discourse/lib/implicit-injections";
|
import { disableImplicitInjections } from "discourse/lib/implicit-injections";
|
||||||
|
|
||||||
@disableImplicitInjections
|
@disableImplicitInjections
|
||||||
export default class Header extends Service {
|
export default class Header extends Service {
|
||||||
|
@service siteSettings;
|
||||||
|
|
||||||
@tracked topic = null;
|
@tracked topic = null;
|
||||||
@tracked hamburgerVisible = false;
|
@tracked hamburgerVisible = false;
|
||||||
@tracked userVisible = false;
|
@tracked userVisible = false;
|
||||||
|
@tracked anyWidgetHeaderOverrides = false;
|
||||||
|
|
||||||
|
get useGlimmerHeader() {
|
||||||
|
if (this.siteSettings.glimmer_header_mode === "disabled") {
|
||||||
|
return false;
|
||||||
|
} else if (this.siteSettings.glimmer_header_mode === "enabled") {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// Auto
|
||||||
|
if (this.anyWidgetHeaderOverrides) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
"Using legacy 'widget' header because themes and/or plugins are using deprecated APIs. https://meta.discourse.org/t/296544"
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{{#if this.showSiteHeader}}
|
{{#if this.showSiteHeader}}
|
||||||
{{#if this.currentUser.glimmer_header_enabled}}
|
{{#if this.header.useGlimmerHeader}}
|
||||||
<GlimmerSiteHeader
|
<GlimmerSiteHeader
|
||||||
@canSignUp={{this.canSignUp}}
|
@canSignUp={{this.canSignUp}}
|
||||||
@showCreateAccount={{route-action "showCreateAccount"}}
|
@showCreateAccount={{route-action "showCreateAccount"}}
|
||||||
|
|
|
@ -27,7 +27,7 @@ acceptance("Do not disturb", function (needs) {
|
||||||
updateCurrentUser({ do_not_disturb_until: null });
|
updateCurrentUser({ do_not_disturb_until: null });
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
await click("#quick-access-profile .do-not-disturb .btn");
|
await click("#quick-access-profile .do-not-disturb .btn");
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ acceptance("Do not disturb", function (needs) {
|
||||||
updateCurrentUser({ do_not_disturb_until: null });
|
updateCurrentUser({ do_not_disturb_until: null });
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
await click("#quick-access-profile .do-not-disturb .btn");
|
await click("#quick-access-profile .do-not-disturb .btn");
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ acceptance("Do not disturb", function (needs) {
|
||||||
"The active dnd icon is shown"
|
"The active dnd icon is shown"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query(".do-not-disturb .relative-date").textContent.trim(),
|
query(".do-not-disturb .relative-date").textContent.trim(),
|
||||||
|
@ -126,7 +126,7 @@ acceptance("Do not disturb", function (needs) {
|
||||||
this.siteSettings.enable_user_status = true;
|
this.siteSettings.enable_user_status = true;
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
await click("#quick-access-profile .do-not-disturb .btn");
|
await click("#quick-access-profile .do-not-disturb .btn");
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ acceptance("Do not disturb", function (needs) {
|
||||||
updateCurrentUser({ do_not_disturb_until: DoNotDisturb.forever });
|
updateCurrentUser({ do_not_disturb_until: DoNotDisturb.forever });
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.dom(".do-not-disturb .relative-date").doesNotExist();
|
assert.dom(".do-not-disturb .relative-date").doesNotExist();
|
||||||
|
|
|
@ -51,7 +51,7 @@ acceptance(
|
||||||
|
|
||||||
test("history modal is shown when navigating from a non-topic page", async function (assert) {
|
test("history modal is shown when navigating from a non-topic page", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click(".notification.edited a");
|
await click(".notification.edited a");
|
||||||
const [v1, v2] = queryAll(".history-modal .revision-content");
|
const [v1, v2] = queryAll(".history-modal .revision-content");
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ acceptance(
|
||||||
|
|
||||||
test("history modal is not shown when navigating from a non-topic page", async function (assert) {
|
test("history modal is not shown when navigating from a non-topic page", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click(".notification.edited a");
|
await click(".notification.edited a");
|
||||||
assert
|
assert
|
||||||
.dom(".history-modal")
|
.dom(".history-modal")
|
||||||
|
@ -117,7 +117,7 @@ acceptance(
|
||||||
|
|
||||||
test("history modal is not shown when navigating from a non-topic page", async function (assert) {
|
test("history modal is not shown when navigating from a non-topic page", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click(".notification.edited a");
|
await click(".notification.edited a");
|
||||||
assert
|
assert
|
||||||
.dom(".history-modal")
|
.dom(".history-modal")
|
||||||
|
|
|
@ -8,6 +8,9 @@ import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
// header is the default.
|
// header is the default.
|
||||||
acceptance("Header API - authenticated", function (needs) {
|
acceptance("Header API - authenticated", function (needs) {
|
||||||
needs.user();
|
needs.user();
|
||||||
|
needs.settings({
|
||||||
|
glimmer_header_mode: "disabled",
|
||||||
|
});
|
||||||
|
|
||||||
test("can add buttons to the header", async function (assert) {
|
test("can add buttons to the header", async function (assert) {
|
||||||
withPluginApi("1.29.0", (api) => {
|
withPluginApi("1.29.0", (api) => {
|
||||||
|
@ -93,7 +96,7 @@ acceptance("Header API - anonymous", function () {
|
||||||
acceptance("Glimmer Header API - authenticated", function (needs) {
|
acceptance("Glimmer Header API - authenticated", function (needs) {
|
||||||
needs.user({ groups: AUTO_GROUPS.everyone });
|
needs.user({ groups: AUTO_GROUPS.everyone });
|
||||||
needs.settings({
|
needs.settings({
|
||||||
experimental_glimmer_header_groups: AUTO_GROUPS.everyone,
|
glimmer_header_mode: "enabled",
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can add buttons to the header", async function (assert) {
|
test("can add buttons to the header", async function (assert) {
|
||||||
|
|
|
@ -64,8 +64,9 @@ async function triggerSwipeEnd({ x, y, touchTarget }) {
|
||||||
// new Touch() isn't available in Firefox, so this is skipped there
|
// new Touch() isn't available in Firefox, so this is skipped there
|
||||||
acceptance("Mobile - menu swipes", function (needs) {
|
acceptance("Mobile - menu swipes", function (needs) {
|
||||||
needs.mobileView();
|
needs.mobileView();
|
||||||
needs.user({
|
needs.user();
|
||||||
glimmer_header_enabled: true,
|
needs.settings({
|
||||||
|
glimmer_header_mode: "enabled",
|
||||||
});
|
});
|
||||||
|
|
||||||
chromeTest("swipe to close hamburger", async function (assert) {
|
chromeTest("swipe to close hamburger", async function (assert) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
click,
|
click,
|
||||||
currentURL,
|
currentURL,
|
||||||
fillIn,
|
fillIn,
|
||||||
|
triggerEvent,
|
||||||
triggerKeyEvent,
|
triggerKeyEvent,
|
||||||
visit,
|
visit,
|
||||||
} from "@ember/test-helpers";
|
} from "@ember/test-helpers";
|
||||||
|
@ -19,6 +20,9 @@ import {
|
||||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||||
import I18n from "discourse-i18n";
|
import I18n from "discourse-i18n";
|
||||||
|
|
||||||
|
const clickOutside = () =>
|
||||||
|
triggerEvent(document.querySelector("header.d-header"), "pointerdown");
|
||||||
|
|
||||||
acceptance("Search - Anonymous", function (needs) {
|
acceptance("Search - Anonymous", function (needs) {
|
||||||
needs.pretender((server, helper) => {
|
needs.pretender((server, helper) => {
|
||||||
server.get("/search/query", (request) => {
|
server.get("/search/query", (request) => {
|
||||||
|
@ -106,7 +110,7 @@ acceptance("Search - Anonymous", function (needs) {
|
||||||
await click("#search-button");
|
await click("#search-button");
|
||||||
assert.ok(exists(".search-menu"));
|
assert.ok(exists(".search-menu"));
|
||||||
|
|
||||||
await click(".d-header"); // click outside
|
await clickOutside();
|
||||||
assert.ok(!exists(".search-menu"));
|
assert.ok(!exists(".search-menu"));
|
||||||
|
|
||||||
await click("#search-button");
|
await click("#search-button");
|
||||||
|
@ -1249,7 +1253,7 @@ acceptance("Search - assistant", function (needs) {
|
||||||
|
|
||||||
assert.notOk(exists(".btn.search-context"), "it removes the button");
|
assert.notOk(exists(".btn.search-context"), "it removes the button");
|
||||||
|
|
||||||
await click(".d-header");
|
await clickOutside();
|
||||||
await click("#search-button");
|
await click("#search-button");
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists(".btn.search-context"),
|
exists(".btn.search-context"),
|
||||||
|
|
|
@ -30,7 +30,7 @@ acceptance("Sidebar - Anonymous User", function (needs) {
|
||||||
this.siteSettings.navigation_menu = "header dropdown";
|
this.siteSettings.navigation_menu = "header dropdown";
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".hamburger-dropdown");
|
await click(".hamburger-dropdown button");
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists(".sidebar-hamburger-dropdown .sidebar-sections-anonymous"),
|
exists(".sidebar-hamburger-dropdown .sidebar-sections-anonymous"),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { click, visit, waitFor } from "@ember/test-helpers";
|
import { click, triggerEvent, visit, waitFor } from "@ember/test-helpers";
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import { test } from "qunit";
|
import { test } from "qunit";
|
||||||
import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
|
import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
|
||||||
|
@ -38,7 +38,8 @@ acceptance("Sidebar - Narrow Desktop", function (needs) {
|
||||||
"cloak sidebar is displayed"
|
"cloak sidebar is displayed"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("#main-outlet");
|
await triggerEvent(document.querySelector(".header-cloak"), "pointerdown");
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
!exists(".sidebar-hamburger-dropdown"),
|
!exists(".sidebar-hamburger-dropdown"),
|
||||||
"cloak sidebar is collapsed"
|
"cloak sidebar is collapsed"
|
||||||
|
@ -66,7 +67,7 @@ acceptance("Sidebar - Narrow Desktop", function (needs) {
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
});
|
});
|
||||||
|
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
$(".header-dropdown-toggle.current-user").click();
|
$(".header-dropdown-toggle.current-user").click();
|
||||||
|
|
||||||
assert.ok(exists(".quick-access-panel"));
|
assert.ok(exists(".quick-access-panel"));
|
||||||
|
|
|
@ -21,7 +21,7 @@ acceptance(
|
||||||
|
|
||||||
test("sections are collapsable", async function (assert) {
|
test("sections are collapsable", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".hamburger-dropdown");
|
await click("#toggle-hamburger-menu");
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists(".sidebar-section-header.sidebar-section-header-collapsable"),
|
exists(".sidebar-section-header.sidebar-section-header-collapsable"),
|
||||||
|
@ -42,14 +42,14 @@ acceptance(
|
||||||
|
|
||||||
test("showing and hiding sidebar", async function (assert) {
|
test("showing and hiding sidebar", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".hamburger-dropdown");
|
await click("#toggle-hamburger-menu");
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists(".sidebar-hamburger-dropdown"),
|
exists(".sidebar-hamburger-dropdown"),
|
||||||
"displays the sidebar dropdown"
|
"displays the sidebar dropdown"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(".hamburger-dropdown");
|
await click("#toggle-hamburger-menu");
|
||||||
|
|
||||||
assert.notOk(
|
assert.notOk(
|
||||||
exists(".sidebar-hamburger-dropdown"),
|
exists(".sidebar-hamburger-dropdown"),
|
||||||
|
@ -59,7 +59,7 @@ acceptance(
|
||||||
|
|
||||||
test("sections are not collapsable", async function (assert) {
|
test("sections are not collapsable", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".hamburger-dropdown");
|
await click("#toggle-hamburger-menu");
|
||||||
|
|
||||||
assert.notOk(
|
assert.notOk(
|
||||||
exists(".sidebar-section-header.sidebar-section-header-collapsable"),
|
exists(".sidebar-section-header.sidebar-section-header-collapsable"),
|
||||||
|
@ -69,7 +69,7 @@ acceptance(
|
||||||
|
|
||||||
test("'more' dropdown should display as regular list items in header dropdown mode", async function (assert) {
|
test("'more' dropdown should display as regular list items in header dropdown mode", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".hamburger-dropdown");
|
await click("#toggle-hamburger-menu");
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists("[data-link-name='admin']"),
|
exists("[data-link-name='admin']"),
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {
|
||||||
click,
|
click,
|
||||||
currentRouteName,
|
currentRouteName,
|
||||||
currentURL,
|
currentURL,
|
||||||
|
triggerEvent,
|
||||||
triggerKeyEvent,
|
triggerKeyEvent,
|
||||||
visit,
|
visit,
|
||||||
} from "@ember/test-helpers";
|
} from "@ember/test-helpers";
|
||||||
|
@ -60,7 +61,7 @@ acceptance("User menu", function (needs) {
|
||||||
|
|
||||||
test("notifications panel has a11y attributes", async function (assert) {
|
test("notifications panel has a11y attributes", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
const panel = query("#quick-access-all-notifications");
|
const panel = query("#quick-access-all-notifications");
|
||||||
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
|
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
|
@ -71,7 +72,7 @@ acceptance("User menu", function (needs) {
|
||||||
|
|
||||||
test("replies notifications panel has a11y attributes", async function (assert) {
|
test("replies notifications panel has a11y attributes", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-replies");
|
await click("#user-menu-button-replies");
|
||||||
const panel = query("#quick-access-replies");
|
const panel = query("#quick-access-replies");
|
||||||
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
|
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
|
||||||
|
@ -83,7 +84,7 @@ acceptance("User menu", function (needs) {
|
||||||
|
|
||||||
test("profile panel has a11y attributes", async function (assert) {
|
test("profile panel has a11y attributes", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
const panel = query("#quick-access-profile");
|
const panel = query("#quick-access-profile");
|
||||||
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
|
assert.strictEqual(panel.getAttribute("tabindex"), "-1");
|
||||||
|
@ -95,7 +96,7 @@ acceptance("User menu", function (needs) {
|
||||||
|
|
||||||
test("clicking on an unread notification", async function (assert) {
|
test("clicking on an unread notification", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
let repliesBadgeNotification = query(
|
let repliesBadgeNotification = query(
|
||||||
"#user-menu-button-replies .badge-notification"
|
"#user-menu-button-replies .badge-notification"
|
||||||
|
@ -114,7 +115,7 @@ acceptance("User menu", function (needs) {
|
||||||
"the Discourse-Clear-Notifications request header is set to the notification id in the next ajax request"
|
"the Discourse-Clear-Notifications request header is set to the notification id in the next ajax request"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
repliesBadgeNotification = query(
|
repliesBadgeNotification = query(
|
||||||
"#user-menu-button-replies .badge-notification"
|
"#user-menu-button-replies .badge-notification"
|
||||||
);
|
);
|
||||||
|
@ -129,7 +130,7 @@ acceptance("User menu", function (needs) {
|
||||||
updateCurrentUser({ reviewable_count: 1 });
|
updateCurrentUser({ reviewable_count: 1 });
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-review-queue");
|
await click("#user-menu-button-review-queue");
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
|
@ -152,7 +153,7 @@ acceptance("User menu", function (needs) {
|
||||||
"clicking on an item closes the menu after navigating"
|
"clicking on an item closes the menu after navigating"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-review-queue");
|
await click("#user-menu-button-review-queue");
|
||||||
await click("#quick-access-review-queue li.reviewable.pending a");
|
await click("#quick-access-review-queue li.reviewable.pending a");
|
||||||
|
|
||||||
|
@ -216,7 +217,7 @@ acceptance("User menu", function (needs) {
|
||||||
"user-menu-button-profile": I18n.t("user_menu.tabs.profile"),
|
"user-menu-button-profile": I18n.t("user_menu.tabs.profile"),
|
||||||
};
|
};
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
for (const [key, title] of Object.entries(expectedTitles)) {
|
for (const [key, title] of Object.entries(expectedTitles)) {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query(`#${key}`).title,
|
query(`#${key}`).title,
|
||||||
|
@ -291,7 +292,7 @@ acceptance("User menu", function (needs) {
|
||||||
};
|
};
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
exists("#user-menu-button-custom-tab-1"),
|
exists("#user-menu-button-custom-tab-1"),
|
||||||
|
@ -377,7 +378,7 @@ acceptance("User menu", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
const notifications = queryAll(
|
const notifications = queryAll(
|
||||||
"#quick-access-all-notifications ul li.notification"
|
"#quick-access-all-notifications ul li.notification"
|
||||||
|
@ -404,7 +405,7 @@ acceptance("User menu", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-bookmarks");
|
await click("#user-menu-button-bookmarks");
|
||||||
|
|
||||||
const bookmarks = queryAll("#quick-access-bookmarks ul li.bookmark");
|
const bookmarks = queryAll("#quick-access-bookmarks ul li.bookmark");
|
||||||
|
@ -431,7 +432,7 @@ acceptance("User menu", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-messages");
|
await click("#user-menu-button-messages");
|
||||||
|
|
||||||
const messages = queryAll("#quick-access-messages ul li.message");
|
const messages = queryAll("#quick-access-messages ul li.message");
|
||||||
|
@ -442,9 +443,12 @@ acceptance("User menu", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("the profile tab", async function (assert) {
|
test("the profile tab", async function (assert) {
|
||||||
|
const clickOutside = () =>
|
||||||
|
triggerEvent(document.querySelector("header.d-header"), "pointerdown");
|
||||||
|
|
||||||
updateCurrentUser({ draft_count: 13 });
|
updateCurrentUser({ draft_count: 13 });
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
const summaryLink = query("#quick-access-profile ul li.summary a");
|
const summaryLink = query("#quick-access-profile ul li.summary a");
|
||||||
|
@ -492,9 +496,10 @@ acceptance("User menu", function (needs) {
|
||||||
"invites link has the right icon"
|
"invites link has the right icon"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("header.d-header"); // close the menu
|
await clickOutside();
|
||||||
updateCurrentUser({ can_invite_to_forum: false });
|
updateCurrentUser({ can_invite_to_forum: false });
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.notOk(
|
assert.notOk(
|
||||||
|
@ -548,11 +553,11 @@ acceptance("User menu", function (needs) {
|
||||||
"Do Not Disturb button has the right icon"
|
"Do Not Disturb button has the right icon"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("header.d-header"); // close the menu
|
await clickOutside();
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
date.setHours(date.getHours() + 2);
|
date.setHours(date.getHours() + 2);
|
||||||
updateCurrentUser({ do_not_disturb_until: date.toISOString() });
|
updateCurrentUser({ do_not_disturb_until: date.toISOString() });
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
doNotDisturbButton = query(
|
doNotDisturbButton = query(
|
||||||
|
@ -591,9 +596,9 @@ acceptance("User menu", function (needs) {
|
||||||
"toggle anonymous button has the right icon when the user isn't anonymous"
|
"toggle anonymous button has the right icon when the user isn't anonymous"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("header.d-header"); // close the menu
|
await clickOutside();
|
||||||
updateCurrentUser({ is_anonymous: true });
|
updateCurrentUser({ is_anonymous: true });
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
toggleAnonButton = query(
|
toggleAnonButton = query(
|
||||||
|
@ -612,7 +617,7 @@ acceptance("User menu", function (needs) {
|
||||||
"toggle anonymous button has the right icon when the user is anonymous"
|
"toggle anonymous button has the right icon when the user is anonymous"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("header.d-header"); // close the menu
|
await clickOutside();
|
||||||
updateCurrentUser({
|
updateCurrentUser({
|
||||||
is_anonymous: false,
|
is_anonymous: false,
|
||||||
can_post_anonymously: false,
|
can_post_anonymously: false,
|
||||||
|
@ -623,7 +628,7 @@ acceptance("User menu", function (needs) {
|
||||||
AUTO_GROUPS.trust_level_2,
|
AUTO_GROUPS.trust_level_2,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.notOk(
|
assert.notOk(
|
||||||
|
@ -635,7 +640,7 @@ acceptance("User menu", function (needs) {
|
||||||
"toggle anon button isn't shown when the user can't use it"
|
"toggle anon button isn't shown when the user can't use it"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("header.d-header"); // close the menu
|
await clickOutside();
|
||||||
updateCurrentUser({
|
updateCurrentUser({
|
||||||
is_anonymous: true,
|
is_anonymous: true,
|
||||||
trust_level: 2,
|
trust_level: 2,
|
||||||
|
@ -646,7 +651,7 @@ acceptance("User menu", function (needs) {
|
||||||
AUTO_GROUPS.trust_level_2,
|
AUTO_GROUPS.trust_level_2,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
|
@ -654,7 +659,7 @@ acceptance("User menu", function (needs) {
|
||||||
"toggle anon button is always shown if the user is anonymous"
|
"toggle anon button is always shown if the user is anonymous"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("header.d-header"); // close the menu
|
await clickOutside();
|
||||||
updateCurrentUser({
|
updateCurrentUser({
|
||||||
is_anonymous: true,
|
is_anonymous: true,
|
||||||
can_post_anonymously: true,
|
can_post_anonymously: true,
|
||||||
|
@ -667,7 +672,7 @@ acceptance("User menu", function (needs) {
|
||||||
AUTO_GROUPS.trust_level_4,
|
AUTO_GROUPS.trust_level_4,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.notOk(
|
assert.notOk(
|
||||||
|
@ -675,7 +680,7 @@ acceptance("User menu", function (needs) {
|
||||||
"toggle anon button is not shown if the allow_anonymous_posting setting is false"
|
"toggle anon button is not shown if the allow_anonymous_posting setting is false"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click("header.d-header"); // close the menu
|
await clickOutside();
|
||||||
updateCurrentUser({
|
updateCurrentUser({
|
||||||
is_anonymous: false,
|
is_anonymous: false,
|
||||||
can_post_anonymously: false,
|
can_post_anonymously: false,
|
||||||
|
@ -686,7 +691,7 @@ acceptance("User menu", function (needs) {
|
||||||
AUTO_GROUPS.trust_level_2,
|
AUTO_GROUPS.trust_level_2,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.notOk(
|
assert.notOk(
|
||||||
|
@ -726,7 +731,7 @@ acceptance("User menu", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
const item1 = query("#quick-access-profile ul li.test-1-item");
|
const item1 = query("#quick-access-profile ul li.test-1-item");
|
||||||
|
@ -792,7 +797,7 @@ acceptance("User menu", function (needs) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-all-notifications");
|
await click("#user-menu-button-all-notifications");
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
currentURL(),
|
currentURL(),
|
||||||
|
@ -812,7 +817,7 @@ acceptance("User menu", function (needs) {
|
||||||
["#user-menu-button-profile", "/u/eviltrout/summary"],
|
["#user-menu-button-profile", "/u/eviltrout/summary"],
|
||||||
];
|
];
|
||||||
for (const [id, expectedLink] of tabs) {
|
for (const [id, expectedLink] of tabs) {
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click(id);
|
await click(id);
|
||||||
await click(id);
|
await click(id);
|
||||||
if (expectedLink) {
|
if (expectedLink) {
|
||||||
|
@ -837,7 +842,7 @@ acceptance("User menu", function (needs) {
|
||||||
|
|
||||||
test("tabs have hrefs and can be opened in new window/tab", async function (assert) {
|
test("tabs have hrefs and can be opened in new window/tab", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom("#user-menu-button-replies")
|
.dom("#user-menu-button-replies")
|
||||||
|
@ -865,7 +870,7 @@ acceptance("User menu", function (needs) {
|
||||||
|
|
||||||
test("tabs without hrefs can be visited with the keyboard", async function (assert) {
|
test("tabs without hrefs can be visited with the keyboard", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
await triggerKeyEvent(
|
await triggerKeyEvent(
|
||||||
"#user-menu-button-other-notifications",
|
"#user-menu-button-other-notifications",
|
||||||
|
@ -881,7 +886,7 @@ acceptance("User menu", function (needs) {
|
||||||
|
|
||||||
test("closes the menu when navigating away", async function (assert) {
|
test("closes the menu when navigating away", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
await click(".quick-access-panel .preferences a");
|
await click(".quick-access-panel .preferences a");
|
||||||
|
|
||||||
|
@ -947,7 +952,7 @@ acceptance("User menu - Dismiss button", function (needs) {
|
||||||
|
|
||||||
test("shows confirmation modal for the all-notifications list", async function (assert) {
|
test("shows confirmation modal for the all-notifications list", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
await click(".user-menu .notifications-dismiss");
|
await click(".user-menu .notifications-dismiss");
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
|
@ -968,7 +973,7 @@ acceptance("User menu - Dismiss button", function (needs) {
|
||||||
|
|
||||||
test("shows confirmation modal for the bookmarks list", async function (assert) {
|
test("shows confirmation modal for the bookmarks list", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query("#user-menu-button-bookmarks .badge-notification").textContent,
|
query("#user-menu-button-bookmarks .badge-notification").textContent,
|
||||||
|
@ -1024,7 +1029,7 @@ acceptance("User menu - Dismiss button", function (needs) {
|
||||||
|
|
||||||
test("shows confirmation modal for the messages list", async function (assert) {
|
test("shows confirmation modal for the messages list", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query("#user-menu-button-messages .badge-notification").textContent,
|
query("#user-menu-button-messages .badge-notification").textContent,
|
||||||
|
@ -1080,7 +1085,7 @@ acceptance("User menu - Dismiss button", function (needs) {
|
||||||
|
|
||||||
test("doesn't show confirmation modal for the likes notifications list", async function (assert) {
|
test("doesn't show confirmation modal for the likes notifications list", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
await click("#user-menu-button-likes");
|
await click("#user-menu-button-likes");
|
||||||
await click(".user-menu .notifications-dismiss");
|
await click(".user-menu .notifications-dismiss");
|
||||||
|
@ -1092,7 +1097,7 @@ acceptance("User menu - Dismiss button", function (needs) {
|
||||||
|
|
||||||
test("doesn't show confirmation modal for the other notifications list", async function (assert) {
|
test("doesn't show confirmation modal for the other notifications list", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
|
|
||||||
await click("#user-menu-button-other-notifications");
|
await click("#user-menu-button-other-notifications");
|
||||||
let othersBadgeNotification = query(
|
let othersBadgeNotification = query(
|
||||||
|
@ -1125,14 +1130,14 @@ acceptance("User menu - avatars", function (needs) {
|
||||||
|
|
||||||
test("It shows user avatars for various notifications on all notifications pane", async function (assert) {
|
test("It shows user avatars for various notifications on all notifications pane", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
assert.ok(exists("li.notification.edited .icon-avatar"));
|
assert.ok(exists("li.notification.edited .icon-avatar"));
|
||||||
assert.ok(exists("li.notification.replied .icon-avatar"));
|
assert.ok(exists("li.notification.replied .icon-avatar"));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("It shows user avatars for messages", async function (assert) {
|
test("It shows user avatars for messages", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-messages");
|
await click("#user-menu-button-messages");
|
||||||
|
|
||||||
assert.ok(exists("li.notification.private-message .icon-avatar"));
|
assert.ok(exists("li.notification.private-message .icon-avatar"));
|
||||||
|
@ -1141,7 +1146,7 @@ acceptance("User menu - avatars", function (needs) {
|
||||||
|
|
||||||
test("It shows user avatars for bookmark items and bookmark reminder notification items", async function (assert) {
|
test("It shows user avatars for bookmark items and bookmark reminder notification items", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
await click("#user-menu-button-bookmarks");
|
await click("#user-menu-button-bookmarks");
|
||||||
|
|
||||||
assert.ok(exists("li.notification.bookmark-reminder .icon-avatar"));
|
assert.ok(exists("li.notification.bookmark-reminder .icon-avatar"));
|
||||||
|
@ -1150,7 +1155,7 @@ acceptance("User menu - avatars", function (needs) {
|
||||||
|
|
||||||
test("Icon avatars have correct class names based on system avatar usage", async function (assert) {
|
test("Icon avatars have correct class names based on system avatar usage", async function (assert) {
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".d-header-icons .current-user");
|
await click(".d-header-icons .current-user button");
|
||||||
assert.ok(exists("li.group-message-summary .icon-avatar.system-avatar"));
|
assert.ok(exists("li.group-message-summary .icon-avatar.system-avatar"));
|
||||||
assert.ok(exists("li.notification.replied .icon-avatar.user-avatar"));
|
assert.ok(exists("li.notification.replied .icon-avatar.user-avatar"));
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
} from "discourse/tests/helpers/qunit-helpers";
|
} from "discourse/tests/helpers/qunit-helpers";
|
||||||
|
|
||||||
async function openUserStatusModal() {
|
async function openUserStatusModal() {
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
await click(".set-user-status button");
|
await click(".set-user-status button");
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ acceptance("User Status", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
@ -155,7 +155,7 @@ acceptance("User Status", function (needs) {
|
||||||
"shows user status emoji on the user avatar in the header"
|
"shows user status emoji on the user avatar in the header"
|
||||||
);
|
);
|
||||||
|
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
assert.equal(
|
assert.equal(
|
||||||
query(
|
query(
|
||||||
|
@ -184,7 +184,7 @@ acceptance("User Status", function (needs) {
|
||||||
await pickEmoji(userStatusEmoji);
|
await pickEmoji(userStatusEmoji);
|
||||||
await click(".btn-primary"); // save
|
await click(".btn-primary"); // save
|
||||||
|
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
assert.equal(
|
assert.equal(
|
||||||
query(
|
query(
|
||||||
|
@ -222,7 +222,7 @@ acceptance("User Status", function (needs) {
|
||||||
await click("#tap_tile_one_hour");
|
await click("#tap_tile_one_hour");
|
||||||
await click(".btn-primary"); // save
|
await click(".btn-primary"); // save
|
||||||
|
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
@ -476,7 +476,7 @@ acceptance("User Status - user menu", function (needs) {
|
||||||
this.siteSettings.enable_user_status = false;
|
this.siteSettings.enable_user_status = false;
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.notOk(exists("li.set-user-status"));
|
assert.notOk(exists("li.set-user-status"));
|
||||||
|
@ -486,7 +486,7 @@ acceptance("User Status - user menu", function (needs) {
|
||||||
this.siteSettings.enable_user_status = true;
|
this.siteSettings.enable_user_status = true;
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.ok(exists("li.set-user-status .btn"), "shows the button");
|
assert.ok(exists("li.set-user-status .btn"), "shows the button");
|
||||||
|
@ -503,7 +503,7 @@ acceptance("User Status - user menu", function (needs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
|
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
@ -529,7 +529,7 @@ acceptance("User Status - user menu", function (needs) {
|
||||||
this.siteSettings.enable_user_status = true;
|
this.siteSettings.enable_user_status = true;
|
||||||
|
|
||||||
await visit("/");
|
await visit("/");
|
||||||
await click(".header-dropdown-toggle.current-user");
|
await click(".header-dropdown-toggle.current-user button");
|
||||||
await click("#user-menu-button-profile");
|
await click("#user-menu-button-profile");
|
||||||
await click(".set-user-status button");
|
await click(".set-user-status button");
|
||||||
|
|
||||||
|
|
|
@ -98,13 +98,14 @@ export function performEmojiUnescape(string, opts) {
|
||||||
isReplaceableInlineEmoji(string, index, opts.inlineEmoji);
|
isReplaceableInlineEmoji(string, index, opts.inlineEmoji);
|
||||||
|
|
||||||
const title = opts.title ?? emojiVal;
|
const title = opts.title ?? emojiVal;
|
||||||
|
const alt = opts.alt ?? opts.title ?? emojiVal;
|
||||||
const tabIndex = opts.tabIndex ? ` tabindex='${opts.tabIndex}'` : "";
|
const tabIndex = opts.tabIndex ? ` tabindex='${opts.tabIndex}'` : "";
|
||||||
return url && isReplacable
|
return url && isReplacable
|
||||||
? `<img width="20" height="20" src='${url}' ${
|
? `<img width="20" height="20" src='${url}' ${
|
||||||
opts.skipTitle ? "" : `title='${title}'`
|
opts.skipTitle ? "" : `title='${title}'`
|
||||||
} ${
|
} ${
|
||||||
opts.lazy ? "loading='lazy' " : ""
|
opts.lazy ? "loading='lazy' " : ""
|
||||||
}alt='${title}' class='${classes}'${tabIndex}>`
|
}alt='${alt}' class='${classes}'${tabIndex}>`
|
||||||
: m;
|
: m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1823,10 +1823,6 @@ class User < ActiveRecord::Base
|
||||||
in_any_groups?(SiteSetting.experimental_new_new_view_groups_map)
|
in_any_groups?(SiteSetting.experimental_new_new_view_groups_map)
|
||||||
end
|
end
|
||||||
|
|
||||||
def glimmer_header_enabled?
|
|
||||||
in_any_groups?(SiteSetting.experimental_glimmer_header_groups_map)
|
|
||||||
end
|
|
||||||
|
|
||||||
def watched_precedence_over_muted
|
def watched_precedence_over_muted
|
||||||
if user_option.watched_precedence_over_muted.nil?
|
if user_option.watched_precedence_over_muted.nil?
|
||||||
SiteSetting.watched_precedence_over_muted
|
SiteSetting.watched_precedence_over_muted
|
||||||
|
|
|
@ -74,7 +74,6 @@ class CurrentUserSerializer < BasicUserSerializer
|
||||||
:new_new_view_enabled?,
|
:new_new_view_enabled?,
|
||||||
:use_experimental_topic_bulk_actions?,
|
:use_experimental_topic_bulk_actions?,
|
||||||
:use_admin_sidebar,
|
:use_admin_sidebar,
|
||||||
:glimmer_header_enabled?,
|
|
||||||
:can_view_raw_email
|
:can_view_raw_email
|
||||||
|
|
||||||
delegate :user_stat, to: :object, private: true
|
delegate :user_stat, to: :object, private: true
|
||||||
|
|
|
@ -2620,7 +2620,7 @@ en:
|
||||||
experimental_topics_filter: "EXPERIMENTAL: Enables the experimental topics filter route at /filter"
|
experimental_topics_filter: "EXPERIMENTAL: Enables the experimental topics filter route at /filter"
|
||||||
enable_experimental_lightbox: "EXPERIMENTAL: Replace the default image lightbox with the revamped design."
|
enable_experimental_lightbox: "EXPERIMENTAL: Replace the default image lightbox with the revamped design."
|
||||||
enable_experimental_bookmark_redesign_groups: "EXPERIMENTAL: Show a quick access menu for bookmarks on posts and a new redesigned modal"
|
enable_experimental_bookmark_redesign_groups: "EXPERIMENTAL: Show a quick access menu for bookmarks on posts and a new redesigned modal"
|
||||||
experimental_glimmer_header_groups: "EXPERIMENTAL: Render the site header as glimmer components."
|
glimmer_header_mode: "Control whether the new 'glimmer' header implementation is used. Defaults to 'auto', which will enable automatically once all your themes and plugins are ready. https://meta.discourse.org/t/296544"
|
||||||
experimental_form_templates: "EXPERIMENTAL: Enable the form templates feature. <b>After enabled,</b> manage the templates at <a href='%{base_path}/admin/customize/form-templates'>Customize / Templates</a>."
|
experimental_form_templates: "EXPERIMENTAL: Enable the form templates feature. <b>After enabled,</b> manage the templates at <a href='%{base_path}/admin/customize/form-templates'>Customize / Templates</a>."
|
||||||
admin_sidebar_enabled_groups: "EXPERIMENTAL: Enable sidebar navigation for the admin UI for the specified groups, which replaces the top-level admin navigation buttons."
|
admin_sidebar_enabled_groups: "EXPERIMENTAL: Enable sidebar navigation for the admin UI for the specified groups, which replaces the top-level admin navigation buttons."
|
||||||
lazy_load_categories_groups: "EXPERIMENTAL: Lazy load category information only for users of these groups. This improves performance on sites with many categories."
|
lazy_load_categories_groups: "EXPERIMENTAL: Lazy load category information only for users of these groups. This improves performance on sites with many categories."
|
||||||
|
|
|
@ -2352,12 +2352,14 @@ developer:
|
||||||
instrument_gc_stat_per_request:
|
instrument_gc_stat_per_request:
|
||||||
default: false
|
default: false
|
||||||
hidden: true
|
hidden: true
|
||||||
experimental_glimmer_header_groups:
|
glimmer_header_mode:
|
||||||
client: true
|
client: true
|
||||||
type: group_list
|
type: enum
|
||||||
list_type: compact
|
choices:
|
||||||
default: ""
|
- disabled
|
||||||
allow_any: false
|
- auto
|
||||||
|
- enabled
|
||||||
|
default: auto
|
||||||
admin_sidebar_enabled_groups:
|
admin_sidebar_enabled_groups:
|
||||||
type: group_list
|
type: group_list
|
||||||
list_type: compact
|
list_type: compact
|
||||||
|
|
|
@ -5,7 +5,7 @@ RSpec.describe "Glimmer Header", type: :system do
|
||||||
let(:search) { PageObjects::Pages::Search.new }
|
let(:search) { PageObjects::Pages::Search.new }
|
||||||
fab!(:current_user) { Fabricate(:user) }
|
fab!(:current_user) { Fabricate(:user) }
|
||||||
fab!(:topic)
|
fab!(:topic)
|
||||||
before { SiteSetting.experimental_glimmer_header_groups = Group::AUTO_GROUPS[:everyone] }
|
before { SiteSetting.glimmer_header_mode = "enabled" }
|
||||||
|
|
||||||
it "renders basics" do
|
it "renders basics" do
|
||||||
visit "/"
|
visit "/"
|
||||||
|
|
Loading…
Reference in New Issue