Switch shared-components from jest & test-runner to vitest (#31800)

* Remove babel

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Remove duplicated patch-package dep

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Switch to @fetch-mock/vitest

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update tests to import & call vitest functions

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update test-utils imports

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update unit test snapshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Switch from jest->vitest for unit tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update visual test screenshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Switch from test-runner->vitest for visual tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update README

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update CI for shared-components unit & visual tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update yarn.lock

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update README

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix storybook trying to import vitest

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix css modules leaking between storybook tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Tweak screenshot update script to accept args

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2026-01-22 14:17:36 +00:00
committed by GitHub
parent 4bddf37866
commit 35fca4d339
157 changed files with 935 additions and 3875 deletions

View File

@@ -5,11 +5,12 @@
* Please see LICENSE files in the repository root for full details.
*/
import { render, screen } from "jest-matrix-react";
import { render, screen } from "@test-utils";
import { composeStories } from "@storybook/react-vite";
import React from "react";
import userEvent from "@testing-library/user-event";
import { fireEvent } from "@testing-library/dom";
import { describe, it, vi, afterEach, expect } from "vitest";
import * as stories from "./AudioPlayerView.stories.tsx";
import { AudioPlayerView, type AudioPlayerViewActions, type AudioPlayerViewSnapshot } from "./AudioPlayerView";
@@ -21,7 +22,7 @@ const { Default, NoMediaName, NoSize, HasError } = composeStories(stories);
describe("AudioPlayerView", () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it("renders the audio player in default state", () => {
@@ -44,9 +45,9 @@ describe("AudioPlayerView", () => {
expect(container).toMatchSnapshot();
});
const onKeyDown = jest.fn();
const togglePlay = jest.fn();
const onSeekbarChange = jest.fn();
const onKeyDown = vi.fn();
const togglePlay = vi.fn();
const onSeekbarChange = vi.fn();
class AudioPlayerViewModel extends MockViewModel<AudioPlayerViewSnapshot> implements AudioPlayerViewActions {
public onKeyDown = onKeyDown;

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AudioPlayerView renders the audio player in default state 1`] = `
exports[`AudioPlayerView > renders the audio player in default state 1`] = `
<div>
<div
aria-label="Audio player"
@@ -91,7 +91,7 @@ exports[`AudioPlayerView renders the audio player in default state 1`] = `
</div>
`;
exports[`AudioPlayerView renders the audio player in error state 1`] = `
exports[`AudioPlayerView > renders the audio player in error state 1`] = `
<div>
<div
aria-label="Audio player"
@@ -187,7 +187,7 @@ exports[`AudioPlayerView renders the audio player in error state 1`] = `
</div>
`;
exports[`AudioPlayerView renders the audio player without media name 1`] = `
exports[`AudioPlayerView > renders the audio player without media name 1`] = `
<div>
<div
aria-label="Audio player"
@@ -278,7 +278,7 @@ exports[`AudioPlayerView renders the audio player without media name 1`] = `
</div>
`;
exports[`AudioPlayerView renders the audio player without size 1`] = `
exports[`AudioPlayerView > renders the audio player without size 1`] = `
<div>
<div
aria-label="Audio player"

View File

@@ -6,8 +6,9 @@
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { describe, it, expect } from "vitest";
import * as stories from "./Clock.stories.tsx";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Clock renders the clock 1`] = `
exports[`Clock > renders the clock 1`] = `
<div>
<time
class="mx_Clock"
@@ -11,7 +11,7 @@ exports[`Clock renders the clock 1`] = `
</div>
`;
exports[`Clock renders the clock with a lot of seconds 1`] = `
exports[`Clock > renders the clock with a lot of seconds 1`] = `
<div>
<time
class="mx_Clock"

View File

@@ -6,10 +6,11 @@
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import userEvent from "@testing-library/user-event";
import { fn } from "storybook/test";
import { describe, it, expect } from "vitest";
import * as stories from "./PlayPauseButton.stories.tsx";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`PlayPauseButton renders the button in default state 1`] = `
exports[`PlayPauseButton > renders the button in default state 1`] = `
<div>
<button
aria-disabled="false"
@@ -32,7 +32,7 @@ exports[`PlayPauseButton renders the button in default state 1`] = `
</div>
`;
exports[`PlayPauseButton renders the button in playing state 1`] = `
exports[`PlayPauseButton > renders the button in playing state 1`] = `
<div>
<button
aria-disabled="false"

View File

@@ -5,9 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { composeStories } from "@storybook/react-vite";
import { describe, it, expect } from "vitest";
import * as stories from "./SeekBar.stories.tsx";
const { Default } = composeStories(stories);

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Seekbar renders the clock 1`] = `
exports[`Seekbar > renders the clock 1`] = `
<div>
<input
aria-label="Audio seek bar"

View File

@@ -6,8 +6,9 @@ Please see LICENSE files in the repository root for full details.
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { describe, it, expect } from "vitest";
import * as stories from "./AvatarWithDetails.stories.tsx";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AvatarWithDetails renders a textual event 1`] = `
exports[`AvatarWithDetails > renders a textual event 1`] = `
<div>
<div
class="avatarWithDetails"

View File

@@ -6,7 +6,8 @@
*/
import React from "react";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import { describe, it, expect } from "vitest";
import { composeStories } from "@storybook/react-vite";
import * as stories from "./Banner.stories.tsx";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AvatarWithDetails renders a banner with an action 1`] = `
exports[`AvatarWithDetails > renders a banner with an action 1`] = `
<div>
<div
class="banner"
@@ -68,7 +68,7 @@ exports[`AvatarWithDetails renders a banner with an action 1`] = `
</div>
`;
exports[`AvatarWithDetails renders a banner with an avatar iamge 1`] = `
exports[`AvatarWithDetails > renders a banner with an avatar iamge 1`] = `
<div>
<div
class="banner"
@@ -105,7 +105,7 @@ exports[`AvatarWithDetails renders a banner with an avatar iamge 1`] = `
</div>
`;
exports[`AvatarWithDetails renders a critical banner 1`] = `
exports[`AvatarWithDetails > renders a critical banner 1`] = `
<div>
<div
class="banner"
@@ -151,7 +151,7 @@ exports[`AvatarWithDetails renders a critical banner 1`] = `
</div>
`;
exports[`AvatarWithDetails renders a default banner 1`] = `
exports[`AvatarWithDetails > renders a default banner 1`] = `
<div>
<div
class="banner"
@@ -201,7 +201,7 @@ exports[`AvatarWithDetails renders a default banner 1`] = `
</div>
`;
exports[`AvatarWithDetails renders a info banner 1`] = `
exports[`AvatarWithDetails > renders a info banner 1`] = `
<div>
<div
class="banner"
@@ -252,7 +252,7 @@ exports[`AvatarWithDetails renders a info banner 1`] = `
</div>
`;
exports[`AvatarWithDetails renders a success banner 1`] = `
exports[`AvatarWithDetails > renders a success banner 1`] = `
<div>
<div
class="banner"

View File

@@ -6,8 +6,9 @@
*/
import React from "react";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import { composeStories } from "@storybook/react-vite";
import { describe, it, vi, expect } from "vitest";
import * as stories from "./HistoryVisibleBannerView.stories.tsx";
@@ -15,7 +16,7 @@ const { Default } = composeStories(stories);
describe("HistoryVisibleBannerView", () => {
it("renders a history visible banner", () => {
const dismissFn = jest.fn();
const dismissFn = vi.fn();
const { container } = render(<Default onClose={dismissFn} />);
expect(container).toMatchSnapshot();

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`HistoryVisibleBannerView renders a history visible banner 1`] = `
exports[`HistoryVisibleBannerView > renders a history visible banner 1`] = `
<div>
<div
class="banner"

View File

@@ -6,8 +6,9 @@ Please see LICENSE files in the repository root for full details.
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { describe, it, expect } from "vitest";
import * as stories from "./TextualEventView.stories.tsx";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`TextualEventView renders a textual event 1`] = `
exports[`TextualEventView > renders a textual event 1`] = `
<div>
<div
class="mx_TextualEvent"

View File

@@ -6,7 +6,8 @@
*/
import { type KeyboardEvent } from "react";
import { renderHook } from "jest-matrix-react";
import { renderHook } from "@test-utils";
import { vi, describe, expect, it, beforeEach, afterEach } from "vitest";
import { useListKeyboardNavigation } from "./useListKeyboardNavigation";
@@ -31,20 +32,20 @@ describe("useListKeyDown", () => {
// Mock event object
mockEvent = {
preventDefault: jest.fn(),
preventDefault: vi.fn(),
key: "",
};
// Mock focus methods
mockItems.forEach((item) => {
item.focus = jest.fn();
item.click = jest.fn();
item.focus = vi.fn();
item.click = vi.fn();
});
});
afterEach(() => {
document.body.removeChild(mockList);
jest.clearAllMocks();
vi.clearAllMocks();
});
function render(): {
@@ -91,7 +92,7 @@ describe("useListKeyDown", () => {
],
)("should handle %s to focus the %inth element", (key, finalPosition, startPosition) => {
const result = render();
mockList.contains = jest.fn().mockReturnValue(true);
mockList.contains = vi.fn().mockReturnValue(true);
Object.defineProperty(document, "activeElement", {
value: mockItems[startPosition],
@@ -109,7 +110,7 @@ describe("useListKeyDown", () => {
it.each([["ArrowDown"], ["ArrowUp"]])("should not handle %s when active element is not in list", (key) => {
const result = render();
mockList.contains = jest.fn().mockReturnValue(false);
mockList.contains = vi.fn().mockReturnValue(false);
const outsideElement = document.createElement("button");

View File

@@ -6,8 +6,9 @@
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { describe, it, expect } from "vitest";
import * as stories from "./MediaBody.stories";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`MediaBody renders the media body 1`] = `
exports[`MediaBody > renders the media body 1`] = `
<div>
<div
class="mx_MediaBody mediaBody"

View File

@@ -6,8 +6,9 @@
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { describe, it, expect } from "vitest";
import * as stories from "./Pill.stories";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Pill renders the pill 1`] = `
exports[`Pill > renders the pill 1`] = `
<div>
<div
class="flex pill"
@@ -45,7 +45,7 @@ exports[`Pill renders the pill 1`] = `
</div>
`;
exports[`Pill renders the pill without close button 1`] = `
exports[`Pill > renders the pill without close button 1`] = `
<div>
<div
class="flex pill"

View File

@@ -5,10 +5,11 @@
* Please see LICENSE files in the repository root for full details.
*/
import { render, screen } from "jest-matrix-react";
import { render, screen } from "@test-utils";
import React from "react";
import { composeStories } from "@storybook/react-vite";
import userEvent from "@testing-library/user-event";
import { describe, it, vi, expect } from "vitest";
import * as stories from "./PillInput.stories";
import { PillInput } from "./PillInput";
@@ -28,7 +29,7 @@ describe("PillInput", () => {
it("calls onRemoveChildren when backspace is pressed and input is empty", async () => {
const user = userEvent.setup();
const mockOnRemoveChildren = jest.fn();
const mockOnRemoveChildren = vi.fn();
render(<PillInput onRemoveChildren={mockOnRemoveChildren} />);

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`PillInput renders only the input without children 1`] = `
exports[`PillInput > renders only the input without children 1`] = `
<div>
<div
class="flex pillInput"
@@ -16,7 +16,7 @@ exports[`PillInput renders only the input without children 1`] = `
</div>
`;
exports[`PillInput renders the pill input 1`] = `
exports[`PillInput > renders the pill input 1`] = `
<div>
<div
class="flex pillInput"

View File

@@ -6,8 +6,9 @@
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { describe, it, vi, beforeAll, expect } from "vitest";
import * as stories from "./RichItem.stories";
@@ -15,7 +16,7 @@ const { Default, Selected, WithoutTimestamp } = composeStories(stories);
describe("RichItem", () => {
beforeAll(() => {
jest.useFakeTimers().setSystemTime(new Date("2025-08-01T12:00:00Z"));
vi.useFakeTimers().setSystemTime(new Date("2025-08-01T12:00:00Z"));
});
it("renders the item in default state", () => {

File diff suppressed because one or more lines are too long

View File

@@ -6,8 +6,9 @@
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import React from "react";
import { describe, it, expect } from "vitest";
import * as stories from "./RichList.stories";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`RichItem renders the list 1`] = `
exports[`RichItem > renders the list 1`] = `
<div>
<div
style="height: 220px; overflow: hidden;"
@@ -163,7 +163,7 @@ exports[`RichItem renders the list 1`] = `
</div>
`;
exports[`RichItem renders the list with isEmpty=true 1`] = `
exports[`RichItem > renders the list with isEmpty=true 1`] = `
<div>
<div
style="height: 220px; overflow: hidden;"

View File

@@ -15,7 +15,7 @@ import {
type RoomListHeaderViewSnapshot,
} from "./RoomListHeaderView";
import { useMockedViewModel } from "../../useMockedViewModel";
import { defaultSnapshot } from "./test-utils";
import { defaultSnapshot } from "./default-snapshot";
type RoomListHeaderProps = RoomListHeaderViewSnapshot & RoomListHeaderViewActions;

View File

@@ -6,7 +6,8 @@
*/
import { composeStories } from "@storybook/react-vite";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import { describe, it, expect } from "vitest";
import React from "react";
import * as stories from "./RoomListHeaderView.stories";

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`RoomListHeaderView renders the default state 1`] = `
exports[`RoomListHeaderView > renders the default state 1`] = `
<div>
<header
aria-label="Room options"
@@ -128,7 +128,7 @@ exports[`RoomListHeaderView renders the default state 1`] = `
</div>
`;
exports[`RoomListHeaderView renders without compose menu 1`] = `
exports[`RoomListHeaderView > renders without compose menu 1`] = `
<div>
<header
aria-label="Room options"
@@ -251,7 +251,7 @@ exports[`RoomListHeaderView renders without compose menu 1`] = `
</div>
`;
exports[`RoomListHeaderView renders without space menu 1`] = `
exports[`RoomListHeaderView > renders without space menu 1`] = `
<div>
<header
aria-label="Room options"

View File

@@ -0,0 +1,20 @@
/*
* 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 { type RoomListHeaderViewSnapshot } from "./RoomListHeaderView";
export const defaultSnapshot: RoomListHeaderViewSnapshot = {
title: "Rooms",
displayComposeMenu: true,
displaySpaceMenu: true,
canCreateRoom: true,
canCreateVideoRoom: true,
canInviteInSpace: true,
canAccessSpaceSettings: true,
activeSortOption: "recent",
isMessagePreviewEnabled: true,
};

View File

@@ -6,15 +6,16 @@
*/
import React from "react";
import { render, screen } from "jest-matrix-react";
import { render, screen } from "@test-utils";
import userEvent from "@testing-library/user-event";
import { vi, describe, it, afterEach, expect } from "vitest";
import { ComposeMenuView } from "./ComposeMenuView";
import { defaultSnapshot, MockedViewModel } from "../test-utils";
describe("<ComposeMenuView />", () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it("should match snapshot", () => {

View File

@@ -6,15 +6,16 @@
*/
import React from "react";
import { render, screen } from "jest-matrix-react";
import { render, screen } from "@test-utils";
import userEvent from "@testing-library/user-event";
import { vi, describe, it, afterEach, expect } from "vitest";
import { OptionMenuView } from "./OptionMenuView";
import { defaultSnapshot, MockedViewModel } from "../test-utils";
describe("<OptionMenuView />", () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it("should match snapshot", () => {

View File

@@ -6,15 +6,16 @@
*/
import React from "react";
import { render, screen } from "jest-matrix-react";
import { render, screen } from "@test-utils";
import userEvent from "@testing-library/user-event";
import { vi, describe, it, afterEach, expect } from "vitest";
import { SpaceMenuView } from "./SpaceMenuView";
import { defaultSnapshot, MockedViewModel } from "../test-utils";
describe("<SpaceMenuView />", () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it("should match snapshot", () => {

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<ComposeMenuView /> should match snapshot 1`] = `
exports[`<ComposeMenuView /> > should match snapshot 1`] = `
<DocumentFragment>
<button
aria-disabled="false"

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<OptionMenuView /> should match snapshot 1`] = `
exports[`<OptionMenuView /> > should match snapshot 1`] = `
<DocumentFragment>
<button
aria-disabled="false"

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<SpaceMenuView /> should match snapshot 1`] = `
exports[`<SpaceMenuView /> > should match snapshot 1`] = `
<DocumentFragment>
<button
aria-disabled="false"

View File

@@ -5,6 +5,8 @@
* Please see LICENSE files in the repository root for full details.
*/
import { vi } from "vitest";
import { MockViewModel } from "../../viewmodel";
import { type RoomListHeaderViewActions, type RoomListHeaderViewSnapshot } from "./RoomListHeaderView";
@@ -12,25 +14,15 @@ import { type RoomListHeaderViewActions, type RoomListHeaderViewSnapshot } from
* A mocked ViewModel for the RoomListHeaderView, for use in tests.
*/
export class MockedViewModel extends MockViewModel<RoomListHeaderViewSnapshot> implements RoomListHeaderViewActions {
public createChatRoom = jest.fn();
public createRoom = jest.fn();
public createVideoRoom = jest.fn();
public openSpaceHome = jest.fn();
public openSpaceSettings = jest.fn();
public inviteInSpace = jest.fn();
public sort = jest.fn();
public openSpacePreferences = jest.fn();
public toggleMessagePreview = jest.fn();
public createChatRoom = vi.fn<() => void>();
public createRoom = vi.fn<() => void>();
public createVideoRoom = vi.fn<() => void>();
public openSpaceHome = vi.fn<() => void>();
public openSpaceSettings = vi.fn<() => void>();
public inviteInSpace = vi.fn<() => void>();
public sort = vi.fn<() => void>();
public openSpacePreferences = vi.fn<() => void>();
public toggleMessagePreview = vi.fn<() => void>();
}
export const defaultSnapshot: RoomListHeaderViewSnapshot = {
title: "Rooms",
displayComposeMenu: true,
displaySpaceMenu: true,
canCreateRoom: true,
canCreateVideoRoom: true,
canInviteInSpace: true,
canAccessSpaceSettings: true,
activeSortOption: "recent",
isMessagePreviewEnabled: true,
};
export { defaultSnapshot } from "./default-snapshot";

View File

@@ -5,10 +5,11 @@
* Please see LICENSE files in the repository root for full details.
*/
import { render, screen } from "jest-matrix-react";
import { render, screen } from "@test-utils";
import { composeStories } from "@storybook/react-vite";
import React from "react";
import userEvent from "@testing-library/user-event";
import { describe, it, vi, afterEach, expect } from "vitest";
import * as stories from "./RoomListSearchView.stories";
import {
@@ -22,7 +23,7 @@ const { Default, WithDialPad, WithoutExplore, AllButtons } = composeStories(stor
describe("RoomListSearchView", () => {
afterEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
describe("Storybook snapshots", () => {
@@ -48,9 +49,9 @@ describe("RoomListSearchView", () => {
});
describe("User interactions", () => {
const onSearchClick = jest.fn();
const onDialPadClick = jest.fn();
const onExploreClick = jest.fn();
const onSearchClick = vi.fn();
const onDialPadClick = vi.fn();
const onExploreClick = vi.fn();
class TestViewModel extends MockViewModel<RoomListSearchViewSnapshot> implements RoomListSearchViewActions {
public onSearchClick = onSearchClick;

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`RoomListSearchView Storybook snapshots renders the default state 1`] = `
exports[`RoomListSearchView > Storybook snapshots > renders the default state 1`] = `
<div>
<div
class="flex view"
@@ -67,7 +67,7 @@ exports[`RoomListSearchView Storybook snapshots renders the default state 1`] =
</div>
`;
exports[`RoomListSearchView Storybook snapshots renders with all buttons visible 1`] = `
exports[`RoomListSearchView > Storybook snapshots > renders with all buttons visible 1`] = `
<div>
<div
class="flex view"
@@ -155,7 +155,7 @@ exports[`RoomListSearchView Storybook snapshots renders with all buttons visible
</div>
`;
exports[`RoomListSearchView Storybook snapshots renders with dial pad button 1`] = `
exports[`RoomListSearchView > Storybook snapshots > renders with dial pad button 1`] = `
<div>
<div
class="flex view"
@@ -243,7 +243,7 @@ exports[`RoomListSearchView Storybook snapshots renders with dial pad button 1`]
</div>
`;
exports[`RoomListSearchView Storybook snapshots renders without explore button 1`] = `
exports[`RoomListSearchView > Storybook snapshots > renders without explore button 1`] = `
<div>
<div
class="flex view"

View File

@@ -6,9 +6,10 @@
*/
import React from "react";
import { render } from "jest-matrix-react";
import { render } from "@test-utils";
import { composeStories } from "@storybook/react-vite";
import userEvent from "@testing-library/user-event";
import { describe, it, vi, expect } from "vitest";
import * as stories from "./RoomStatusBarView.stories.tsx";
@@ -33,12 +34,12 @@ describe("RoomStatusBarView", () => {
});
it("renders unsent messages", async () => {
const { container } = render(
<WithUnsentMessages onDeleteAllClick={jest.fn()} onRetryRoomCreationClick={jest.fn()} />,
<WithUnsentMessages onDeleteAllClick={vi.fn()} onRetryRoomCreationClick={vi.fn()} />,
);
expect(container).toMatchSnapshot();
});
it("renders unsent messages and deletes all", async () => {
const onDeleteAllClick = jest.fn();
const onDeleteAllClick = vi.fn();
const { container, getByRole } = render(<WithUnsentMessages onDeleteAllClick={onDeleteAllClick} />);
expect(container).toMatchSnapshot();
@@ -47,7 +48,7 @@ describe("RoomStatusBarView", () => {
expect(onDeleteAllClick).toHaveBeenCalled();
});
it("renders unsent messages and resends all", async () => {
const onResendAllClick = jest.fn();
const onResendAllClick = vi.fn();
const { container, getByRole } = render(<WithUnsentMessages onResendAllClick={onResendAllClick} />);
expect(container).toMatchSnapshot();
@@ -56,7 +57,7 @@ describe("RoomStatusBarView", () => {
expect(onResendAllClick).toHaveBeenCalled();
});
it("renders local room error", async () => {
const onRetryRoomCreationClick = jest.fn();
const onRetryRoomCreationClick = vi.fn();
const { container, getByRole } = render(
<WithLocalRoomRetry onRetryRoomCreationClick={onRetryRoomCreationClick} />,
);

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`RoomStatusBarView renders connection lost 1`] = `
exports[`RoomStatusBarView > renders connection lost 1`] = `
<div>
<div
aria-labelledby="_r_0_"
@@ -50,7 +50,7 @@ exports[`RoomStatusBarView renders connection lost 1`] = `
</div>
`;
exports[`RoomStatusBarView renders consent link 1`] = `
exports[`RoomStatusBarView > renders consent link 1`] = `
<div>
<div
aria-labelledby="_r_2_"
@@ -108,7 +108,7 @@ exports[`RoomStatusBarView renders consent link 1`] = `
</div>
`;
exports[`RoomStatusBarView renders local room error 1`] = `
exports[`RoomStatusBarView > renders local room error 1`] = `
<div>
<div
aria-labelledby="_r_6_"
@@ -171,7 +171,7 @@ exports[`RoomStatusBarView renders local room error 1`] = `
</div>
`;
exports[`RoomStatusBarView renders resource limit error 1`] = `
exports[`RoomStatusBarView > renders resource limit error 1`] = `
<div>
<div
aria-labelledby="_r_1_"
@@ -234,7 +234,7 @@ exports[`RoomStatusBarView renders resource limit error 1`] = `
</div>
`;
exports[`RoomStatusBarView renders unsent messages 1`] = `
exports[`RoomStatusBarView > renders unsent messages 1`] = `
<div>
<div
aria-labelledby="_r_3_"
@@ -329,7 +329,7 @@ exports[`RoomStatusBarView renders unsent messages 1`] = `
</div>
`;
exports[`RoomStatusBarView renders unsent messages and deletes all 1`] = `
exports[`RoomStatusBarView > renders unsent messages and deletes all 1`] = `
<div>
<div
aria-labelledby="_r_4_"
@@ -424,7 +424,7 @@ exports[`RoomStatusBarView renders unsent messages and deletes all 1`] = `
</div>
`;
exports[`RoomStatusBarView renders unsent messages and resends all 1`] = `
exports[`RoomStatusBarView > renders unsent messages and resends all 1`] = `
<div>
<div
aria-labelledby="_r_5_"

View File

@@ -5,13 +5,14 @@ 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 "@testing-library/jest-dom";
import fetchMock from "@fetch-mock/jest";
import fetchMock from "@fetch-mock/vitest";
import { cleanup } from "@test-utils";
import { afterEach } from "vitest";
import { setLanguage } from "../../src/utils/i18n";
import en from "../i18n/strings/en_EN.json";
export function setupLanguageMock(): void {
function setupLanguageMock(): void {
fetchMock
.get("end:/i18n/languages.json", {
en: "en_EN.json",
@@ -22,3 +23,7 @@ setupLanguageMock();
fetchMock.mockGlobal();
setLanguage("en");
afterEach(() => {
cleanup();
});

View File

@@ -7,7 +7,7 @@ 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.
*/
// Copied from element-web/test/test-utils because, seemingly, if we
// Copied from element-web/test/@test-utils because, seemingly, if we
// set that as the modules directory to use it directly, it fails to
// actually put the right thing in the context somehow.

View File

@@ -5,6 +5,8 @@
* Please see LICENSE files in the repository root for full details.
*/
import { describe, it, expect } from "vitest";
import { I18nApi } from "./I18nApi";
describe("I18nApi", () => {

View File

@@ -5,13 +5,15 @@
* Please see LICENSE files in the repository root for full details.
*/
import { describe, it, beforeAll, vi, expect } from "vitest";
import { humanizeTime } from "./humanize";
describe("humanizeTime", () => {
const now = new Date("2025-08-01T12:00:00Z").getTime();
beforeAll(() => {
jest.useFakeTimers().setSystemTime(now);
vi.useFakeTimers().setSystemTime(now);
});
it.each([

View File

@@ -6,39 +6,40 @@
*/
import counterpart from "counterpart";
import { vi, describe, it, beforeEach, expect } from "vitest";
import { registerTranslations, setMissingEntryGenerator, getLocale, setLocale } from "./i18n";
describe("i18n utils", () => {
beforeEach(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});
it("should wrap registerTranslations", () => {
jest.spyOn(counterpart, "registerTranslations");
vi.spyOn(counterpart, "registerTranslations");
registerTranslations("en", { test: "This is a test" });
expect(counterpart.registerTranslations).toHaveBeenCalledWith("en", { test: "This is a test" });
});
it("should wrap setMissingEntryGenerator", () => {
jest.spyOn(counterpart, "setMissingEntryGenerator");
vi.spyOn(counterpart, "setMissingEntryGenerator");
const dummyFn = jest.fn();
const dummyFn = vi.fn();
setMissingEntryGenerator(dummyFn);
expect(counterpart.setMissingEntryGenerator).toHaveBeenCalledWith(dummyFn);
});
it("should wrap getLocale", () => {
jest.spyOn(counterpart, "getLocale");
vi.spyOn(counterpart, "getLocale");
getLocale();
expect(counterpart.getLocale).toHaveBeenCalled();
});
it("should wrap setLocale", () => {
jest.spyOn(counterpart, "setLocale");
vi.spyOn(counterpart, "setLocale");
setLocale("en");
expect(counterpart.setLocale).toHaveBeenCalledWith("en");

View File

@@ -6,6 +6,8 @@ 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 { describe, it, expect } from "vitest";
import { clamp, defaultNumber, percentageOf, percentageWithin, sum } from "./numbers";
describe("numbers", () => {

View File

@@ -5,6 +5,7 @@ Please see LICENSE files in the repository root for full details.
*/
import { EventEmitter } from "events";
import { describe, it, vi, expect } from "vitest";
import { Disposables } from "..";
@@ -21,11 +22,11 @@ describe("Disposable", () => {
const item1 = {
foo: 5,
dispose: jest.fn(),
dispose: vi.fn(),
};
disposables.track(item1);
const item2 = jest.fn();
const item2 = vi.fn();
disposables.track(item2);
disposables.dispose();
@@ -38,7 +39,7 @@ describe("Disposable", () => {
const disposables = new Disposables();
disposables.dispose();
expect(() => {
disposables.track(jest.fn);
disposables.track(vi.fn);
}).toThrow();
});
@@ -46,7 +47,7 @@ describe("Disposable", () => {
const disposables = new Disposables();
const emitter = new EventEmitter();
const fn = jest.fn();
const fn = vi.fn();
disposables.trackListener(emitter, "FooEvent", fn);
emitter.emit("FooEvent");
expect(fn).toHaveBeenCalled();

View File

@@ -5,6 +5,8 @@ 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 { describe, it, vi, expect } from "vitest";
import { Snapshot } from "..";
interface TestSnapshot {
@@ -15,26 +17,26 @@ interface TestSnapshot {
describe("Snapshot", () => {
it("should accept an initial value", () => {
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, jest.fn());
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, vi.fn());
expect(snapshot.current).toStrictEqual({ key1: "foo", key2: 5, key3: false });
});
it("should call emit callback when state changes", () => {
const emit = jest.fn();
const emit = vi.fn();
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, emit);
snapshot.merge({ key3: true });
expect(emit).toHaveBeenCalledTimes(1);
});
it("should swap out entire snapshot on set call", () => {
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, jest.fn());
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, vi.fn());
const newValue = { key1: "bar", key2: 8, key3: true };
snapshot.set(newValue);
expect(snapshot.current).toStrictEqual(newValue);
});
it("should merge partial snapshot on merge call", () => {
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, jest.fn());
const snapshot = new Snapshot<TestSnapshot>({ key1: "foo", key2: 5, key3: false }, vi.fn());
snapshot.merge({ key2: 10 });
expect(snapshot.current).toStrictEqual({ key1: "foo", key2: 10, key3: false });
});

View File

@@ -4,7 +4,8 @@ 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 { renderHook } from "jest-matrix-react";
import { renderHook } from "@test-utils";
import { describe, it, expect } from "vitest";
import { BaseViewModel } from "../BaseViewModel";
import { useCreateAutoDisposedViewModel } from "../useCreateAutoDisposedViewModel";