Skip to content

Commit

Permalink
Clean up our tests in preparation for the testing sprint (#2466)
Browse files Browse the repository at this point in the history
* Fix coverage reporting

Codecov hasn't been working recently because Vitest doesn't report coverage by default.

* Suppress some noisy log lines

Closes #686

* Store test files alongside source files

This way we benefit from not having to maintain the same directory structure twice, and our linters etc. will actually lint test files by default.

* Stop using Vitest globals

Vitest provides globals primarily to make the transition from Jest more smooth. But importing its functions explicitly is considered a better pattern, and we have so few tests right now that it's trivial to migrate them all.

* Remove Storybook directory

We no longer use Storybook.

* Configure Codecov

Add a coverage gate for all new changes and disable its comments.

* upgrade vitest

---------

Co-authored-by: Timo <toger5@hotmail.de>
  • Loading branch information
robintown and toger5 authored Aug 27, 2024
1 parent 3a75447 commit 5eaabcf
Show file tree
Hide file tree
Showing 41 changed files with 470 additions and 180 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ jobs:
- name: Install dependencies
run: "yarn install"
- name: Vitest
run: "yarn run test"
run: "yarn run test:coverage"
- name: Upload to codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4
with:
flags: unittests
fail_ci_if_error: true
25 changes: 0 additions & 25 deletions .storybook/main.js

This file was deleted.

24 changes: 0 additions & 24 deletions .storybook/preview.jsx

This file was deleted.

13 changes: 13 additions & 0 deletions codecov.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Don't post comments on PRs; they're noisy and the same information can be
# gotten through the checks section at the bottom of the PR anyways
comment: false
coverage:
status:
project:
default:
# Track the impact of changes on overall coverage without blocking PRs
informational: true
patch:
default:
# Expect 80% coverage on all lines that a PR touches
target: 80%
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"i18n": "node_modules/i18next-parser/bin/cli.js",
"i18n:check": "node_modules/i18next-parser/bin/cli.js --fail-on-warnings --fail-on-update",
"test": "vitest",
"test:coverage": "vitest run --coverage",
"test:coverage": "vitest --coverage",
"backend": "docker-compose -f backend-docker-compose.yml up"
},
"dependencies": {
Expand Down Expand Up @@ -95,7 +95,7 @@
"@types/content-type": "^1.1.5",
"@types/dom-screen-wake-lock": "^1.0.1",
"@types/dompurify": "^3.0.2",
"@types/grecaptcha": "^3.0.4",
"@types/grecaptcha": "^3.0.9",
"@types/node": "^20.0.0",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
Expand All @@ -104,6 +104,7 @@
"@types/uuid": "10",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"@vitest/coverage-v8": "^2.0.5",
"babel-loader": "^9.0.0",
"babel-plugin-transform-vite-meta-env": "^1.0.3",
"eslint": "^8.14.0",
Expand All @@ -116,6 +117,7 @@
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^4.5.0",
"eslint-plugin-unicorn": "^55.0.0",
"global-jsdom": "^24.0.0",
"i18next-parser": "^9.0.0",
"jsdom": "^25.0.0",
"prettier": "^3.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ limitations under the License.
import { useMemo, FC } from "react";
import { Avatar as CompoundAvatar } from "@vector-im/compound-web";

import { getAvatarUrl } from "./matrix-utils";
import { getAvatarUrl } from "./utils/matrix";
import { useClient } from "./ClientContext";

export enum Size {
Expand Down
2 changes: 1 addition & 1 deletion src/ClientContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
CryptoStoreIntegrityError,
fallbackICEServerAllowed,
initClient,
} from "./matrix-utils";
} from "./utils/matrix";
import { widget } from "./widget";
import {
PosthogAnalytics,
Expand Down
55 changes: 55 additions & 0 deletions src/Toast.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright 2023 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import { describe, expect, test, vi } from "vitest";
import { render, configure } from "@testing-library/react";

import { Toast } from "../src/Toast";
import { withFakeTimers } from "./utils/test";

configure({
defaultHidden: true,
});

describe("Toast", () => {
test("renders", () => {
const { queryByRole } = render(
<Toast open={false} onDismiss={() => {}}>
Hello world!
</Toast>,
);
expect(queryByRole("dialog")).toBe(null);
const { getByRole } = render(
<Toast open={true} onDismiss={() => {}}>
Hello world!
</Toast>,
);
expect(getByRole("dialog")).toMatchSnapshot();
});

test("dismisses itself after the specified timeout", () => {
withFakeTimers(() => {
const onDismiss = vi.fn();
render(
<Toast open={true} onDismiss={onDismiss} autoDismiss={2000}>
Hello world!
</Toast>,
);
vi.advanceTimersByTime(2000);
expect(onDismiss).toHaveBeenCalled();
});
});
});
2 changes: 1 addition & 1 deletion src/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const Toast: FC<Props> = ({
<DialogOverlay
className={classNames(overlayStyles.bg, overlayStyles.animate)}
/>
<DialogContent asChild>
<DialogContent aria-describedby={undefined} asChild>
<DialogClose
className={classNames(
overlayStyles.overlay,
Expand Down
11 changes: 2 additions & 9 deletions test/UrlParams-test.ts → src/UrlParams.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { vi } from "vitest";
import { describe, expect, it } from "vitest";

import { getRoomIdentifierFromUrl } from "../src/UrlParams";
import { Config } from "../src/config/Config";

const ROOM_NAME = "roomNameHere";
const ROOM_ID = "!d45f138fsd";
const ORIGIN = "https://call.element.io";
const HOMESERVER = "call.ems.host";

vi.mock("../src/config/Config");
const HOMESERVER = "localhost";

describe("UrlParams", () => {
beforeAll(() => {
vi.mocked(Config.defaultServerName).mockReturnValue("call.ems.host");
});

describe("handles URL with /room/", () => {
it("and nothing else", () => {
expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

exports[`Toast renders 1`] = `
<button
aria-describedby="radix-:r5:"
aria-labelledby="radix-:r4:"
class="overlay animate toast"
data-state="open"
Expand Down
21 changes: 21 additions & 0 deletions src/__snapshots__/Toast.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Toast > renders 1`] = `
<button
aria-labelledby="radix-:r4:"
class="overlay animate toast"
data-state="open"
id="radix-:r3:"
role="dialog"
style="pointer-events: auto;"
tabindex="-1"
type="button"
>
<h3
class="_typography_yh5dq_162 _font-body-sm-semibold_yh5dq_45"
id="radix-:r4:"
>
Hello world!
</h3>
</button>
`;
2 changes: 1 addition & 1 deletion src/analytics/PosthogAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export class PosthogAnalytics {
advanced_disable_decide: true,
});
this.enabled = true;
} else {
} else if (import.meta.env.MODE !== "test") {
logger.info(
"Posthog is not enabled because there is no api key or no host given in the config",
);
Expand Down
2 changes: 1 addition & 1 deletion src/auth/useInteractiveLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
MatrixClient,
} from "matrix-js-sdk/src/matrix";

import { initClient } from "../matrix-utils";
import { initClient } from "../utils/matrix";
import { Session } from "../ClientContext";

export function useInteractiveLogin(): (
Expand Down
2 changes: 1 addition & 1 deletion src/auth/useInteractiveRegistration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
RegisterResponse,
} from "matrix-js-sdk/src/matrix";

import { initClient } from "../matrix-utils";
import { initClient } from "../utils/matrix";
import { Session } from "../ClientContext";
import { Config } from "../config/Config";
import { widget } from "../widget";
Expand Down
4 changes: 2 additions & 2 deletions src/auth/useRecaptcha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// import "@types/grecaptcha";
import { useEffect, useCallback, useRef, useState } from "react";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";

import { translatedError } from "../TranslatedError";

declare global {
interface Window {
mxOnRecaptchaLoaded: () => void;
// grecaptcha: any;
}
}

Expand Down
12 changes: 12 additions & 0 deletions src/config/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ export class Config {
return Config.internalInstance.initPromise;
}

/**
* This is a alternative initializer that does not load anything
* from a hosted config file but instead just initializes the conifg using the
* default config.
*
* It is supposed to only be used in tests. (It is executed in `vite.setup.js`)
*/
public static initDefault(): void {
Config.internalInstance = new Config();
Config.internalInstance.config = { ...DEFAULT_CONFIG };
}

// Convenience accessors
public static defaultHomeserverUrl(): string | undefined {
return (
Expand Down
15 changes: 7 additions & 8 deletions test/home/CallList-test.tsx → src/home/CallList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@ limitations under the License.
*/

import { render, RenderResult } from "@testing-library/react";
import { CallList } from "../../src/home/CallList";
import { MatrixClient } from "matrix-js-sdk";
import { GroupCallRoom } from "../../src/home/useGroupCallRooms";
import { MemoryRouter } from "react-router-dom";
import { ClientProvider } from "../../src/ClientContext";
import { describe, expect, it } from "vitest";

import { CallList } from "../../src/home/CallList";
import { GroupCallRoom } from "../../src/home/useGroupCallRooms";

describe("CallList", () => {
const renderComponent = (rooms: GroupCallRoom[]): RenderResult => {
return render(
<ClientProvider>
<MemoryRouter>
<CallList client={{} as MatrixClient} rooms={rooms} />
</MemoryRouter>
</ClientProvider>,
<MemoryRouter>
<CallList client={{} as MatrixClient} rooms={rooms} />
</MemoryRouter>,
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/home/CallList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { FC } from "react";
import { CopyButton } from "../button";
import { Avatar, Size } from "../Avatar";
import styles from "./CallList.module.css";
import { getAbsoluteRoomUrl, getRelativeRoomUrl } from "../matrix-utils";
import { getAbsoluteRoomUrl, getRelativeRoomUrl } from "../utils/matrix";
import { Body } from "../typography/Typography";
import { GroupCallRoom } from "./useGroupCallRooms";
import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement";
Expand Down
2 changes: 1 addition & 1 deletion src/home/RegisteredView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
getRelativeRoomUrl,
roomAliasLocalpartFromRoomName,
sanitiseRoomNameInput,
} from "../matrix-utils";
} from "../utils/matrix";
import { useGroupCallRooms } from "./useGroupCallRooms";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
import commonStyles from "./common.module.css";
Expand Down
2 changes: 1 addition & 1 deletion src/home/UnauthenticatedView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
getRelativeRoomUrl,
roomAliasLocalpartFromRoomName,
sanitiseRoomNameInput,
} from "../matrix-utils";
} from "../utils/matrix";
import { useInteractiveRegistration } from "../auth/useInteractiveRegistration";
import { JoinExistingCallModal } from "./JoinExistingCallModal";
import { useRecaptcha } from "../auth/useRecaptcha";
Expand Down
2 changes: 2 additions & 0 deletions test/initializer-test.ts → src/initializer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import { expect, test } from "vitest";

import { Initializer } from "../src/initializer";

test("initBeforeReact sets font family from URL param", () => {
Expand Down
Loading

0 comments on commit 5eaabcf

Please sign in to comment.