Go to welcome on logout (#33306)

* Go to welcome on logout

Instead of login, for QR login project

* Update tests

* Add tests

* Delint

* Update comments
This commit is contained in:
Michael Telatynski
2026-04-28 10:24:47 +00:00
committed by GitHub
parent c363d2eb82
commit 5f770bfe4c
8 changed files with 45 additions and 26 deletions
@@ -57,6 +57,6 @@ test.describe("Logout tests", () => {
await locator.getByRole("menuitem", { name: "Remove this device", exact: true }).click(); await locator.getByRole("menuitem", { name: "Remove this device", exact: true }).click();
// Should have logged out directly // Should have logged out directly
await expect(page.getByRole("heading", { name: "Sign in" })).toBeVisible(); await expect(page.getByRole("heading", { name: "Be in your element" })).toBeVisible();
}); });
}); });
+3 -3
View File
@@ -245,7 +245,7 @@ export async function logIntoElementAndVerify(page: Page, credentials: Credentia
} }
/** /**
* Click the "sign out" option in Element, and wait for the login page to load * Click the "sign out" option in Element, and wait for the welcome page to load
* *
* @param page - Playwright `Page` object. * @param page - Playwright `Page` object.
* @param discardKeys - if true, expect a "You'll lose access to your encrypted messages" dialog, and dismiss it. * @param discardKeys - if true, expect a "You'll lose access to your encrypted messages" dialog, and dismiss it.
@@ -259,8 +259,8 @@ export async function logOutOfElement(page: Page, discardKeys: boolean = false)
await page.locator(".mx_Dialog .mx_QuestionDialog").getByRole("button", { name: "Remove this device" }).click(); await page.locator(".mx_Dialog .mx_QuestionDialog").getByRole("button", { name: "Remove this device" }).click();
} }
// Wait for the login page to load // Wait for the welcome page to load
await page.getByRole("heading", { name: "Sign in" }).click(); await expect(page.getByRole("heading", { name: "Be in your element" })).toBeVisible();
} }
/** /**
@@ -334,7 +334,7 @@ test.describe("Login", () => {
}); });
test.describe("logout", () => { test.describe("logout", () => {
test("should go to login page on logout", async ({ page, user }) => { test("should go to welcome page on logout", async ({ page, user }) => {
await page.getByRole("button", { name: "User menu" }).click(); await page.getByRole("button", { name: "User menu" }).click();
await expect(page.getByText(user.displayName, { exact: true })).toBeVisible(); await expect(page.getByText(user.displayName, { exact: true })).toBeVisible();
@@ -345,7 +345,7 @@ test.describe("Login", () => {
.locator(".mx_UserMenu_contextMenu") .locator(".mx_UserMenu_contextMenu")
.getByRole("menuitem", { name: "Remove this device" }) .getByRole("menuitem", { name: "Remove this device" })
.click(); .click();
await expect(page).toHaveURL(/\/#\/login$/); await expect(page).toHaveURL(/\/#\/welcome$/);
}); });
}); });
}); });
@@ -123,7 +123,7 @@ test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
// Allow the outstanding requests queue to settle before logging out // Allow the outstanding requests queue to settle before logging out
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
await page.locator(".mx_UserMenu_contextMenu").getByRole("menuitem", { name: "Remove this device" }).click(); await page.locator(".mx_UserMenu_contextMenu").getByRole("menuitem", { name: "Remove this device" }).click();
await expect(page).toHaveURL(/\/#\/login$/); await expect(page).toHaveURL(/\/#\/welcome$/);
// Log in again // Log in again
await page.goto("/#/login"); await page.goto("/#/login");
@@ -159,7 +159,7 @@ test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
.locator(".mx_UserMenu_contextMenu") .locator(".mx_UserMenu_contextMenu")
.getByRole("menuitem", { name: "Remove this device" }) .getByRole("menuitem", { name: "Remove this device" })
.click(); .click();
await expect(page).toHaveURL(/\/#\/login$/); await expect(page).toHaveURL(/\/#\/welcome$/);
// Log in again // Log in again
await page.goto("/#/login"); await page.goto("/#/login");
@@ -209,7 +209,7 @@ test.describe("OIDC Native", { tag: ["@no-firefox", "@no-webkit"] }, () => {
.locator(".mx_UserMenu_contextMenu") .locator(".mx_UserMenu_contextMenu")
.getByRole("menuitem", { name: "Remove this device" }) .getByRole("menuitem", { name: "Remove this device" })
.click(); .click();
await expect(page).toHaveURL(/\/#\/login$/); await expect(page).toHaveURL(/\/#\/welcome$/);
// Log in again // Log in again
await page.goto("/#/login"); await page.goto("/#/login");
+1 -1
View File
@@ -1133,7 +1133,7 @@ export async function onLoggedOut(): Promise<void> {
// customisations got the memo. // customisations got the memo.
if (SdkConfig.get().logout_redirect_url) { if (SdkConfig.get().logout_redirect_url) {
logger.log("Redirecting to external provider to finish logout"); logger.log("Redirecting to external provider to finish logout");
// XXX: Defer this so that it doesn't race with MatrixChat unmounting the world by going to /#/login // XXX: Defer this so that it doesn't race with MatrixChat unmounting the world by going to /#/welcome
window.setTimeout(() => { window.setTimeout(() => {
window.location.href = SdkConfig.get().logout_redirect_url!; window.location.href = SdkConfig.get().logout_redirect_url!;
}, 100); }, 100);
+9 -9
View File
@@ -25,15 +25,15 @@ Please see LICENSE files in the repository root for full details.
* *
* No previous session * No previous session
* *
* (from all other states * (from all other states Client logged out
* except LOCK_STOLEN) WELCOME * except LOCK_STOLEN) WELCOME
* *
* Client logged out *
* *
* "Sign in" "Create account" * "Sign in" "Create account"
* *
* *
* "Forgot ▼ "Create an * "Forgot ▼ "Create an
* password" ┌─────────────────┐ account" * password" ┌─────────────────┐ account"
* FORGOT_PASSWORD LOGIN REGISTER * FORGOT_PASSWORD LOGIN REGISTER
* *
@@ -422,7 +422,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
this.onShowPostLoginScreen(); this.onShowPostLoginScreen();
} }
const promisesList: Promise<any>[] = [this.firstSyncPromise.promise]; const promisesList: Promise<unknown>[] = [this.firstSyncPromise.promise];
let crossSigningIsSetUp = false; let crossSigningIsSetUp = false;
if (cryptoEnabled) { if (cryptoEnabled) {
// check if the user has previously published public cross-signing keys, // check if the user has previously published public cross-signing keys,
@@ -1101,17 +1101,18 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
} }
} }
private viewWelcome(): void { private viewWelcome(otherState?: Partial<IState>): void {
if (shouldUseLoginForWelcome(SdkConfig.get())) { if (shouldUseLoginForWelcome(SdkConfig.get())) {
return this.viewLogin(); return this.viewLogin(otherState);
} }
this.setStateForNewView({ this.setStateForNewView({
view: Views.WELCOME, view: Views.WELCOME,
...otherState,
}); });
this.notifyNewScreen("welcome"); this.notifyNewScreen("welcome");
} }
private viewLogin(otherState?: any): void { private viewLogin(otherState?: Partial<IState>): void {
this.setStateForNewView({ this.setStateForNewView({
view: Views.LOGIN, view: Views.LOGIN,
...otherState, ...otherState,
@@ -1555,7 +1556,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
* Called when the session is logged out * Called when the session is logged out
*/ */
private onLoggedOut(): void { private onLoggedOut(): void {
this.viewLogin({ this.viewWelcome({
ready: false, ready: false,
collapseLhs: false, collapseLhs: false,
currentRoomId: null, currentRoomId: null,
@@ -588,8 +588,10 @@ describe("<MatrixChat />", () => {
}); });
}); });
const getComponentAndWaitForReady = async (): Promise<RenderResult> => { const getComponentAndWaitForReady = async (
const renderResult = getComponent(); props: Partial<ComponentProps<typeof MatrixChat>> = {},
): Promise<RenderResult> => {
const renderResult = getComponent(props);
// we think we are logged in, but are still waiting for the /sync to complete // we think we are logged in, but are still waiting for the /sync to complete
await screen.findByText("Logout"); await screen.findByText("Logout");
@@ -1023,6 +1025,22 @@ describe("<MatrixChat />", () => {
expect(PlatformPeg.get()!.destroyPickleKey).toHaveBeenCalledWith(userId, deviceId); expect(PlatformPeg.get()!.destroyPickleKey).toHaveBeenCalledWith(userId, deviceId);
}); });
it("should go to welcome", async () => {
await getComponentAndWaitForReady();
await dispatchLogoutAndWait();
expect(defaultProps.onNewScreen).toHaveBeenLastCalledWith("welcome", false);
});
it("should go to login if welcome disabled", async () => {
await getComponentAndWaitForReady({
config: { ...defaultProps.config, embedded_pages: { login_for_welcome: true } },
});
await dispatchLogoutAndWait();
expect(defaultProps.onNewScreen).toHaveBeenLastCalledWith("login", false);
});
describe("without delegated auth", () => { describe("without delegated auth", () => {
it("should call /logout", async () => { it("should call /logout", async () => {
await getComponentAndWaitForReady(); await getComponentAndWaitForReady();