Merge remote-tracking branch 'origin/develop' into poll-votes
This commit is contained in:
commit
e55c9a1a5b
229 changed files with 1745 additions and 1578 deletions
|
@ -39,6 +39,7 @@ jest.mock("matrix-js-sdk/src/logger");
|
|||
jest.mock("../../src/dispatcher/dispatcher", () => ({
|
||||
dispatch: jest.fn(),
|
||||
register: jest.fn(),
|
||||
unregister: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../../src/SecurityManager", () => ({
|
||||
|
|
|
@ -62,6 +62,7 @@ import { DRAFT_LAST_CLEANUP_KEY } from "../../../../src/DraftCleaner";
|
|||
import { UIFeature } from "../../../../src/settings/UIFeature";
|
||||
import AutoDiscoveryUtils from "../../../../src/utils/AutoDiscoveryUtils";
|
||||
import { ValidatedServerConfig } from "../../../../src/utils/ValidatedServerConfig";
|
||||
import Modal from "../../../../src/Modal.tsx";
|
||||
|
||||
jest.mock("matrix-js-sdk/src/oidc/authorize", () => ({
|
||||
completeAuthorizationCodeGrant: jest.fn(),
|
||||
|
@ -952,7 +953,7 @@ describe("<MatrixChat />", () => {
|
|||
const getComponentAndWaitForReady = async (): Promise<RenderResult> => {
|
||||
const renderResult = getComponent();
|
||||
// wait for welcome page chrome render
|
||||
await screen.findByText("powered by Matrix");
|
||||
await screen.findByText("Powered by Matrix");
|
||||
|
||||
// go to login page
|
||||
defaultDispatcher.dispatch({
|
||||
|
@ -1479,7 +1480,7 @@ describe("<MatrixChat />", () => {
|
|||
const getComponentAndWaitForReady = async (): Promise<RenderResult> => {
|
||||
const renderResult = getComponent();
|
||||
// wait for welcome page chrome render
|
||||
await screen.findByText("powered by Matrix");
|
||||
await screen.findByText("Powered by Matrix");
|
||||
|
||||
// go to mobile_register page
|
||||
defaultDispatcher.dispatch({
|
||||
|
@ -1499,7 +1500,7 @@ describe("<MatrixChat />", () => {
|
|||
it("should render welcome screen if mobile registration is not enabled in settings", async () => {
|
||||
await getComponentAndWaitForReady();
|
||||
|
||||
await screen.findByText("powered by Matrix");
|
||||
await screen.findByText("Powered by Matrix");
|
||||
});
|
||||
|
||||
it("should render mobile registration", async () => {
|
||||
|
@ -1514,7 +1515,9 @@ describe("<MatrixChat />", () => {
|
|||
|
||||
describe("when key backup failed", () => {
|
||||
it("should show the new recovery method dialog", async () => {
|
||||
const spy = jest.spyOn(Modal, "createDialogAsync");
|
||||
jest.mock("../../../../src/async-components/views/dialogs/security/NewRecoveryMethodDialog", () => ({
|
||||
__test: true,
|
||||
__esModule: true,
|
||||
default: () => <span>mocked dialog</span>,
|
||||
}));
|
||||
|
@ -1526,7 +1529,8 @@ describe("<MatrixChat />", () => {
|
|||
});
|
||||
await flushPromises();
|
||||
mockClient.emit(CryptoEvent.KeyBackupFailed, "error code");
|
||||
await waitFor(() => expect(screen.getByText("mocked dialog")).toBeInTheDocument());
|
||||
await waitFor(() => expect(spy).toHaveBeenCalledTimes(1));
|
||||
expect(await spy.mock.lastCall![0]).toEqual(expect.objectContaining({ __test: true }));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -114,46 +114,56 @@ exports[`<MatrixChat /> Multi-tab lockout waits for other tab to stop during sta
|
|||
>
|
||||
<div
|
||||
class="mx_AuthPage_modal"
|
||||
style="position: relative;"
|
||||
>
|
||||
<div
|
||||
class="mx_Welcome"
|
||||
data-testid="mx_welcome_screen"
|
||||
class="mx_AuthPage_modalBlur"
|
||||
style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; filter: blur(40px);"
|
||||
/>
|
||||
<div
|
||||
class="mx_AuthPage_modalContent"
|
||||
style="display: flex; z-index: 1; background: rgba(255, 255, 255, 0.59); border-radius: 8px;"
|
||||
>
|
||||
<div
|
||||
class="mx_WelcomePage mx_WelcomePage_loggedIn"
|
||||
class="mx_Welcome"
|
||||
data-testid="mx_welcome_screen"
|
||||
>
|
||||
<div
|
||||
class="mx_WelcomePage_body"
|
||||
>
|
||||
<h1>
|
||||
Hello
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dropdown mx_LanguageDropdown mx_AuthBody_language"
|
||||
>
|
||||
<div
|
||||
aria-describedby="mx_LanguageDropdown_value"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-label="Language Dropdown"
|
||||
aria-owns="mx_LanguageDropdown_input"
|
||||
class="mx_AccessibleButton mx_Dropdown_input mx_no_textinput"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="mx_WelcomePage mx_WelcomePage_loggedIn"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown_option"
|
||||
id="mx_LanguageDropdown_value"
|
||||
class="mx_WelcomePage_body"
|
||||
>
|
||||
<div>
|
||||
English
|
||||
</div>
|
||||
<h1>
|
||||
Hello
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Dropdown mx_LanguageDropdown mx_AuthBody_language"
|
||||
>
|
||||
<div
|
||||
aria-describedby="mx_LanguageDropdown_value"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-label="Language Dropdown"
|
||||
aria-owns="mx_LanguageDropdown_input"
|
||||
class="mx_AccessibleButton mx_Dropdown_input mx_no_textinput"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown_option"
|
||||
id="mx_LanguageDropdown_value"
|
||||
>
|
||||
<div>
|
||||
English
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="mx_Dropdown_arrow"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
class="mx_Dropdown_arrow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -162,12 +172,33 @@ exports[`<MatrixChat /> Multi-tab lockout waits for other tab to stop during sta
|
|||
class="mx_AuthFooter"
|
||||
role="contentinfo"
|
||||
>
|
||||
<a
|
||||
href="https://element.io/blog"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
Blog
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com/element_hq"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/element-hq/element-web"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<a
|
||||
href="https://matrix.org"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
powered by Matrix
|
||||
Powered by Matrix
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
|
@ -201,116 +232,150 @@ exports[`<MatrixChat /> with a soft-logged-out session should show the soft-logo
|
|||
>
|
||||
<div
|
||||
class="mx_AuthPage_modal"
|
||||
style="position: relative;"
|
||||
>
|
||||
<div
|
||||
class="mx_AuthHeader"
|
||||
class="mx_AuthPage_modalBlur"
|
||||
style="position: absolute; top: 0px; right: 0px; bottom: 0px; left: 0px; filter: blur(40px);"
|
||||
/>
|
||||
<div
|
||||
class="mx_AuthPage_modalContent"
|
||||
style="display: flex; z-index: 1; background: rgba(255, 255, 255, 0.59); border-radius: 8px;"
|
||||
>
|
||||
<aside
|
||||
class="mx_AuthHeaderLogo"
|
||||
>
|
||||
Matrix
|
||||
</aside>
|
||||
<div
|
||||
class="mx_Dropdown mx_LanguageDropdown mx_AuthBody_language"
|
||||
class="mx_AuthHeader"
|
||||
>
|
||||
<div
|
||||
aria-describedby="mx_LanguageDropdown_value"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-label="Language Dropdown"
|
||||
aria-owns="mx_LanguageDropdown_input"
|
||||
class="mx_AccessibleButton mx_Dropdown_input mx_no_textinput"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
<aside
|
||||
class="mx_AuthHeaderLogo"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown_option"
|
||||
id="mx_LanguageDropdown_value"
|
||||
>
|
||||
<div>
|
||||
English
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="mx_Dropdown_arrow"
|
||||
<img
|
||||
alt="Element"
|
||||
src="themes/element/img/logos/element-logo.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<main
|
||||
class="mx_AuthBody"
|
||||
>
|
||||
<h1>
|
||||
You're signed out
|
||||
</h1>
|
||||
<h2>
|
||||
Sign in
|
||||
</h2>
|
||||
<div>
|
||||
<form>
|
||||
<p>
|
||||
Enter your password to sign in and regain access to your account.
|
||||
</p>
|
||||
<div
|
||||
class="mx_Field mx_Field_input"
|
||||
>
|
||||
<input
|
||||
id="mx_Field_1"
|
||||
label="Password"
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="mx_Field_1"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
type="submit"
|
||||
>
|
||||
Sign in
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Forgotten your password?
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<h2>
|
||||
Clear personal data
|
||||
</h2>
|
||||
<p>
|
||||
Warning: your personal data (including encryption keys) is still stored in this session. Clear it if you're finished using this session, or want to sign in to another account.
|
||||
</p>
|
||||
<div>
|
||||
</aside>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="mx_Dropdown mx_LanguageDropdown mx_AuthBody_language"
|
||||
>
|
||||
Clear all data
|
||||
<div
|
||||
aria-describedby="mx_LanguageDropdown_value"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-label="Language Dropdown"
|
||||
aria-owns="mx_LanguageDropdown_input"
|
||||
class="mx_AccessibleButton mx_Dropdown_input mx_no_textinput"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown_option"
|
||||
id="mx_LanguageDropdown_value"
|
||||
>
|
||||
<div>
|
||||
English
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="mx_Dropdown_arrow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<main
|
||||
class="mx_AuthBody"
|
||||
>
|
||||
<h1>
|
||||
You're signed out
|
||||
</h1>
|
||||
<h2>
|
||||
Sign in
|
||||
</h2>
|
||||
<div>
|
||||
<form>
|
||||
<p>
|
||||
Enter your password to sign in and regain access to your account.
|
||||
</p>
|
||||
<div
|
||||
class="mx_Field mx_Field_input"
|
||||
>
|
||||
<input
|
||||
id="mx_Field_1"
|
||||
label="Password"
|
||||
placeholder="Password"
|
||||
type="password"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="mx_Field_1"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
type="submit"
|
||||
>
|
||||
Sign in
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Forgotten your password?
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<h2>
|
||||
Clear personal data
|
||||
</h2>
|
||||
<p>
|
||||
Warning: your personal data (including encryption keys) is still stored in this session. Clear it if you're finished using this session, or want to sign in to another account.
|
||||
</p>
|
||||
<div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Clear all data
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<footer
|
||||
class="mx_AuthFooter"
|
||||
role="contentinfo"
|
||||
>
|
||||
<a
|
||||
href="https://element.io/blog"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
Blog
|
||||
</a>
|
||||
<a
|
||||
href="https://twitter.com/element_hq"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/element-hq/element-web"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<a
|
||||
href="https://matrix.org"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
powered by Matrix
|
||||
Powered by Matrix
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||
|
||||
import React from "react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { act, render, RenderResult, screen } from "jest-matrix-react";
|
||||
import { act, render, RenderResult, screen, waitFor } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { MatrixClient, createClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
|
@ -47,14 +47,12 @@ describe("<ForgotPassword>", () => {
|
|||
};
|
||||
|
||||
const click = async (element: Element): Promise<void> => {
|
||||
await act(async () => {
|
||||
await userEvent.click(element, { delay: null });
|
||||
});
|
||||
await userEvent.click(element, { delay: null });
|
||||
};
|
||||
|
||||
const itShouldCloseTheDialogAndShowThePasswordInput = (): void => {
|
||||
it("should close the dialog and show the password input", () => {
|
||||
expect(screen.queryByText("Verify your email to continue")).not.toBeInTheDocument();
|
||||
it("should close the dialog and show the password input", async () => {
|
||||
await waitFor(() => expect(screen.queryByText("Verify your email to continue")).not.toBeInTheDocument());
|
||||
expect(screen.getByText("Reset your password")).toBeInTheDocument();
|
||||
});
|
||||
};
|
||||
|
@ -314,7 +312,7 @@ describe("<ForgotPassword>", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("should send the new password and show the click validation link dialog", () => {
|
||||
it("should send the new password and show the click validation link dialog", async () => {
|
||||
expect(client.setPassword).toHaveBeenCalledWith(
|
||||
{
|
||||
type: "m.login.email.identity",
|
||||
|
@ -326,15 +324,15 @@ describe("<ForgotPassword>", () => {
|
|||
testPassword,
|
||||
false,
|
||||
);
|
||||
expect(screen.getByText("Verify your email to continue")).toBeInTheDocument();
|
||||
await expect(
|
||||
screen.findByText("Verify your email to continue"),
|
||||
).resolves.toBeInTheDocument();
|
||||
expect(screen.getByText(testEmail)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("and dismissing the dialog by clicking the background", () => {
|
||||
beforeEach(async () => {
|
||||
await act(async () => {
|
||||
await userEvent.click(screen.getByTestId("dialog-background"), { delay: null });
|
||||
});
|
||||
await userEvent.click(await screen.findByTestId("dialog-background"), { delay: null });
|
||||
await waitEnoughCyclesForModal({
|
||||
useFakeTimers: true,
|
||||
});
|
||||
|
@ -345,7 +343,7 @@ describe("<ForgotPassword>", () => {
|
|||
|
||||
describe("and dismissing the dialog", () => {
|
||||
beforeEach(async () => {
|
||||
await click(screen.getByLabelText("Close dialog"));
|
||||
await click(await screen.findByLabelText("Close dialog"));
|
||||
await waitEnoughCyclesForModal({
|
||||
useFakeTimers: true,
|
||||
});
|
||||
|
@ -356,14 +354,16 @@ describe("<ForgotPassword>", () => {
|
|||
|
||||
describe("and clicking »Re-enter email address«", () => {
|
||||
beforeEach(async () => {
|
||||
await click(screen.getByText("Re-enter email address"));
|
||||
await click(await screen.findByText("Re-enter email address"));
|
||||
await waitEnoughCyclesForModal({
|
||||
useFakeTimers: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("should close the dialog and go back to the email input", () => {
|
||||
expect(screen.queryByText("Verify your email to continue")).not.toBeInTheDocument();
|
||||
it("should close the dialog and go back to the email input", async () => {
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByText("Verify your email to continue")).not.toBeInTheDocument(),
|
||||
);
|
||||
expect(screen.queryByText("Enter your email to reset password")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -397,11 +397,11 @@ describe("<ForgotPassword>", () => {
|
|||
});
|
||||
|
||||
it("should show the sign out warning dialog", async () => {
|
||||
expect(
|
||||
screen.getByText(
|
||||
await expect(
|
||||
screen.findByText(
|
||||
"Signing out your devices will delete the message encryption keys stored on them, making encrypted chat history unreadable.",
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
).resolves.toBeInTheDocument();
|
||||
|
||||
// confirm dialog
|
||||
await click(screen.getByText("Continue"));
|
||||
|
|
|
@ -9,16 +9,16 @@ Please see LICENSE files in the repository root for full details.
|
|||
import * as React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import VectorAuthPage from "../../../../../src/components/views/auth/VectorAuthPage";
|
||||
import AuthFooter from "../../../../../src/components/views/auth/AuthFooter";
|
||||
import { setupLanguageMock } from "../../../../setup/setupLanguage";
|
||||
|
||||
describe("<VectorAuthPage />", () => {
|
||||
describe("<AuthFooter />", () => {
|
||||
beforeEach(() => {
|
||||
setupLanguageMock();
|
||||
});
|
||||
|
||||
it("should match snapshot", () => {
|
||||
const { asFragment } = render(<VectorAuthPage />);
|
||||
const { asFragment } = render(<AuthFooter />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -9,11 +9,11 @@ Please see LICENSE files in the repository root for full details.
|
|||
import * as React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import VectorAuthHeaderLogo from "../../../../../src/components/views/auth/VectorAuthHeaderLogo";
|
||||
import AuthHeaderLogo from "../../../../../src/components/views/auth/AuthHeaderLogo";
|
||||
|
||||
describe("<VectorAuthHeaderLogo />", () => {
|
||||
describe("<AuthHeaderLogo />", () => {
|
||||
it("should match snapshot", () => {
|
||||
const { asFragment } = render(<VectorAuthHeaderLogo />);
|
||||
const { asFragment } = render(<AuthHeaderLogo />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
36
test/unit-tests/components/views/auth/AuthPage-test.tsx
Normal file
36
test/unit-tests/components/views/auth/AuthPage-test.tsx
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import AuthPage from "../../../../../src/components/views/auth/AuthPage";
|
||||
import { setupLanguageMock } from "../../../../setup/setupLanguage";
|
||||
import SdkConfig from "../../../../../src/SdkConfig.ts";
|
||||
|
||||
describe("<AuthPage />", () => {
|
||||
beforeEach(() => {
|
||||
setupLanguageMock();
|
||||
SdkConfig.reset();
|
||||
// @ts-ignore private access
|
||||
AuthPage.welcomeBackgroundUrl = undefined;
|
||||
});
|
||||
|
||||
it("should match snapshot", () => {
|
||||
const { asFragment } = render(<AuthPage />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should use configured background url", () => {
|
||||
SdkConfig.add({ branding: { welcome_background_url: ["https://example.com/image.png"] } });
|
||||
const { container } = render(<AuthPage />);
|
||||
expect(container.querySelector(".mx_AuthPage")).toHaveStyle({
|
||||
background: "center/cover fixed url(https://example.com/image.png)",
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
|
||||
import VectorAuthFooter from "../../../../../src/components/views/auth/VectorAuthFooter";
|
||||
import { setupLanguageMock } from "../../../../setup/setupLanguage";
|
||||
|
||||
describe("<VectorAuthFooter />", () => {
|
||||
beforeEach(() => {
|
||||
setupLanguageMock();
|
||||
});
|
||||
|
||||
it("should match snapshot", () => {
|
||||
const { asFragment } = render(<VectorAuthFooter />);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<VectorAuthFooter /> should match snapshot 1`] = `
|
||||
exports[`<AuthFooter /> should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<footer
|
||||
class="mx_AuthFooter"
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<VectorAuthHeaderLogo /> should match snapshot 1`] = `
|
||||
exports[`<AuthHeaderLogo /> should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<aside
|
||||
class="mx_AuthHeaderLogo"
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<VectorAuthPage /> should match snapshot 1`] = `
|
||||
exports[`<AuthPage /> should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_AuthPage"
|
|
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||
|
||||
import { Feature, ServerSupport } from "matrix-js-sdk/src/feature";
|
||||
import { MatrixClient, MatrixEvent, RelationType } from "matrix-js-sdk/src/matrix";
|
||||
import { screen } from "jest-matrix-react";
|
||||
import { screen, act } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import { flushPromises, mkEvent, stubClient } from "../../../../test-utils";
|
||||
|
@ -31,12 +31,12 @@ describe("ConfirmRedactDialog", () => {
|
|||
};
|
||||
|
||||
const confirmDeleteVoiceBroadcastStartedEvent = async () => {
|
||||
createRedactEventDialog({ mxEvent });
|
||||
act(() => createRedactEventDialog({ mxEvent }));
|
||||
// double-flush promises required for the dialog to show up
|
||||
await flushPromises();
|
||||
await flushPromises();
|
||||
|
||||
await userEvent.click(screen.getByTestId("dialog-primary-button"));
|
||||
await userEvent.click(await screen.findByTestId("dialog-primary-button"));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -7,13 +7,57 @@
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { render, fireEvent, waitFor } from "jest-matrix-react";
|
||||
import fetchMock from "fetch-mock-jest";
|
||||
|
||||
import ImageView from "../../../../../src/components/views/elements/ImageView";
|
||||
import { FileDownloader } from "../../../../../src/utils/FileDownloader";
|
||||
import Modal from "../../../../../src/Modal";
|
||||
import ErrorDialog from "../../../../../src/components/views/dialogs/ErrorDialog";
|
||||
|
||||
jest.mock("../../../../../src/utils/FileDownloader");
|
||||
|
||||
describe("<ImageView />", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
fetchMock.reset();
|
||||
});
|
||||
|
||||
it("renders correctly", () => {
|
||||
const { container } = render(<ImageView src="https://example.com/image.png" onFinished={jest.fn()} />);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should download on click", async () => {
|
||||
fetchMock.get("https://example.com/image.png", "TESTFILE");
|
||||
const { getByRole } = render(
|
||||
<ImageView src="https://example.com/image.png" name="filename.png" onFinished={jest.fn()} />,
|
||||
);
|
||||
fireEvent.click(getByRole("button", { name: "Download" }));
|
||||
await waitFor(() =>
|
||||
expect(mocked(FileDownloader).mock.instances[0].download).toHaveBeenCalledWith({
|
||||
blob: expect.anything(),
|
||||
name: "filename.png",
|
||||
}),
|
||||
);
|
||||
expect(fetchMock).toHaveFetched("https://example.com/image.png");
|
||||
});
|
||||
|
||||
it("should handle download errors", async () => {
|
||||
const modalSpy = jest.spyOn(Modal, "createDialog");
|
||||
fetchMock.get("https://example.com/image.png", { status: 500 });
|
||||
const { getByRole } = render(
|
||||
<ImageView src="https://example.com/image.png" name="filename.png" onFinished={jest.fn()} />,
|
||||
);
|
||||
fireEvent.click(getByRole("button", { name: "Download" }));
|
||||
await waitFor(() =>
|
||||
expect(modalSpy).toHaveBeenCalledWith(
|
||||
ErrorDialog,
|
||||
expect.objectContaining({
|
||||
title: "Download failed",
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,9 +6,18 @@ exports[`<MapError /> applies class when isMinimised is truthy 1`] = `
|
|||
class="mx_MapError test mx_MapError_isMinimised"
|
||||
data-testid="map-rendering-error"
|
||||
>
|
||||
<div
|
||||
<svg
|
||||
class="mx_MapError_icon"
|
||||
/>
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17a.97.97 0 0 0 .713-.288A.968.968 0 0 0 13 16a.968.968 0 0 0-.287-.713A.968.968 0 0 0 12 15a.968.968 0 0 0-.713.287A.968.968 0 0 0 11 16c0 .283.096.52.287.712.192.192.43.288.713.288Zm0-4c.283 0 .52-.096.713-.287A.968.968 0 0 0 13 12V8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8v4c0 .283.096.52.287.713.192.191.43.287.713.287Zm0 9a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Z"
|
||||
/>
|
||||
</svg>
|
||||
<h3
|
||||
class="mx_Heading_h3 mx_MapError_heading"
|
||||
>
|
||||
|
@ -36,9 +45,18 @@ exports[`<MapError /> renders correctly for MapStyleUrlNotConfigured 1`] = `
|
|||
class="mx_MapError test"
|
||||
data-testid="map-rendering-error"
|
||||
>
|
||||
<div
|
||||
<svg
|
||||
class="mx_MapError_icon"
|
||||
/>
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17a.97.97 0 0 0 .713-.288A.968.968 0 0 0 13 16a.968.968 0 0 0-.287-.713A.968.968 0 0 0 12 15a.968.968 0 0 0-.713.287A.968.968 0 0 0 11 16c0 .283.096.52.287.712.192.192.43.288.713.288Zm0-4c.283 0 .52-.096.713-.287A.968.968 0 0 0 13 12V8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8v4c0 .283.096.52.287.713.192.191.43.287.713.287Zm0 9a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Z"
|
||||
/>
|
||||
</svg>
|
||||
<h3
|
||||
class="mx_Heading_h3 mx_MapError_heading"
|
||||
>
|
||||
|
@ -66,9 +84,18 @@ exports[`<MapError /> renders correctly for MapStyleUrlNotReachable 1`] = `
|
|||
class="mx_MapError test"
|
||||
data-testid="map-rendering-error"
|
||||
>
|
||||
<div
|
||||
<svg
|
||||
class="mx_MapError_icon"
|
||||
/>
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17a.97.97 0 0 0 .713-.288A.968.968 0 0 0 13 16a.968.968 0 0 0-.287-.713A.968.968 0 0 0 12 15a.968.968 0 0 0-.713.287A.968.968 0 0 0 11 16c0 .283.096.52.287.712.192.192.43.288.713.288Zm0-4c.283 0 .52-.096.713-.287A.968.968 0 0 0 13 12V8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8v4c0 .283.096.52.287.713.192.191.43.287.713.287Zm0 9a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Z"
|
||||
/>
|
||||
</svg>
|
||||
<h3
|
||||
class="mx_Heading_h3 mx_MapError_heading"
|
||||
>
|
||||
|
|
|
@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||
|
||||
import React from "react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { fireEvent, render, screen } from "jest-matrix-react";
|
||||
import { fireEvent, render, screen, waitFor } from "jest-matrix-react";
|
||||
import { TimestampToEventResponse, ConnectionError, HTTPError, MatrixError } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import dispatcher from "../../../../../src/dispatcher/dispatcher";
|
||||
|
@ -291,7 +291,9 @@ describe("DateSeparator", () => {
|
|||
// The submit debug logs option should *NOT* be shown for network errors.
|
||||
//
|
||||
// We have to use `queryBy` so that it can return `null` for something that does not exist.
|
||||
expect(screen.queryByTestId("jump-to-date-error-submit-debug-logs-button")).not.toBeInTheDocument();
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByTestId("jump-to-date-error-submit-debug-logs-button")).not.toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -129,6 +129,6 @@ describe("DecryptionFailureBody", () => {
|
|||
const { container } = customRender(event);
|
||||
|
||||
// Then
|
||||
expect(container).toHaveTextContent("Encrypted by a device not verified by its owner");
|
||||
expect(container).toHaveTextContent("Sent from an insecure device");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
|||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { fireEvent, render, RenderResult } from "jest-matrix-react";
|
||||
import { fireEvent, render, RenderResult, waitFor } from "jest-matrix-react";
|
||||
import {
|
||||
M_POLL_KIND_DISCLOSED,
|
||||
M_POLL_KIND_UNDISCLOSED,
|
||||
|
@ -85,7 +85,7 @@ describe("MPollBody", () => {
|
|||
expect(votesCount(renderResult, "poutine")).toBe("");
|
||||
expect(votesCount(renderResult, "italian")).toBe("");
|
||||
expect(votesCount(renderResult, "wings")).toBe("");
|
||||
expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("No votes cast");
|
||||
await waitFor(() => expect(renderResult.getByTestId("totalVotes").innerHTML).toBe("No votes cast"));
|
||||
expect(renderResult.getByText("What should we order for the party?")).toBeTruthy();
|
||||
});
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ exports[`DecryptionFailureBody Should display "Unable to decrypt message" 1`] =
|
|||
exports[`DecryptionFailureBody should handle messages from users who change identities after verification 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_DecryptionFailureBody mx_EventTile_content mx_DecryptionFailureVerifiedIdentityChanged"
|
||||
class="mx_DecryptionFailureBody mx_EventTile_content mx_DecryptionFailureSenderTrustRequirement"
|
||||
>
|
||||
<span>
|
||||
<svg
|
||||
|
@ -35,15 +35,10 @@ exports[`DecryptionFailureBody should handle messages from users who change iden
|
|||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12.713 17.713A.968.968 0 0 1 12 18a.968.968 0 0 1-.713-.287A.967.967 0 0 1 11 17a.97.97 0 0 1 .287-.712A.968.968 0 0 1 12 16a.97.97 0 0 1 .713.288A.968.968 0 0 1 13 17a.97.97 0 0 1-.287.713Zm0-4A.968.968 0 0 1 12 14a.968.968 0 0 1-.713-.287A.967.967 0 0 1 11 13V9a.97.97 0 0 1 .287-.712A.968.968 0 0 1 12 8a.97.97 0 0 1 .713.288A.968.968 0 0 1 13 9v4a.97.97 0 0 1-.287.713Z"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M10.264 3.039c.767-1.344 2.705-1.344 3.472 0l8.554 14.969c.762 1.333-.2 2.992-1.736 2.992H3.446c-1.535 0-2.498-1.659-1.736-2.992l8.553-14.969ZM3.446 19 12 4.031l8.554 14.97H3.446Z"
|
||||
fill-rule="evenodd"
|
||||
d="M12 22a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Zm0-2c2.233 0 4.125-.775 5.675-2.325C19.225 16.125 20 14.233 20 12c0-.9-.146-1.767-.438-2.6A7.951 7.951 0 0 0 18.3 7.1L7.1 18.3c.7.55 1.467.97 2.3 1.262.833.292 1.7.438 2.6.438Zm-6.3-3.1L16.9 5.7a7.95 7.95 0 0 0-2.3-1.263A7.813 7.813 0 0 0 12 4c-2.233 0-4.125.775-5.675 2.325C4.775 7.875 4 9.767 4 12c0 .9.146 1.767.438 2.6A7.95 7.95 0 0 0 5.7 16.9Z"
|
||||
/>
|
||||
</svg>
|
||||
Verified identity has changed
|
||||
Sender's verified identity has changed
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,9 +5,18 @@ exports[`<MBeaconBody /> when map display is not configured renders maps unavail
|
|||
class="mx_MapError mx_MBeaconBody_mapError mx_MBeaconBody_mapErrorInteractive mx_MapError_isMinimised"
|
||||
data-testid="map-rendering-error"
|
||||
>
|
||||
<div
|
||||
<svg
|
||||
class="mx_MapError_icon"
|
||||
/>
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17a.97.97 0 0 0 .713-.288A.968.968 0 0 0 13 16a.968.968 0 0 0-.287-.713A.968.968 0 0 0 12 15a.968.968 0 0 0-.713.287A.968.968 0 0 0 11 16c0 .283.096.52.287.712.192.192.43.288.713.288Zm0-4c.283 0 .52-.096.713-.287A.968.968 0 0 0 13 12V8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8v4c0 .283.096.52.287.713.192.191.43.287.713.287Zm0 9a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Z"
|
||||
/>
|
||||
</svg>
|
||||
<h3
|
||||
class="mx_Heading_h3 mx_MapError_heading"
|
||||
>
|
||||
|
|
|
@ -19,7 +19,13 @@ import {
|
|||
Room,
|
||||
TweakName,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { CryptoApi, EventEncryptionInfo, EventShieldColour, EventShieldReason } from "matrix-js-sdk/src/crypto-api";
|
||||
import {
|
||||
CryptoApi,
|
||||
DecryptionFailureCode,
|
||||
EventEncryptionInfo,
|
||||
EventShieldColour,
|
||||
EventShieldReason,
|
||||
} from "matrix-js-sdk/src/crypto-api";
|
||||
import { mkEncryptedMatrixEvent } from "matrix-js-sdk/src/testing";
|
||||
|
||||
import EventTile, { EventTileProps } from "../../../../../src/components/views/rooms/EventTile";
|
||||
|
@ -350,6 +356,32 @@ describe("EventTile", () => {
|
|||
"mx_EventTile_e2eIcon_decryption_failure",
|
||||
);
|
||||
});
|
||||
|
||||
it("should not show a shield for previously-verified users", async () => {
|
||||
mxEvent = mkEvent({
|
||||
type: "m.room.encrypted",
|
||||
room: room.roomId,
|
||||
user: "@alice:example.org",
|
||||
event: true,
|
||||
content: {},
|
||||
});
|
||||
|
||||
const mockCrypto = {
|
||||
decryptEvent: async (_ev): Promise<IEventDecryptionResult> => {
|
||||
throw new Error("can't decrypt");
|
||||
},
|
||||
} as Parameters<MatrixEvent["attemptDecryption"]>[0];
|
||||
await mxEvent.attemptDecryption(mockCrypto);
|
||||
mxEvent["_decryptionFailureReason"] = DecryptionFailureCode.SENDER_IDENTITY_PREVIOUSLY_VERIFIED;
|
||||
|
||||
const { container } = getComponent();
|
||||
await act(flushPromises);
|
||||
|
||||
const eventTiles = container.getElementsByClassName("mx_EventTile");
|
||||
expect(eventTiles).toHaveLength(1);
|
||||
|
||||
expect(container.getElementsByClassName("mx_EventTile_e2eIcon")).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
it("should update the warning when the event is edited", async () => {
|
||||
|
|
|
@ -14,7 +14,7 @@ import userEvent from "@testing-library/user-event";
|
|||
import * as pinnedEventHooks from "../../../../../src/hooks/usePinnedEvents";
|
||||
import { PinnedMessageBanner } from "../../../../../src/components/views/rooms/PinnedMessageBanner";
|
||||
import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks";
|
||||
import { makePollStartEvent, stubClient } from "../../../../test-utils";
|
||||
import { makePollStartEvent, stubClient, withClientContextRenderOptions } from "../../../../test-utils";
|
||||
import dis from "../../../../../src/dispatcher/dispatcher";
|
||||
import RightPanelStore from "../../../../../src/stores/right-panel/RightPanelStore";
|
||||
import { RightPanelPhases } from "../../../../../src/stores/right-panel/RightPanelStorePhases";
|
||||
|
@ -76,7 +76,10 @@ describe("<PinnedMessageBanner />", () => {
|
|||
* Render the banner
|
||||
*/
|
||||
function renderBanner() {
|
||||
return render(<PinnedMessageBanner permalinkCreator={permalinkCreator} room={room} />);
|
||||
return render(
|
||||
<PinnedMessageBanner permalinkCreator={permalinkCreator} room={room} />,
|
||||
withClientContextRenderOptions(mockClient),
|
||||
);
|
||||
}
|
||||
|
||||
it("should render nothing when there are no pinned events", async () => {
|
||||
|
@ -92,7 +95,7 @@ describe("<PinnedMessageBanner />", () => {
|
|||
|
||||
const { asFragment } = renderBanner();
|
||||
|
||||
expect(screen.getByText("First pinned message")).toBeVisible();
|
||||
await expect(screen.findByText("First pinned message")).resolves.toBeVisible();
|
||||
expect(screen.queryByRole("button", { name: "View all" })).toBeNull();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
@ -103,7 +106,7 @@ describe("<PinnedMessageBanner />", () => {
|
|||
|
||||
const { asFragment } = renderBanner();
|
||||
|
||||
expect(screen.getByText("Second pinned message")).toBeVisible();
|
||||
await expect(screen.findByText("Second pinned message")).resolves.toBeVisible();
|
||||
expect(screen.getByTestId("banner-counter")).toHaveTextContent("2 of 2 Pinned messages");
|
||||
expect(screen.getAllByTestId("banner-indicator")).toHaveLength(2);
|
||||
expect(screen.queryByRole("button", { name: "View all" })).toBeVisible();
|
||||
|
@ -121,7 +124,7 @@ describe("<PinnedMessageBanner />", () => {
|
|||
|
||||
const { asFragment } = renderBanner();
|
||||
|
||||
expect(screen.getByText("Fourth pinned message")).toBeVisible();
|
||||
await expect(screen.findByText("Fourth pinned message")).resolves.toBeVisible();
|
||||
expect(screen.getByTestId("banner-counter")).toHaveTextContent("4 of 4 Pinned messages");
|
||||
expect(screen.getAllByTestId("banner-indicator")).toHaveLength(3);
|
||||
expect(screen.queryByRole("button", { name: "View all" })).toBeVisible();
|
||||
|
@ -143,7 +146,7 @@ describe("<PinnedMessageBanner />", () => {
|
|||
]);
|
||||
jest.spyOn(pinnedEventHooks, "useSortedFetchedPinnedEvents").mockReturnValue([event1, event2, event3]);
|
||||
rerender(<PinnedMessageBanner permalinkCreator={permalinkCreator} room={room} />);
|
||||
expect(screen.getByText("Third pinned message")).toBeVisible();
|
||||
await expect(screen.findByText("Third pinned message")).resolves.toBeVisible();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -152,7 +155,7 @@ describe("<PinnedMessageBanner />", () => {
|
|||
jest.spyOn(pinnedEventHooks, "useSortedFetchedPinnedEvents").mockReturnValue([event1, event2]);
|
||||
|
||||
renderBanner();
|
||||
expect(screen.getByText("Second pinned message")).toBeVisible();
|
||||
await expect(screen.findByText("Second pinned message")).resolves.toBeVisible();
|
||||
|
||||
await userEvent.click(screen.getByRole("button", { name: "View the pinned message in the timeline." }));
|
||||
expect(screen.getByText("First pinned message")).toBeVisible();
|
||||
|
@ -182,14 +185,14 @@ describe("<PinnedMessageBanner />", () => {
|
|||
["m.audio", "Audio"],
|
||||
["m.video", "Video"],
|
||||
["m.image", "Image"],
|
||||
])("should display the %s event type", (msgType, label) => {
|
||||
])("should display the %s event type", async (msgType, label) => {
|
||||
const body = `Message with ${msgType} type`;
|
||||
const event = makePinEvent({ content: { body, msgtype: msgType } });
|
||||
jest.spyOn(pinnedEventHooks, "usePinnedEvents").mockReturnValue([event.getId()!]);
|
||||
jest.spyOn(pinnedEventHooks, "useSortedFetchedPinnedEvents").mockReturnValue([event]);
|
||||
|
||||
const { asFragment } = renderBanner();
|
||||
expect(screen.getByTestId("banner-message")).toHaveTextContent(`${label}: ${body}`);
|
||||
await expect(screen.findByTestId("banner-message")).resolves.toHaveTextContent(`${label}: ${body}`);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -199,7 +202,7 @@ describe("<PinnedMessageBanner />", () => {
|
|||
jest.spyOn(pinnedEventHooks, "useSortedFetchedPinnedEvents").mockReturnValue([event]);
|
||||
|
||||
const { asFragment } = renderBanner();
|
||||
expect(screen.getByTestId("banner-message")).toHaveTextContent("Poll: Alice?");
|
||||
await expect(screen.findByTestId("banner-message")).resolves.toHaveTextContent("Poll: Alice?");
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ exports[`<PinnedMessageBanner /> should display display a poll event 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_prefix"
|
||||
class="mx_EventPreview_prefix"
|
||||
>
|
||||
Poll:
|
||||
</span>
|
||||
|
@ -113,8 +113,9 @@ exports[`<PinnedMessageBanner /> should display the last message when the pinned
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
title="Third pinned message"
|
||||
>
|
||||
Third pinned message
|
||||
</span>
|
||||
|
@ -170,12 +171,12 @@ exports[`<PinnedMessageBanner /> should display the m.audio event type 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_prefix"
|
||||
class="mx_EventPreview_prefix"
|
||||
>
|
||||
Audio:
|
||||
</span>
|
||||
|
@ -225,12 +226,12 @@ exports[`<PinnedMessageBanner /> should display the m.file event type 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_prefix"
|
||||
class="mx_EventPreview_prefix"
|
||||
>
|
||||
File:
|
||||
</span>
|
||||
|
@ -280,12 +281,12 @@ exports[`<PinnedMessageBanner /> should display the m.image event type 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_prefix"
|
||||
class="mx_EventPreview_prefix"
|
||||
>
|
||||
Image:
|
||||
</span>
|
||||
|
@ -335,12 +336,12 @@ exports[`<PinnedMessageBanner /> should display the m.video event type 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_prefix"
|
||||
class="mx_EventPreview_prefix"
|
||||
>
|
||||
Video:
|
||||
</span>
|
||||
|
@ -407,8 +408,9 @@ exports[`<PinnedMessageBanner /> should render 2 pinned event 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
title="Second pinned message"
|
||||
>
|
||||
Second pinned message
|
||||
</span>
|
||||
|
@ -485,8 +487,9 @@ exports[`<PinnedMessageBanner /> should render 4 pinned event 1`] = `
|
|||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
title="Fourth pinned message"
|
||||
>
|
||||
Fourth pinned message
|
||||
</span>
|
||||
|
@ -542,8 +545,9 @@ exports[`<PinnedMessageBanner /> should render a single pinned event 1`] = `
|
|||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PinnedMessageBanner_message"
|
||||
class="mx_EventPreview mx_PinnedMessageBanner_message"
|
||||
data-testid="banner-message"
|
||||
title="First pinned message"
|
||||
>
|
||||
First pinned message
|
||||
</span>
|
||||
|
|
|
@ -417,7 +417,7 @@ describe("message", () => {
|
|||
expect(mockClient.sendMessage).toHaveBeenCalledTimes(0);
|
||||
expect(mockClient.cancelPendingEvent).toHaveBeenCalledTimes(1);
|
||||
expect(mockCreateRedactEventDialog).toHaveBeenCalledTimes(1);
|
||||
expect(spyDispatcher).toHaveBeenCalledTimes(0);
|
||||
expect(spyDispatcher).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("Should do nothing if the content is unmodified", async () => {
|
||||
|
|
|
@ -14,6 +14,7 @@ import { mocked } from "jest-mock";
|
|||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||
import * as TestUtils from "../../../../test-utils";
|
||||
import CryptographyPanel from "../../../../../src/components/views/settings/CryptographyPanel";
|
||||
import { withClientContextRenderOptions } from "../../../../test-utils";
|
||||
|
||||
describe("CryptographyPanel", () => {
|
||||
it("shows the session ID and key", async () => {
|
||||
|
@ -28,7 +29,7 @@ describe("CryptographyPanel", () => {
|
|||
mocked(client.getCrypto()!.getOwnDeviceKeys).mockResolvedValue({ ed25519: sessionKey, curve25519: "1234" });
|
||||
|
||||
// When we render the CryptographyPanel
|
||||
const rendered = render(<CryptographyPanel />);
|
||||
const rendered = render(<CryptographyPanel />, withClientContextRenderOptions(client));
|
||||
|
||||
// Then it displays info about the user's session
|
||||
const codes = rendered.container.querySelectorAll("code");
|
||||
|
@ -52,7 +53,7 @@ describe("CryptographyPanel", () => {
|
|||
mocked(client.getCrypto()!.getOwnDeviceKeys).mockRejectedValue(new Error("bleh"));
|
||||
|
||||
// When we render the CryptographyPanel
|
||||
const rendered = render(<CryptographyPanel />);
|
||||
const rendered = render(<CryptographyPanel />, withClientContextRenderOptions(client));
|
||||
|
||||
// Then it displays info about the user's session
|
||||
const codes = rendered.container.querySelectorAll("code");
|
||||
|
|
|
@ -59,7 +59,7 @@ describe("<JoinRuleSettings />", () => {
|
|||
onError: jest.fn(),
|
||||
};
|
||||
const getComponent = (props: Partial<JoinRuleSettingsProps> = {}) =>
|
||||
render(<JoinRuleSettings {...defaultProps} {...props} />);
|
||||
render(<JoinRuleSettings {...defaultProps} {...props} />, { legacyRoot: false });
|
||||
|
||||
const setRoomStateEvents = (
|
||||
room: Room,
|
||||
|
@ -202,7 +202,7 @@ describe("<JoinRuleSettings />", () => {
|
|||
|
||||
await flushPromises();
|
||||
|
||||
expect(within(dialog).getByText("Loading new room")).toBeInTheDocument();
|
||||
await expect(within(dialog).findByText("Loading new room")).resolves.toBeInTheDocument();
|
||||
|
||||
// "create" our new room, have it come thru sync
|
||||
client.getRoom.mockImplementation((id) => {
|
||||
|
@ -250,7 +250,7 @@ describe("<JoinRuleSettings />", () => {
|
|||
|
||||
await flushPromises();
|
||||
|
||||
expect(within(dialog).getByText("Loading new room")).toBeInTheDocument();
|
||||
await expect(within(dialog).findByText("Loading new room")).resolves.toBeInTheDocument();
|
||||
|
||||
// "create" our new room, have it come thru sync
|
||||
client.getRoom.mockImplementation((id) => {
|
||||
|
|
|
@ -130,10 +130,8 @@ describe("<SecureBackupPanel />", () => {
|
|||
})
|
||||
.mockResolvedValue(null);
|
||||
getComponent();
|
||||
// flush checkKeyBackup promise
|
||||
await flushPromises();
|
||||
|
||||
fireEvent.click(screen.getByText("Delete Backup"));
|
||||
fireEvent.click(await screen.findByText("Delete Backup"));
|
||||
|
||||
const dialog = await screen.findByRole("dialog");
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@ describe("<SessionManagerTab />", () => {
|
|||
const mockVerificationRequest = {
|
||||
cancel: jest.fn(),
|
||||
on: jest.fn(),
|
||||
off: jest.fn(),
|
||||
} as unknown as VerificationRequest;
|
||||
|
||||
const mockCrypto = mocked({
|
||||
|
|
|
@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
|||
import { mocked } from "jest-mock";
|
||||
|
||||
import EditorModel from "../../../src/editor/model";
|
||||
import { htmlSerializeIfNeeded } from "../../../src/editor/serialize";
|
||||
import { htmlSerializeFromMdIfNeeded, htmlSerializeIfNeeded } from "../../../src/editor/serialize";
|
||||
import { createPartCreator } from "./mock";
|
||||
import { IConfigOptions } from "../../../src/IConfigOptions";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
|
@ -71,6 +71,12 @@ describe("editor/serialize", function () {
|
|||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("*hello* world");
|
||||
});
|
||||
it("escaped markdown should not retain backslashes around other markdown", function () {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain("\\*hello\\* **world**")], pc);
|
||||
const html = htmlSerializeIfNeeded(model, {});
|
||||
expect(html).toBe("*hello* <strong>world</strong>");
|
||||
});
|
||||
it("escaped markdown should convert HTML entities", function () {
|
||||
const pc = createPartCreator();
|
||||
const model = new EditorModel([pc.plain("\\*hello\\* world < hey world!")], pc);
|
||||
|
@ -153,6 +159,14 @@ describe("editor/serialize", function () {
|
|||
const html = htmlSerializeIfNeeded(model, { forceHTML: true, useMarkdown: false });
|
||||
expect(html).toBe("hello world");
|
||||
});
|
||||
it("should treat tags not in allowlist as plaintext", () => {
|
||||
const html = htmlSerializeFromMdIfNeeded("<b>test</b>", {});
|
||||
expect(html).toBeUndefined();
|
||||
});
|
||||
it("should treat tags not in allowlist as plaintext even if escaped", () => {
|
||||
const html = htmlSerializeFromMdIfNeeded("\\<b>test</b>", {});
|
||||
expect(html).toBe("<b>test</b>");
|
||||
});
|
||||
});
|
||||
|
||||
describe("feature_latex_maths", () => {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 460 B |
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="19px" height="19px" viewBox="0 0 19 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: sketchtool 39.1 (31720) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>ED5D3E59-2561-4AC1-9B43-82FBC51767FC</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<defs></defs>
|
||||
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="icon_context">
|
||||
<g>
|
||||
<path d="M9.5,19 C14.7467051,19 19,14.7467051 19,9.5 C19,4.25329488 14.7467051,0 9.5,0 C4.25329488,0 0,4.25329488 0,9.5 C0,14.7467051 4.25329488,19 9.5,19 Z" id="Oval-69" fill="#ECECEC"></path>
|
||||
<path d="M4.5,9.50063771 C4.5,9.13148623 4.59887838,8.85242947 4.7966381,8.66345907 C4.99439782,8.47448867 5.28224377,8.38000488 5.66018457,8.38000488 C6.0249414,8.38000488 6.3072941,8.47668596 6.50725115,8.67005103 C6.70720821,8.86341609 6.80718523,9.14027555 6.80718523,9.50063771 C6.80718523,9.84781589 6.70610956,10.1213794 6.50395517,10.3213365 C6.30180079,10.5212935 6.02054674,10.6212705 5.66018457,10.6212705 C5.29103309,10.6212705 5.00538444,10.5234908 4.80323006,10.3279284 C4.60107568,10.132366 4.5,9.85660521 4.5,9.50063771 L4.5,9.50063771 Z M8.3431114,9.50063771 C8.3431114,9.13148623 8.44198978,8.85242947 8.63974951,8.66345907 C8.83750923,8.47448867 9.12755247,8.38000488 9.50988794,8.38000488 C9.87464476,8.38000488 10.1569975,8.47668596 10.3569545,8.67005103 C10.5569116,8.86341609 10.6568886,9.14027555 10.6568886,9.50063771 C10.6568886,9.84781589 10.5558129,10.1213794 10.3536585,10.3213365 C10.1515042,10.5212935 9.8702501,10.6212705 9.50988794,10.6212705 C9.13634179,10.6212705 8.84849585,10.5234908 8.64634146,10.3279284 C8.44418708,10.132366 8.3431114,9.85660521 8.3431114,9.50063771 L8.3431114,9.50063771 Z M12.1928148,9.50063771 C12.1928148,9.13148623 12.2916931,8.85242947 12.4894529,8.66345907 C12.6872126,8.47448867 12.9750585,8.38000488 13.3529993,8.38000488 C13.7177562,8.38000488 14.0001089,8.47668596 14.2000659,8.67005103 C14.400023,8.86341609 14.5,9.14027555 14.5,9.50063771 C14.5,9.84781589 14.3989243,10.1213794 14.1967699,10.3213365 C13.9946156,10.5212935 13.7133615,10.6212705 13.3529993,10.6212705 C12.9838479,10.6212705 12.6981992,10.5234908 12.4960448,10.3279284 C12.2938904,10.132366 12.1928148,9.85660521 12.1928148,9.50063771 L12.1928148,9.50063771 Z" id="…" fill="#9B9B9B"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.5 KiB |
|
@ -19,9 +19,9 @@ describe("requestMediaPermissions", () => {
|
|||
const audioStream = {} as MediaStream;
|
||||
|
||||
const itShouldLogTheErrorAndShowTheNoMediaPermissionsModal = () => {
|
||||
it("should log the error and show the »No media permissions« modal", () => {
|
||||
it("should log the error and show the »No media permissions« modal", async () => {
|
||||
expect(logger.log).toHaveBeenCalledWith("Failed to list userMedia devices", error);
|
||||
screen.getByText("No media permissions");
|
||||
await screen.findByText("No media permissions");
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
|||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
import { act, render } from "jest-matrix-react";
|
||||
import { MatrixEvent, ConditionKind, EventType, PushRuleActionName, Room, TweakName } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
|
@ -15,6 +15,7 @@ import { pillifyLinks } from "../../../src/utils/pillify";
|
|||
import { stubClient } from "../../test-utils";
|
||||
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
||||
import DMRoomMap from "../../../src/utils/DMRoomMap";
|
||||
import { ReactRootManager } from "../../../src/utils/react.tsx";
|
||||
|
||||
describe("pillify", () => {
|
||||
const roomId = "!room:id";
|
||||
|
@ -84,51 +85,55 @@ describe("pillify", () => {
|
|||
it("should do nothing for empty element", () => {
|
||||
const { container } = render(<div />);
|
||||
const originalHtml = container.outerHTML;
|
||||
const containers: Element[] = [];
|
||||
const containers = new ReactRootManager();
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
expect(containers).toHaveLength(0);
|
||||
expect(containers.elements).toHaveLength(0);
|
||||
expect(container.outerHTML).toEqual(originalHtml);
|
||||
});
|
||||
|
||||
it("should pillify @room", () => {
|
||||
const { container } = render(<div>@room</div>);
|
||||
const containers: Element[] = [];
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
expect(containers).toHaveLength(1);
|
||||
const containers = new ReactRootManager();
|
||||
act(() => pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers));
|
||||
expect(containers.elements).toHaveLength(1);
|
||||
expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room");
|
||||
});
|
||||
|
||||
it("should pillify @room in an intentional mentions world", () => {
|
||||
mocked(MatrixClientPeg.safeGet().supportsIntentionalMentions).mockReturnValue(true);
|
||||
const { container } = render(<div>@room</div>);
|
||||
const containers: Element[] = [];
|
||||
pillifyLinks(
|
||||
MatrixClientPeg.safeGet(),
|
||||
[container],
|
||||
new MatrixEvent({
|
||||
room_id: roomId,
|
||||
type: EventType.RoomMessage,
|
||||
content: {
|
||||
"body": "@room",
|
||||
"m.mentions": {
|
||||
room: true,
|
||||
const containers = new ReactRootManager();
|
||||
act(() =>
|
||||
pillifyLinks(
|
||||
MatrixClientPeg.safeGet(),
|
||||
[container],
|
||||
new MatrixEvent({
|
||||
room_id: roomId,
|
||||
type: EventType.RoomMessage,
|
||||
content: {
|
||||
"body": "@room",
|
||||
"m.mentions": {
|
||||
room: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
containers,
|
||||
}),
|
||||
containers,
|
||||
),
|
||||
);
|
||||
expect(containers).toHaveLength(1);
|
||||
expect(containers.elements).toHaveLength(1);
|
||||
expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room");
|
||||
});
|
||||
|
||||
it("should not double up pillification on repeated calls", () => {
|
||||
const { container } = render(<div>@room</div>);
|
||||
const containers: Element[] = [];
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
expect(containers).toHaveLength(1);
|
||||
const containers = new ReactRootManager();
|
||||
act(() => {
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
|
||||
});
|
||||
expect(containers.elements).toHaveLength(1);
|
||||
expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ import { act, render } from "jest-matrix-react";
|
|||
import { tooltipifyLinks } from "../../../src/utils/tooltipify";
|
||||
import PlatformPeg from "../../../src/PlatformPeg";
|
||||
import BasePlatform from "../../../src/BasePlatform";
|
||||
import { ReactRootManager } from "../../../src/utils/react.tsx";
|
||||
|
||||
describe("tooltipify", () => {
|
||||
jest.spyOn(PlatformPeg, "get").mockReturnValue({ needsUrlTooltips: () => true } as unknown as BasePlatform);
|
||||
|
@ -19,9 +20,9 @@ describe("tooltipify", () => {
|
|||
it("does nothing for empty element", () => {
|
||||
const { container: root } = render(<div />);
|
||||
const originalHtml = root.outerHTML;
|
||||
const containers: Element[] = [];
|
||||
const containers = new ReactRootManager();
|
||||
tooltipifyLinks([root], [], containers);
|
||||
expect(containers).toHaveLength(0);
|
||||
expect(containers.elements).toHaveLength(0);
|
||||
expect(root.outerHTML).toEqual(originalHtml);
|
||||
});
|
||||
|
||||
|
@ -31,9 +32,9 @@ describe("tooltipify", () => {
|
|||
<a href="/foo">click</a>
|
||||
</div>,
|
||||
);
|
||||
const containers: Element[] = [];
|
||||
const containers = new ReactRootManager();
|
||||
tooltipifyLinks([root], [], containers);
|
||||
expect(containers).toHaveLength(1);
|
||||
expect(containers.elements).toHaveLength(1);
|
||||
const anchor = root.querySelector("a");
|
||||
expect(anchor?.getAttribute("href")).toEqual("/foo");
|
||||
const tooltip = anchor!.querySelector(".mx_TextWithTooltip_target");
|
||||
|
@ -47,9 +48,9 @@ describe("tooltipify", () => {
|
|||
</div>,
|
||||
);
|
||||
const originalHtml = root.outerHTML;
|
||||
const containers: Element[] = [];
|
||||
const containers = new ReactRootManager();
|
||||
tooltipifyLinks([root], [root.children[0]], containers);
|
||||
expect(containers).toHaveLength(0);
|
||||
expect(containers.elements).toHaveLength(0);
|
||||
expect(root.outerHTML).toEqual(originalHtml);
|
||||
});
|
||||
|
||||
|
@ -59,12 +60,12 @@ describe("tooltipify", () => {
|
|||
<a href="/foo">click</a>
|
||||
</div>,
|
||||
);
|
||||
const containers: Element[] = [];
|
||||
const containers = new ReactRootManager();
|
||||
tooltipifyLinks([root], [], containers);
|
||||
tooltipifyLinks([root], [], containers);
|
||||
tooltipifyLinks([root], [], containers);
|
||||
tooltipifyLinks([root], [], containers);
|
||||
expect(containers).toHaveLength(1);
|
||||
expect(containers.elements).toHaveLength(1);
|
||||
const anchor = root.querySelector("a");
|
||||
expect(anchor?.getAttribute("href")).toEqual("/foo");
|
||||
const tooltip = anchor!.querySelector(".mx_TextWithTooltip_target");
|
||||
|
|
|
@ -229,4 +229,18 @@ describe("WebPlatform", () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should return config from config.json", async () => {
|
||||
window.location.hostname = "domain.com";
|
||||
fetchMock.get(/config\.json.*/, { brand: "test" });
|
||||
const platform = new WebPlatform();
|
||||
await expect(platform.getConfig()).resolves.toEqual(expect.objectContaining({ brand: "test" }));
|
||||
});
|
||||
|
||||
it("should re-render favicon when setting error status", () => {
|
||||
const platform = new WebPlatform();
|
||||
const spy = jest.spyOn(platform.favicon, "badge");
|
||||
platform.setErrorStatus(true);
|
||||
expect(spy).toHaveBeenCalledWith(expect.anything(), { bgColor: "#f00" });
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue