diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bb802ef03e0..ad1804bfc5f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,6 +16,7 @@ /src/components/views/dialogs/devtools/Crypto.tsx @element-hq/element-crypto-web-reviewers /playwright/e2e/crypto/ @element-hq/element-crypto-web-reviewers /playwright/e2e/settings/encryption-user-tab/ @element-hq/element-crypto-web-reviewers +/packages/shared-components/src/crypto/ @element-hq/element-crypto-web-reviewers /src/models/Call.ts @element-hq/element-call-reviewers diff --git a/package.json b/package.json index 2b8c1e243fe..92cf1549881 100644 --- a/package.json +++ b/package.json @@ -90,7 +90,6 @@ "@matrix-org/analytics-events": "^0.31.0", "@matrix-org/emojibase-bindings": "^1.5.0", "@matrix-org/react-sdk-module-api": "^2.4.0", - "@matrix-org/spec": "^1.7.0", "@sentry/browser": "^10.0.0", "@types/png-chunks-extract": "^1.0.2", "@vector-im/compound-design-tokens": "6.9.0", diff --git a/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/default-auto.png b/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/default-auto.png new file mode 100644 index 00000000000..8e27242e478 Binary files /dev/null and b/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/default-auto.png differ diff --git a/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/worst-case-albanian-auto.png b/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/worst-case-albanian-auto.png new file mode 100644 index 00000000000..c845bdeabe2 Binary files /dev/null and b/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/worst-case-albanian-auto.png differ diff --git a/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/worst-case-german-auto.png b/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/worst-case-german-auto.png new file mode 100644 index 00000000000..6565cf86b70 Binary files /dev/null and b/packages/shared-components/__vis__/linux/__baselines__/crypto/SasEmoji/SasEmoji.stories.tsx/worst-case-german-auto.png differ diff --git a/packages/shared-components/package.json b/packages/shared-components/package.json index 5987d81dbd8..0ed297872e3 100644 --- a/packages/shared-components/package.json +++ b/packages/shared-components/package.json @@ -50,6 +50,7 @@ }, "dependencies": { "@element-hq/element-web-module-api": "^1.8.0", + "@matrix-org/spec": "^1.7.0", "@vector-im/compound-design-tokens": "^6.4.3", "classnames": "^2.5.1", "counterpart": "^0.18.6", diff --git a/packages/shared-components/src/crypto/SasEmoji/SasEmoji.module.css b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.module.css new file mode 100644 index 00000000000..b763ef66642 --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.module.css @@ -0,0 +1,33 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +.container { + display: flex; + flex-wrap: wrap; + gap: var(--cpd-space-2x); + justify-content: space-evenly; +} + +.segment { + display: inline-block; + margin-bottom: var(--cpd-space-4x); + text-align: center; + /* Allow maximum 4 per line, accounting for 8px gap */ + min-width: calc(25% - 8px); +} + +.emoji { + /* Use the Twemoji font for consistency with other clients */ + font-family: Twemoji, var(--cpd-font-family-sans); + font-size: var(--cpd-font-size-heading-xl); +} + +.label { + font-weight: var(--cpd-font-weight-regular); + font-size: var(--cpd-font-size-body-lg); + color: var(--cpd-color-text-secondary); +} diff --git a/packages/shared-components/src/crypto/SasEmoji/SasEmoji.stories.tsx b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.stories.tsx new file mode 100644 index 00000000000..9c0fcc3f402 --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.stories.tsx @@ -0,0 +1,48 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { type Meta, type StoryObj } from "@storybook/react-vite"; + +import { SasEmoji } from "./SasEmoji"; + +const meta = { + title: "Crypto/SasEmoji", + component: SasEmoji, + tags: ["autodocs"], + args: { + emoji: ["πŸ•", "🌽", "πŸš€", "πŸ”’", "πŸ”§", "πŸ“", "βŒ›"], + }, + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/design/XLWIAB5n8yObYvU0INKPK1/Verification-by-Emoji?node-id=1-2935&t=NrV9JnuItrAyyh53-4", + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const WorstCaseAlbanian: Story = { + globals: { + language: "sq", + }, + args: { + emoji: ["πŸŽ…", "πŸŽ…", "πŸŽ…", "πŸŽ…", "πŸŽ…", "πŸŽ…", "πŸŽ…"], + }, +}; + +export const WorstCaseGerman: Story = { + globals: { + language: "de", + }, + args: { + emoji: ["πŸ”§", "πŸ”§", "πŸ”§", "πŸ”§", "πŸ”§", "πŸ”§", "πŸ”§"], + }, +}; diff --git a/packages/shared-components/src/crypto/SasEmoji/SasEmoji.test.tsx b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.test.tsx new file mode 100644 index 00000000000..c9946d52a0b --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.test.tsx @@ -0,0 +1,19 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import React from "react"; +import { describe, it, expect } from "vitest"; +import { render } from "@test-utils"; + +import { SasEmoji } from "./SasEmoji"; + +describe("", () => { + it("should match snapshot", () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/packages/shared-components/src/crypto/SasEmoji/SasEmoji.tsx b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.tsx new file mode 100644 index 00000000000..6701cb37c9c --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/SasEmoji.tsx @@ -0,0 +1,43 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +import React, { type JSX } from "react"; +import classNames from "classnames"; + +import { type SasEmoji, tEmoji } from "./SasEmojiTranslate.ts"; +import styles from "./SasEmoji.module.css"; +import { useI18n } from "../../utils/i18nContext.ts"; + +export type Props = { + /** + * The emoji to render + */ + emoji: [SasEmoji, SasEmoji, SasEmoji, SasEmoji, SasEmoji, SasEmoji, SasEmoji]; + /** + * Optional className to apply to the container + */ + className?: string; +}; + +/** + * Renders the 7 emoji used for SAS verification. + * The component is responsive so can be rendered in any context, dialog, side panel. + */ +export function SasEmoji({ emoji, className }: Props): JSX.Element { + const { language } = useI18n(); + + const emojiBlocks = emoji.map((emoji, i) => ( +
+
+ {emoji} +
+
{tEmoji(emoji, language)}
+
+ )); + + return
{emojiBlocks}
; +} diff --git a/packages/shared-components/src/crypto/SasEmoji/SasEmojiTranslate.test.ts b/packages/shared-components/src/crypto/SasEmoji/SasEmojiTranslate.test.ts new file mode 100644 index 00000000000..8251e52ea4b --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/SasEmojiTranslate.test.ts @@ -0,0 +1,26 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { describe, it, expect } from "vitest"; + +import { tEmoji, type SasEmoji } from "./SasEmojiTranslate.ts"; + +describe("tEmoji", () => { + it.each([ + ["🐢", "en-GB", "Dog"], + ["🐢", "en", "Dog"], + ["🐢", "de-DE", "Hund"], + ["🐢", "pt", "Cachorro"], + ["πŸ”§", "de-DE", "SchraubenschlΓΌssel"], + ["πŸŽ…", "sq", "Babagjyshi i Vitit tΓ« Ri"], + ] as [emoji: SasEmoji, locale: string, expectation: string][])( + "should handle locale %s", + (emoji, locale, expectation) => { + expect(tEmoji(emoji, locale)).toEqual(expectation); + }, + ); +}); diff --git a/packages/shared-components/src/crypto/SasEmoji/SasEmojiTranslate.ts b/packages/shared-components/src/crypto/SasEmoji/SasEmojiTranslate.ts new file mode 100644 index 00000000000..da977a98e0e --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/SasEmojiTranslate.ts @@ -0,0 +1,122 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +import SasEmojiJson from "@matrix-org/spec/sas-emoji.json"; +import { getNormalizedLanguageKeys } from "matrix-web-i18n"; + +// Type as specified in https://spec.matrix.org/v1.17/client-server-api/#sas-method-emoji +export type SasEmoji = + | "🐢" + | "🐱" + | "🦁" + | "🐎" + | "πŸ¦„" + | "🐷" + | "🐘" + | "🐰" + | "🐼" + | "πŸ“" + | "🐧" + | "🐒" + | "🐟" + | "πŸ™" + | "πŸ¦‹" + | "🌷" + | "🌳" + | "🌡" + | "πŸ„" + | "🌏" + | "πŸŒ™" + | "☁" + | "πŸ”₯" + | "🍌" + | "🍎" + | "πŸ“" + | "🌽" + | "πŸ•" + | "πŸŽ‚" + | "❀" + | "πŸ˜€" + | "πŸ€–" + | "🎩" + | "πŸ‘“" + | "πŸ”§" + | "πŸŽ…" + | "πŸ‘" + | "β˜‚" + | "βŒ›" + | "⏰" + | "🎁" + | "πŸ’‘" + | "πŸ“•" + | "✏" + | "πŸ“Ž" + | "βœ‚" + | "πŸ”’" + | "πŸ”‘" + | "πŸ”¨" + | "☎" + | "🏁" + | "πŸš‚" + | "🚲" + | "✈" + | "πŸš€" + | "πŸ†" + | "⚽" + | "🎸" + | "🎺" + | "πŸ””" + | "βš“" + | "🎧" + | "πŸ“" + | "πŸ“Œ"; + +const SasEmojiMap = new Map< + SasEmoji, + [ + description: string, + translations: { + [normalizedLanguageKey: string]: string; + }, + ] +>( + SasEmojiJson.map(({ emoji, description, translated_descriptions: translations }) => [ + emoji as SasEmoji, + [ + description, + // Normalize the translation keys + Object.keys(translations).reduce>((o, k) => { + for (const key of getNormalizedLanguageKeys(k)) { + o[key] = translations[k as keyof typeof translations]!; + } + return o; + }, {}), + ], + ]), +); + +/** + * Translate given SAS emoji into the target locale + * @param emoji - the SAS emoji to translate + * @param locale - the BCP 47 locale to translate to, will fall back to English as the base locale for Matrix SAS Emoji. + */ +export function tEmoji(emoji: SasEmoji, locale: string): string { + const mapping = SasEmojiMap.get(emoji); + if (!mapping) { + throw new Error(`Emoji mapping not found for emoji ${emoji}`); + } + + const [description, translations] = mapping; + + for (const key of getNormalizedLanguageKeys(locale)) { + if (translations[key]) { + return translations[key]; + } + } + + return description; +} diff --git a/packages/shared-components/src/crypto/SasEmoji/__snapshots__/SasEmoji.test.tsx.snap b/packages/shared-components/src/crypto/SasEmoji/__snapshots__/SasEmoji.test.tsx.snap new file mode 100644 index 00000000000..27f53cb8708 --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/__snapshots__/SasEmoji.test.tsx.snap @@ -0,0 +1,115 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[` > should match snapshot 1`] = ` + +
+
+ +
+ Butterfly +
+
+
+ +
+ Mushroom +
+
+
+ +
+ Ball +
+
+
+ +
+ Globe +
+
+
+ +
+ Unicorn +
+
+
+ +
+ Rocket +
+
+
+ +
+ Spanner +
+
+
+
+`; diff --git a/packages/shared-components/src/crypto/SasEmoji/index.ts b/packages/shared-components/src/crypto/SasEmoji/index.ts new file mode 100644 index 00000000000..5c6dc18fb7b --- /dev/null +++ b/packages/shared-components/src/crypto/SasEmoji/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +export { SasEmoji } from "./SasEmoji.tsx"; diff --git a/packages/shared-components/src/index.ts b/packages/shared-components/src/index.ts index 83f074fa662..99aa142d209 100644 --- a/packages/shared-components/src/index.ts +++ b/packages/shared-components/src/index.ts @@ -12,6 +12,7 @@ export * from "./audio/PlayPauseButton"; export * from "./audio/SeekBar"; export * from "./avatar/AvatarWithDetails"; export * from "./composer/Banner"; +export * from "./crypto/SasEmoji"; export * from "./event-tiles/TextualEventView"; export * from "./message-body/MediaBody"; export * from "./pill-input/Pill"; diff --git a/packages/shared-components/yarn.lock b/packages/shared-components/yarn.lock index 2341936db59..62e161d50d1 100644 --- a/packages/shared-components/yarn.lock +++ b/packages/shared-components/yarn.lock @@ -667,6 +667,11 @@ dependencies: "@babel/runtime" "^7.17.9" +"@matrix-org/spec@^1.7.0": + version "1.16.0" + resolved "https://registry.yarnpkg.com/@matrix-org/spec/-/spec-1.16.0.tgz#c88f4ed521e4c0bd3a4c108bcaf13f25173a0fdc" + integrity sha512-xUKHkwGXXISMCfTrx6JW6uGEK5O8IeZVOjBm7FX1h/ihpK6l50nlSIMRYdtz4V6q3pvOVBOCft4hPYTJVeTZDA== + "@mdx-js/react@^3.0.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-3.1.1.tgz#24bda7fffceb2fe256f954482123cda1be5f5fef" diff --git a/playwright/e2e/crypto/utils.ts b/playwright/e2e/crypto/utils.ts index 8b677ed4cb4..4aab27f51af 100644 --- a/playwright/e2e/crypto/utils.ts +++ b/playwright/e2e/crypto/utils.ts @@ -290,7 +290,7 @@ export async function doTwoWaySasVerification(page: Page, verifier: JSHandle div"); await expect(emojiBlocks).toHaveCount(emojis.length); // then, check that our application shows an emoji panel with the same emojis. diff --git a/res/css/views/verification/_VerificationShowSas.pcss b/res/css/views/verification/_VerificationShowSas.pcss index 9e4d1f138b3..57fae767883 100644 --- a/res/css/views/verification/_VerificationShowSas.pcss +++ b/res/css/views/verification/_VerificationShowSas.pcss @@ -20,40 +20,9 @@ Please see LICENSE files in the repository root for full details. } .mx_VerificationShowSas_emojiSas { - text-align: center; - display: flex; - flex-wrap: wrap; - justify-content: center; margin: 25px 0; } -.mx_VerificationShowSas_emojiSas_block { - display: inline-block; - margin-bottom: 16px; - position: relative; - width: 52px; -} - -.mx_Dialog .mx_VerificationShowSas_emojiSas_block, -.mx_AuthPage_modal .mx_VerificationShowSas_emojiSas_block { - width: 60px; -} - -.mx_VerificationShowSas_emojiSas_emoji { - font-size: $font-32px; - /* Use the Twemoji font for consistency with other clients */ - font-family: Twemoji, var(--cpd-font-family-sans); -} - -.mx_VerificationShowSas_emojiSas_label { - font-size: $font-12px; - word-break: break-word; -} - -.mx_VerificationShowSas_emojiSas_break { - flex-basis: 100%; -} - .mx_VerificationShowSas_buttonRow { text-align: center; display: flex; diff --git a/src/components/views/verification/VerificationShowSas.tsx b/src/components/views/verification/VerificationShowSas.tsx index 0f6272a8850..84490e556bd 100644 --- a/src/components/views/verification/VerificationShowSas.tsx +++ b/src/components/views/verification/VerificationShowSas.tsx @@ -6,12 +6,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ -import React from "react"; +import React, { type ComponentProps } from "react"; import { type Device } from "matrix-js-sdk/src/matrix"; -import { type GeneratedSas, type EmojiMapping } from "matrix-js-sdk/src/crypto-api"; -import SasEmoji from "@matrix-org/spec/sas-emoji.json"; +import { type GeneratedSas } from "matrix-js-sdk/src/crypto-api"; +import { SasEmoji } from "@element-hq/web-shared-components"; -import { _t, getNormalizedLanguageKeys, getUserLanguage } from "../../../languageHandler"; +import { _t } from "../../../languageHandler"; import { PendingActionSpinner } from "../right_panel/EncryptionInfo"; import AccessibleButton from "../elements/AccessibleButton"; @@ -34,52 +34,6 @@ interface IState { cancelling?: boolean; } -const SasEmojiMap = new Map< - string, // lowercase - { - description: string; - translations: { - [normalizedLanguageKey: string]: string; - }; - } ->( - SasEmoji.map(({ description, translated_descriptions: translations }) => [ - description.toLowerCase(), - { - description, - // Normalize the translation keys - translations: Object.keys(translations).reduce>((o, k) => { - for (const key of getNormalizedLanguageKeys(k)) { - o[key] = translations[k as keyof typeof translations]!; - } - return o; - }, {}), - }, - ]), -); - -/** - * Translate given EmojiMapping into the target locale - * @param mapping - the given EmojiMapping to translate - * @param locale - the BCP 47 locale to translate to, will fall back to English as the base locale for Matrix SAS Emoji. - */ -export function tEmoji(mapping: EmojiMapping, locale: string): string { - const name = mapping[1]; - const emoji = SasEmojiMap.get(name.toLowerCase()); - if (!emoji) { - console.warn("Emoji not found for translation", name); - return name; - } - - for (const key of getNormalizedLanguageKeys(locale)) { - if (!!emoji.translations[key]) { - return emoji.translations[key]; - } - } - - return emoji.description; -} - export default class VerificationShowSas extends React.Component { public constructor(props: IProps) { super(props); @@ -100,25 +54,14 @@ export default class VerificationShowSas extends React.Component }; public render(): React.ReactNode { - const locale = getUserLanguage(); - let sasDisplay; let sasCaption; if (this.props.sas.emoji) { - const emojiBlocks = this.props.sas.emoji.map((emoji, i) => ( -
-
- {emoji[0]} -
-
{tEmoji(emoji, locale)}
-
- )); sasDisplay = ( -
- {emojiBlocks.slice(0, 4)} -
- {emojiBlocks.slice(4)} -
+ e[0]) as ComponentProps["emoji"]} + /> ); sasCaption = this.props.isSelf ? _t("encryption|verification|confirm_the_emojis") diff --git a/test/unit-tests/components/views/VerificationShowSas-test.tsx b/test/unit-tests/components/views/VerificationShowSas-test.tsx deleted file mode 100644 index f9312e906e4..00000000000 --- a/test/unit-tests/components/views/VerificationShowSas-test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2023 The Matrix.org Foundation C.I.C. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -import { type EmojiMapping } from "matrix-js-sdk/src/crypto-api"; - -import { tEmoji } from "../../../../src/components/views/verification/VerificationShowSas"; - -describe("tEmoji", () => { - it.each([ - ["en-GB", "Dog"], - ["en", "Dog"], - ["de-DE", "Hund"], - ["pt", "Cachorro"], - ])("should handle locale %s", (locale, expectation) => { - const emoji: EmojiMapping = ["🐢", "Dog"]; - expect(tEmoji(emoji, locale)).toEqual(expectation); - }); -}); diff --git a/test/unit-tests/components/views/dialogs/IncomingSasDialog-test.tsx b/test/unit-tests/components/views/dialogs/IncomingSasDialog-test.tsx index cf9e103ee64..2a7ed61f13c 100644 --- a/test/unit-tests/components/views/dialogs/IncomingSasDialog-test.tsx +++ b/test/unit-tests/components/views/dialogs/IncomingSasDialog-test.tsx @@ -34,7 +34,7 @@ describe("IncomingSasDialog", () => { it("should show some emojis once keys are exchanged", () => { const mockVerifier = makeMockVerifier(); - const { container } = renderComponent(mockVerifier); + const { getAllByText } = renderComponent(mockVerifier); // fire the ShowSas event const sasEvent = makeMockSasCallbacks(); @@ -42,11 +42,8 @@ describe("IncomingSasDialog", () => { mockVerifier.emit(VerifierEvent.ShowSas, sasEvent); }); - const emojis = container.getElementsByClassName("mx_VerificationShowSas_emojiSas_block"); - expect(emojis.length).toEqual(7); - for (const emoji of emojis) { - expect(emoji).toHaveTextContent("πŸ¦„Unicorn"); - } + expect(getAllByText("πŸ¦„")).toHaveLength(7); + expect(getAllByText("Unicorn")).toHaveLength(7); }); }); diff --git a/test/unit-tests/components/views/dialogs/__snapshots__/VerificationRequestDialog-test.tsx.snap b/test/unit-tests/components/views/dialogs/__snapshots__/VerificationRequestDialog-test.tsx.snap index 79737988d0a..79d21cf19f1 100644 --- a/test/unit-tests/components/views/dialogs/__snapshots__/VerificationRequestDialog-test.tsx.snap +++ b/test/unit-tests/components/views/dialogs/__snapshots__/VerificationRequestDialog-test.tsx.snap @@ -456,41 +456,38 @@ exports[`VerificationRequestDialog When other device accepted emoji, displays em Confirm that the emojis below match those shown on your other device.

Dog
Cat
-

", () => { }); it("should show some emojis once keys are exchanged", () => { - const { container } = renderComponent({ + const { getAllByText } = renderComponent({ request: mockRequest, phase: Phase.Started, }); @@ -117,11 +117,8 @@ describe("", () => { mockVerifier.emit(VerifierEvent.ShowSas, sasEvent); }); - const emojis = container.getElementsByClassName("mx_VerificationShowSas_emojiSas_block"); - expect(emojis.length).toEqual(7); - for (const emoji of emojis) { - expect(emoji).toHaveTextContent("πŸ¦„Unicorn"); - } + expect(getAllByText("πŸ¦„")).toHaveLength(7); + expect(getAllByText("Unicorn")).toHaveLength(7); }); describe("'Verify own device' flow", () => {