mirror of
https://github.com/vector-im/element-call.git
synced 2024-11-24 00:38:31 +08:00
Add back keyboard toast tests (#2582)
* Fix global-jsdom initialization * add back toast tests * fix keyboard input events. * add jsdom types
This commit is contained in:
parent
e9fc5dadd9
commit
3e57a7692c
@ -45,6 +45,7 @@
|
|||||||
"@testing-library/user-event": "^14.5.1",
|
"@testing-library/user-event": "^14.5.1",
|
||||||
"@types/content-type": "^1.1.5",
|
"@types/content-type": "^1.1.5",
|
||||||
"@types/grecaptcha": "^3.0.9",
|
"@types/grecaptcha": "^3.0.9",
|
||||||
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/lodash": "^4.14.199",
|
"@types/lodash": "^4.14.199",
|
||||||
"@types/node": "^20.0.0",
|
"@types/node": "^20.0.0",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||||||
|
|
||||||
import { describe, expect, test, vi } from "vitest";
|
import { describe, expect, test, vi } from "vitest";
|
||||||
import { render, configure } from "@testing-library/react";
|
import { render, configure } from "@testing-library/react";
|
||||||
|
import userEvent from "@testing-library/user-event";
|
||||||
|
|
||||||
import { Toast } from "../src/Toast";
|
import { Toast } from "../src/Toast";
|
||||||
import { withFakeTimers } from "./utils/test";
|
import { withFakeTimers } from "./utils/test";
|
||||||
@ -24,6 +25,9 @@ configure({
|
|||||||
defaultHidden: true,
|
defaultHidden: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Test Explanation:
|
||||||
|
// This test the toast. We need to use { document: window.document } because the toast listens
|
||||||
|
// for user input on `window`.
|
||||||
describe("Toast", () => {
|
describe("Toast", () => {
|
||||||
test("renders", () => {
|
test("renders", () => {
|
||||||
const { queryByRole } = render(
|
const { queryByRole } = render(
|
||||||
@ -40,6 +44,33 @@ describe("Toast", () => {
|
|||||||
expect(getByRole("dialog")).toMatchSnapshot();
|
expect(getByRole("dialog")).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("dismisses when Esc is pressed", async () => {
|
||||||
|
const user = userEvent.setup({ document: window.document });
|
||||||
|
const onDismiss = vi.fn();
|
||||||
|
const { debug } = render(
|
||||||
|
<Toast open={true} onDismiss={onDismiss}>
|
||||||
|
Hello world!
|
||||||
|
</Toast>,
|
||||||
|
);
|
||||||
|
debug();
|
||||||
|
await user.keyboard("[Escape]");
|
||||||
|
expect(onDismiss).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("dismisses when background is clicked", async () => {
|
||||||
|
const user = userEvent.setup();
|
||||||
|
const onDismiss = vi.fn();
|
||||||
|
const { getByRole, unmount } = render(
|
||||||
|
<Toast open={true} onDismiss={onDismiss}>
|
||||||
|
Hello world!
|
||||||
|
</Toast>,
|
||||||
|
);
|
||||||
|
const background = getByRole("dialog").previousSibling! as Element;
|
||||||
|
await user.click(background);
|
||||||
|
expect(onDismiss).toHaveBeenCalled();
|
||||||
|
unmount();
|
||||||
|
});
|
||||||
|
|
||||||
test("dismisses itself after the specified timeout", () => {
|
test("dismisses itself after the specified timeout", () => {
|
||||||
withFakeTimers(() => {
|
withFakeTimers(() => {
|
||||||
const onDismiss = vi.fn();
|
const onDismiss = vi.fn();
|
||||||
|
@ -22,6 +22,12 @@ import userEvent from "@testing-library/user-event";
|
|||||||
|
|
||||||
import { useCallViewKeyboardShortcuts } from "../src/useCallViewKeyboardShortcuts";
|
import { useCallViewKeyboardShortcuts } from "../src/useCallViewKeyboardShortcuts";
|
||||||
|
|
||||||
|
// Test Explanation:
|
||||||
|
// - The main objective is to test `useCallViewKeyboardShortcuts`.
|
||||||
|
// The TestComponent just wraps a button around that hook.
|
||||||
|
// - We need to set `userEvent` to the `{document = window.document}` since we are testing the
|
||||||
|
// `useCallViewKeyboardShortcuts` hook here. Which is listening to window.
|
||||||
|
|
||||||
interface TestComponentProps {
|
interface TestComponentProps {
|
||||||
setMicrophoneMuted: (muted: boolean) => void;
|
setMicrophoneMuted: (muted: boolean) => void;
|
||||||
onButtonClick?: () => void;
|
onButtonClick?: () => void;
|
||||||
@ -40,24 +46,33 @@ const TestComponent: FC<TestComponentProps> = ({
|
|||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
<Button onClick={onButtonClick}>I'm a button</Button>
|
<Button onClick={onButtonClick}>TEST</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
test("spacebar unmutes", async () => {
|
test("spacebar unmutes", async () => {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup({ document: window.document });
|
||||||
let muted = true;
|
let muted = true;
|
||||||
render(<TestComponent setMicrophoneMuted={(m) => (muted = m)} />);
|
render(
|
||||||
|
<TestComponent
|
||||||
|
onButtonClick={() => (muted = false)}
|
||||||
|
setMicrophoneMuted={(m) => {
|
||||||
|
muted = m;
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
await user.keyboard("[Space>]");
|
await user.keyboard("[Space>]");
|
||||||
expect(muted).toBe(false);
|
expect(muted).toBe(false);
|
||||||
await user.keyboard("[/Space]");
|
await user.keyboard("[/Space]");
|
||||||
|
|
||||||
expect(muted).toBe(true);
|
expect(muted).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("spacebar prioritizes pressing a button", async () => {
|
test("spacebar prioritizes pressing a button", async () => {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup({ document: window.document });
|
||||||
|
|
||||||
const setMuted = vi.fn();
|
const setMuted = vi.fn();
|
||||||
const onClick = vi.fn();
|
const onClick = vi.fn();
|
||||||
render(
|
render(
|
||||||
@ -71,7 +86,7 @@ test("spacebar prioritizes pressing a button", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("unmuting happens in place of the default action", async () => {
|
test("unmuting happens in place of the default action", async () => {
|
||||||
const user = userEvent.setup();
|
const user = userEvent.setup({ document: window.document });
|
||||||
const defaultPrevented = vi.fn();
|
const defaultPrevented = vi.fn();
|
||||||
// In the real application, we mostly just want the spacebar shortcut to avoid
|
// In the real application, we mostly just want the spacebar shortcut to avoid
|
||||||
// scrolling the page. But to test that here in JSDOM, we need some kind of
|
// scrolling the page. But to test that here in JSDOM, we need some kind of
|
||||||
|
@ -13,13 +13,12 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "global-jsdom/register";
|
import "global-jsdom/register";
|
||||||
|
import globalJsdom from "global-jsdom";
|
||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import posthog from "posthog-js";
|
import posthog from "posthog-js";
|
||||||
import { initReactI18next } from "react-i18next";
|
import { initReactI18next } from "react-i18next";
|
||||||
import { afterEach } from "vitest";
|
import { afterEach, beforeEach } from "vitest";
|
||||||
import { cleanup } from "@testing-library/react";
|
import { cleanup } from "@testing-library/react";
|
||||||
|
|
||||||
import { Config } from "./config/Config";
|
import { Config } from "./config/Config";
|
||||||
@ -36,4 +35,12 @@ i18n.use(initReactI18next).init({
|
|||||||
Config.initDefault();
|
Config.initDefault();
|
||||||
posthog.opt_out_capturing();
|
posthog.opt_out_capturing();
|
||||||
|
|
||||||
afterEach(cleanup);
|
// We need to cleanup the global jsDom
|
||||||
|
// Otherwise we will run into issues with async input test overlapping and throwing.
|
||||||
|
|
||||||
|
let cleanupJsDom: { (): void };
|
||||||
|
beforeEach(() => (cleanupJsDom = globalJsdom()));
|
||||||
|
afterEach(() => {
|
||||||
|
cleanupJsDom();
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
21
yarn.lock
21
yarn.lock
@ -2854,6 +2854,15 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
|
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
|
||||||
integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
|
integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
|
||||||
|
|
||||||
|
"@types/jsdom@^21.1.7":
|
||||||
|
version "21.1.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-21.1.7.tgz#9edcb09e0b07ce876e7833922d3274149c898cfa"
|
||||||
|
integrity sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
"@types/tough-cookie" "*"
|
||||||
|
parse5 "^7.0.0"
|
||||||
|
|
||||||
"@types/json5@^0.0.29":
|
"@types/json5@^0.0.29":
|
||||||
version "0.0.29"
|
version "0.0.29"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||||
@ -2869,6 +2878,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
|
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
|
||||||
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
|
integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==
|
||||||
|
|
||||||
|
"@types/node@*":
|
||||||
|
version "22.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.1.tgz#de01dce265f6b99ed32b295962045d10b5b99560"
|
||||||
|
integrity sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==
|
||||||
|
dependencies:
|
||||||
|
undici-types "~6.19.2"
|
||||||
|
|
||||||
"@types/node@>=13.7.0":
|
"@types/node@>=13.7.0":
|
||||||
version "22.1.0"
|
version "22.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.1.0.tgz#6d6adc648b5e03f0e83c78dc788c2b037d0ad94b"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.1.0.tgz#6d6adc648b5e03f0e83c78dc788c2b037d0ad94b"
|
||||||
@ -2940,6 +2956,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz#51b1c00b516a5774ada5d611e65eb123f988ef8d"
|
resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz#51b1c00b516a5774ada5d611e65eb123f988ef8d"
|
||||||
integrity sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==
|
integrity sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==
|
||||||
|
|
||||||
|
"@types/tough-cookie@*":
|
||||||
|
version "4.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304"
|
||||||
|
integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==
|
||||||
|
|
||||||
"@types/uuid@10":
|
"@types/uuid@10":
|
||||||
version "10.0.0"
|
version "10.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d"
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d"
|
||||||
|
Loading…
Reference in New Issue
Block a user