This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/tests/acceptance/preferences-test.js
Martin Brennan ac7bf98ad1
DEV: Load client site settings YML into JS tests (#18413)
Our method of loading a subset of client settings into tests via
tests/helpers/site-settings.js can be improved upon. Currently we have a
hardcoded subset of the client settings, which may get out of date and not have
the correct defaults. As well as this plugins do not get their settings into the
tests, so whenever you need a setting from a plugin, even if it has a default,
you have to do needs.setting({ ... }) which is inconvenient.

This commit introduces an ember CLI build step to take the site_settings.yml and
all the plugin settings.yml files, pull out the client settings, and dump them
into a variable in a single JS file we can load in our tests, so we have the
correct selection of settings and default values in our JS tests. It also fixes
many, many tests that were operating under incorrect assumptions or old
settings.

Co-authored-by: Joffrey JAFFEUX <j.jaffeux@gmail.com>
2022-11-08 09:17:43 +10:00

652 lines
18 KiB
JavaScript

import {
acceptance,
count,
exists,
query,
updateCurrentUser,
} from "discourse/tests/helpers/qunit-helpers";
import {
click,
currentRouteName,
currentURL,
fillIn,
visit,
} from "@ember/test-helpers";
import I18n from "I18n";
import User from "discourse/models/user";
import selectKit from "discourse/tests/helpers/select-kit-helper";
import { test } from "qunit";
function preferencesPretender(server, helper) {
server.post("/u/second_factors.json", () => {
return helper.response({
success: "OK",
password_required: "true",
});
});
server.post("/u/create_second_factor_totp.json", () => {
return helper.response({
key: "rcyryaqage3jexfj",
qr: "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=",
});
});
server.post("/u/create_second_factor_security_key.json", () => {
return helper.response({
challenge: "a6d393d12654c130b2273e68ca25ca232d1d7f4c2464c2610fb8710a89d4",
rp_id: "localhost",
rp_name: "Discourse",
supported_algorithms: [-7, -257],
});
});
server.post("/u/enable_second_factor_totp.json", () => {
return helper.response({ error: "invalid token" });
});
server.put("/u/second_factors_backup.json", () => {
return helper.response({
backup_codes: ["dsffdsd", "fdfdfdsf", "fddsds"],
});
});
server.post("/u/eviltrout/preferences/revoke-account", () => {
return helper.response({
success: true,
});
});
server.put("/u/eviltrout/preferences/email", () => {
return helper.response({
success: true,
});
});
server.post("/user_avatar/eviltrout/refresh_gravatar.json", () => {
return helper.response({
gravatar_upload_id: 6543,
gravatar_avatar_template: "/images/avatar.png",
});
});
server.get("/u/eviltrout/activity.json", () => {
return helper.response({});
});
}
acceptance("User Preferences", function (needs) {
needs.user();
needs.pretender(preferencesPretender);
test("update some fields", async function (assert) {
await visit("/u/eviltrout/preferences");
assert.ok(
document.body.classList.contains("user-preferences-page"),
"has the body class"
);
assert.strictEqual(
currentURL(),
"/u/eviltrout/preferences/account",
"defaults to account tab"
);
assert.ok(exists(".user-preferences"), "it shows the preferences");
const savePreferences = async () => {
assert.ok(!exists(".saved"), "it hasn't been saved yet");
await click(".save-changes");
assert.ok(exists(".saved"), "it displays the saved message");
query(".saved").remove();
};
await fillIn(".pref-name input[type=text]", "Jon Snow");
await savePreferences();
await click(".preferences-nav .nav-profile a");
await fillIn("#edit-location", "Westeros");
await savePreferences();
await click(".preferences-nav .nav-emails a");
await click(".pref-activity-summary input[type=checkbox]");
await savePreferences();
await click(".preferences-nav .nav-notifications a");
await selectKit(
".control-group.notifications .combo-box.duration"
).expand();
await selectKit(
".control-group.notifications .combo-box.duration"
).selectRowByValue(1440);
await savePreferences();
await click(".preferences-nav .nav-categories a");
const categorySelector = selectKit(
".tracking-controls .category-selector "
);
await categorySelector.expand();
await categorySelector.fillInFilter("faq");
await savePreferences();
this.siteSettings.tagging_enabled = false;
await visit("/");
await visit("/u/eviltrout/preferences");
assert.ok(
!exists(".preferences-nav .nav-tags a"),
"tags tab isn't there when tags are disabled"
);
await click(".preferences-nav .nav-interface a");
await click(".control-group.other input[type=checkbox]:nth-of-type(1)");
await savePreferences();
assert.ok(
!exists(".preferences-nav .nav-apps a"),
"apps tab isn't there when you have no authorized apps"
);
});
test("username", async function (assert) {
await visit("/u/eviltrout/preferences/username");
assert.ok(exists("#change_username"), "it has the input element");
});
test("email", async function (assert) {
await visit("/u/eviltrout/preferences/email");
assert.ok(exists("#change-email"), "it has the input element");
await fillIn("#change-email", "invalid-email");
assert.strictEqual(
query(".tip.bad").innerText.trim(),
I18n.t("user.email.invalid"),
"it should display invalid email tip"
);
});
test("email field always shows up", async function (assert) {
await visit("/u/eviltrout/preferences/email");
assert.ok(exists("#change-email"), "it has the input element");
await fillIn("#change-email", "eviltrout@discourse.org");
await click(".user-preferences button.btn-primary");
await visit("/u/eviltrout/preferences");
await visit("/u/eviltrout/preferences/email");
assert.ok(exists("#change-email"), "it has the input element");
});
test("connected accounts", async function (assert) {
await visit("/u/eviltrout/preferences/account");
assert.ok(
exists(".pref-associated-accounts"),
"it has the connected accounts section"
);
assert.ok(
query(
".pref-associated-accounts table tr:nth-of-type(1) td:nth-of-type(1)"
).innerHTML.includes("Facebook"),
"it lists facebook"
);
await click(
".pref-associated-accounts table tr:nth-of-type(1) td:last-child button"
);
assert.ok(
query(
".pref-associated-accounts table tr:nth-of-type(1) td:last-of-type"
).innerHTML.includes("Connect")
);
});
test("second factor totp", async function (assert) {
await visit("/u/eviltrout/preferences/second-factor");
assert.ok(exists("#password"), "it has a password input");
await fillIn("#password", "secrets");
await click(".user-preferences .btn-primary");
assert.notOk(exists("#password"), "it hides the password input");
await click(".new-totp");
assert.ok(exists(".qr-code img"), "shows qr code image");
await click(".add-totp");
assert.ok(
query(".alert-error").innerHTML.includes("provide a name and the code"),
"shows name/token missing error message"
);
});
test("second factor security keys", async function (assert) {
await visit("/u/eviltrout/preferences/second-factor");
assert.ok(exists("#password"), "it has a password input");
await fillIn("#password", "secrets");
await click(".user-preferences .btn-primary");
assert.notOk(exists("#password"), "it hides the password input");
await click(".new-security-key");
assert.ok(exists("#security-key-name"), "shows security key name input");
await fillIn("#security-key-name", "");
// The following tests can only run when Webauthn is enabled. This is not
// always the case, for example on a browser running on a non-standard port
if (typeof PublicKeyCredential !== "undefined") {
await click(".add-security-key");
assert.ok(
query(".alert-error").innerHTML.includes("provide a name"),
"shows name missing error message"
);
}
});
test("default avatar selector", async function (assert) {
await visit("/u/eviltrout/preferences");
await click(".pref-avatar .btn");
assert.ok(exists(".avatar-choice", "opens the avatar selection modal"));
await click(".avatar-selector-refresh-gravatar");
assert.strictEqual(
User.currentProp("gravatar_avatar_upload_id"),
6543,
"it should set the gravatar_avatar_upload_id property"
);
});
});
acceptance("Second Factor Backups", function (needs) {
needs.user();
needs.pretender((server, helper) => {
server.post("/u/second_factors.json", () => {
return helper.response({
success: "OK",
totps: [{ id: 1, name: "one of them" }],
});
});
server.put("/u/second_factors_backup.json", () => {
return helper.response({
backup_codes: ["dsffdsd", "fdfdfdsf", "fddsds"],
});
});
server.get("/u/eviltrout/activity.json", () => {
return helper.response({});
});
});
test("second factor backup", async function (assert) {
updateCurrentUser({ second_factor_enabled: true });
await visit("/u/eviltrout/preferences/second-factor");
await click(".edit-2fa-backup");
assert.ok(
exists(".second-factor-backup-preferences"),
"shows the 2fa backup panel"
);
await click(".second-factor-backup-preferences .btn-primary");
assert.ok(exists(".backup-codes-area"), "shows backup codes");
});
});
acceptance(
"Avatar selector when selectable avatars is enabled",
function (needs) {
needs.user();
needs.settings({ selectable_avatars_mode: "no_one" });
needs.pretender((server, helper) => {
server.get("/site/selectable-avatars.json", () =>
helper.response([
"https://www.discourse.org",
"https://meta.discourse.org",
])
);
});
test("selectable avatars", async function (assert) {
await visit("/u/eviltrout/preferences");
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.notOk(
exists(
"#uploaded-avatar",
"avatar selection modal does not include option to upload"
)
);
});
}
);
acceptance(
"Avatar selector when selectable avatars allows staff to upload",
function (needs) {
needs.user();
needs.settings({ selectable_avatars_mode: "staff" });
needs.pretender((server, helper) => {
server.get("/site/selectable-avatars.json", () =>
helper.response([
"https://www.discourse.org",
"https://meta.discourse.org",
])
);
});
test("allows staff to upload", async function (assert) {
updateCurrentUser({
trust_level: 3,
moderator: true,
admin: false,
});
await visit("/u/eviltrout/preferences");
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.ok(
exists(
"#uploaded-avatar",
"avatar selection modal includes option to upload"
)
);
});
test("disallow non-staff", async function (assert) {
await visit("/u/eviltrout/preferences");
updateCurrentUser({
trust_level: 3,
moderator: false,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.notOk(
exists(
"#uploaded-avatar",
"avatar selection modal does not include option to upload"
)
);
});
}
);
acceptance(
"Avatar selector when selectable avatars allows trust level 3+ to upload",
function (needs) {
needs.user();
needs.settings({ selectable_avatars_mode: "tl3" });
needs.pretender((server, helper) => {
server.get("/site/selectable-avatars.json", () =>
helper.response([
"https://www.discourse.org",
"https://meta.discourse.org",
])
);
});
test("with a tl3 user", async function (assert) {
await visit("/u/eviltrout/preferences");
updateCurrentUser({
trust_level: 3,
moderator: false,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.ok(
exists(
"#uploaded-avatar",
"avatar selection modal does includes option to upload"
)
);
});
test("with a tl2 user", async function (assert) {
await visit("/u/eviltrout/preferences");
updateCurrentUser({
trust_level: 2,
moderator: false,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.notOk(
exists(
"#uploaded-avatar",
"avatar selection modal does not include option to upload"
)
);
});
test("always allow staff to upload", async function (assert) {
await visit("/u/eviltrout/preferences");
updateCurrentUser({
trust_level: 2,
moderator: true,
admin: false,
});
await click(".pref-avatar .btn");
assert.ok(
exists(".selectable-avatars", "opens the avatar selection modal")
);
assert.ok(
exists(
"#uploaded-avatar",
"avatar selection modal includes option to upload"
)
);
});
}
);
acceptance("User Preferences when badges are disabled", function (needs) {
needs.user();
needs.settings({ enable_badges: false });
needs.pretender(preferencesPretender);
test("visit my preferences", async function (assert) {
await visit("/u/eviltrout/preferences");
assert.ok(
document.body.classList.contains("user-preferences-page"),
"has the body class"
);
assert.strictEqual(
currentURL(),
"/u/eviltrout/preferences/account",
"defaults to account tab"
);
assert.ok(exists(".user-preferences"), "it shows the preferences");
});
});
acceptance("Custom User Fields", function (needs) {
needs.user();
needs.site({
user_fields: [
{
id: 30,
name: "What kind of pet do you have?",
field_type: "dropdown",
options: ["Dog", "Cat", "Hamster"],
required: true,
},
],
});
needs.pretender(preferencesPretender);
test("can select an option from a dropdown", async function (assert) {
await visit("/u/eviltrout/preferences/profile");
assert.ok(exists(".user-field"), "it has at least one user field");
await click(".user-field.dropdown");
const field = selectKit(
".user-field-what-kind-of-pet-do-you-have .combo-box"
);
await field.expand();
await field.selectRowByValue("Cat");
assert.strictEqual(
field.header().value(),
"Cat",
"it sets the value of the field"
);
});
});
acceptance(
"User Preferences, selecting bookmarks discovery as user's default homepage",
function (needs) {
needs.user();
needs.settings({
top_menu: "categories|latest|top|bookmarks",
});
test("selecting bookmarks as home directs home to bookmarks", async function (assert) {
await visit("/u/eviltrout/preferences/interface");
assert.ok(exists(".home .combo-box"), "it has a home selector combo-box");
const field = selectKit(".home .combo-box");
await field.expand();
await field.selectRowByValue("6");
await click(".save-changes");
await visit("/");
assert.ok(exists(".topic-list"), "The list of topics was rendered");
assert.strictEqual(
currentRouteName(),
"discovery.bookmarks",
"it navigates to bookmarks"
);
});
}
);
acceptance("Ignored users", function (needs) {
needs.user();
needs.settings({ min_trust_level_to_allow_ignore: 1 });
test("when trust level < min level to ignore", async function (assert) {
await visit(`/u/eviltrout/preferences/users`);
updateCurrentUser({ trust_level: 0, moderator: false, admin: false });
assert.ok(
!exists(".user-ignore"),
"it does not show the list of ignored users"
);
});
test("when trust level >= min level to ignore", async function (assert) {
await visit(`/u/eviltrout/preferences/users`);
updateCurrentUser({ trust_level: 1 });
assert.ok(exists(".user-ignore"), "it shows the list of ignored users");
});
test("staff can always see ignored users", async function (assert) {
await visit(`/u/eviltrout/preferences/users`);
updateCurrentUser({ moderator: true });
assert.ok(exists(".user-ignore"), "it shows the list of ignored users");
});
});
acceptance("Security", function (needs) {
needs.user();
needs.pretender(preferencesPretender);
test("recently connected devices", async function (assert) {
await visit("/u/eviltrout/preferences/security");
assert.strictEqual(
query(
".auth-tokens > .auth-token:nth-of-type(1) .auth-token-device"
).innerText.trim(),
"Linux Computer",
"it should display active token first"
);
assert.strictEqual(
query(".pref-auth-tokens > a:nth-of-type(1)").innerText.trim(),
I18n.t("user.auth_tokens.show_all", { count: 3 }),
"it should display two tokens"
);
assert.strictEqual(
count(".pref-auth-tokens .auth-token"),
2,
"it should display two tokens"
);
await click(".pref-auth-tokens > a:nth-of-type(1)");
assert.strictEqual(
count(".pref-auth-tokens .auth-token"),
3,
"it should display three tokens"
);
const authTokenDropdown = selectKit(".auth-token-dropdown");
await authTokenDropdown.expand();
await authTokenDropdown.selectRowByValue("notYou");
assert.strictEqual(count(".d-modal:visible"), 1, "modal should appear");
await click(".modal-footer .btn-primary");
assert.strictEqual(
count(".pref-password.highlighted"),
1,
"it should highlight password preferences"
);
});
});
acceptance(
"User Preferences for staged user and don't allow tracking prefs",
function (needs) {
needs.settings({
allow_changing_staged_user_tracking: false,
tagging_enabled: true,
});
needs.pretender(preferencesPretender);
test("staged user doesn't show category and tag preferences", async function (assert) {
await visit("/u/staged/preferences");
assert.ok(
document.body.classList.contains("user-preferences-page"),
"has the body class"
);
assert.strictEqual(
currentURL(),
"/u/staged/preferences/account",
"defaults to account tab"
);
assert.ok(exists(".user-preferences"), "it shows the preferences");
assert.ok(
!exists(".preferences-nav .nav-categories a"),
"categories tab isn't there for staged users"
);
assert.ok(
!exists(".preferences-nav .nav-tags a"),
"tags tab isn't there for staged users"
);
});
}
);