diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 73358acc..eaefe652 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -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
diff --git a/.storybook/main.js b/.storybook/main.js
deleted file mode 100644
index 9d03e947..00000000
--- a/.storybook/main.js
+++ /dev/null
@@ -1,25 +0,0 @@
-const svgrPlugin = require("vite-plugin-svgr");
-const path = require("path");
-
-module.exports = {
- stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
- framework: "@storybook/react",
- core: {
- builder: "storybook-builder-vite",
- },
- async viteFinal(config) {
- config.plugins = config.plugins.filter(
- (item) =>
- !(
- Array.isArray(item) &&
- item.length > 0 &&
- item[0].name === "vite-plugin-mdx"
- ),
- );
- config.plugins.push(svgrPlugin());
- config.resolve = config.resolve || {};
- config.resolve.dedupe = config.resolve.dedupe || [];
- config.resolve.dedupe.push("react", "react-dom", "matrix-js-sdk");
- return config;
- },
-};
diff --git a/.storybook/preview.jsx b/.storybook/preview.jsx
deleted file mode 100644
index 928e10eb..00000000
--- a/.storybook/preview.jsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { addDecorator } from "@storybook/react";
-import { MemoryRouter } from "react-router-dom";
-import { usePageFocusStyle } from "../src/usePageFocusStyle";
-import { OverlayProvider } from "@react-aria/overlays";
-import "../src/index.css";
-
-export const parameters = {
- actions: { argTypesRegex: "^on[A-Z].*" },
- controls: {
- matchers: {
- color: /(background|color)$/i,
- date: /Date$/,
- },
- },
-};
-
-addDecorator((story) => {
- usePageFocusStyle();
- return (
-
- {story()}
-
- );
-});
diff --git a/codecov.yaml b/codecov.yaml
new file mode 100644
index 00000000..30c038ec
--- /dev/null
+++ b/codecov.yaml
@@ -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%
diff --git a/package.json b/package.json
index f020b70e..175a5655 100644
--- a/package.json
+++ b/package.json
@@ -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": {
@@ -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",
@@ -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",
@@ -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",
diff --git a/src/Avatar.tsx b/src/Avatar.tsx
index 06583445..abe01539 100644
--- a/src/Avatar.tsx
+++ b/src/Avatar.tsx
@@ -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 {
diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx
index 8d13e315..8516a13d 100644
--- a/src/ClientContext.tsx
+++ b/src/ClientContext.tsx
@@ -39,7 +39,7 @@ import {
CryptoStoreIntegrityError,
fallbackICEServerAllowed,
initClient,
-} from "./matrix-utils";
+} from "./utils/matrix";
import { widget } from "./widget";
import {
PosthogAnalytics,
diff --git a/src/Toast.test.tsx b/src/Toast.test.tsx
new file mode 100644
index 00000000..e35e135c
--- /dev/null
+++ b/src/Toast.test.tsx
@@ -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(
+ {}}>
+ Hello world!
+ ,
+ );
+ expect(queryByRole("dialog")).toBe(null);
+ const { getByRole } = render(
+ {}}>
+ Hello world!
+ ,
+ );
+ expect(getByRole("dialog")).toMatchSnapshot();
+ });
+
+ test("dismisses itself after the specified timeout", () => {
+ withFakeTimers(() => {
+ const onDismiss = vi.fn();
+ render(
+
+ Hello world!
+ ,
+ );
+ vi.advanceTimersByTime(2000);
+ expect(onDismiss).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/src/Toast.tsx b/src/Toast.tsx
index fffbec97..e9c534f1 100644
--- a/src/Toast.tsx
+++ b/src/Toast.tsx
@@ -86,7 +86,7 @@ export const Toast: FC = ({
-
+
{
- beforeAll(() => {
- vi.mocked(Config.defaultServerName).mockReturnValue("call.ems.host");
- });
-
describe("handles URL with /room/", () => {
it("and nothing else", () => {
expect(
diff --git a/test/__snapshots__/Toast-test.tsx.snap b/src/__snapshots__/Toast-test.tsx.snap
similarity index 92%
rename from test/__snapshots__/Toast-test.tsx.snap
rename to src/__snapshots__/Toast-test.tsx.snap
index 7edfdcf7..2a424474 100644
--- a/test/__snapshots__/Toast-test.tsx.snap
+++ b/src/__snapshots__/Toast-test.tsx.snap
@@ -2,7 +2,6 @@
exports[`Toast renders 1`] = `