Skip to content

Commit

Permalink
tests: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nahoc committed May 7, 2024
1 parent 486941b commit e0037bf
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 9 deletions.
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ biome.jsonc
components.json
tsconfig.tsbuildinfo
*.test.*
*.spec.*
*.spec.*
vitest.config.ts
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ Building blocks for UI applications at RISC Zero.

> #### General
>
> When making code changes, please have the [Biome VSCode extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) installed.
> When making code changes, please have the [Biome VSCode extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) installed.
### Tests

All test files named with the pattern `*.spec.*` are ran using `bun test` while all files named `*.test.*` are ran through `vitest`.
32 changes: 32 additions & 0 deletions hooks/use-event-listener.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { renderHook } from '@testing-library/react-hooks';
import type { RefObject } from 'react';
import { useEventListener } from './use-event-listener';
import { vi } from 'vitest';

describe('useEventListener', () => {
it('should call handler when the event is triggered', () => {
const handler = vi.fn();
const event = new Event('click');
const ref: RefObject<HTMLDivElement> = { current: document.createElement('div') };

renderHook(() => useEventListener('click', handler, ref));

ref.current?.dispatchEvent(event);

expect(handler).toHaveBeenCalledWith(event);
});

it('should not call handler after unmount', () => {
const handler = vi.fn();
const event = new Event('click');
const ref: RefObject<HTMLDivElement> = { current: document.createElement('div') };

const { unmount } = renderHook(() => useEventListener('click', handler, ref));

unmount();

ref.current?.dispatchEvent(event);

expect(handler).not.toHaveBeenCalled();
});
});
74 changes: 74 additions & 0 deletions hooks/use-local-storage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { renderHook, act } from '@testing-library/react-hooks';
import { useRef } from 'react';
import { useEventListener } from './use-event-listener';
import { vi } from 'vitest';

describe('useEventListener', () => {
it('adds event listener to window when no element is provided', () => {
const handler = vi.fn();
const { unmount } = renderHook(() => useEventListener('click', handler));

act(() => {
window.dispatchEvent(new Event('click'));
});

expect(handler).toHaveBeenCalled();

unmount();
});

it('adds event listener to provided element', () => {
const handler = vi.fn();
const { result, unmount } = renderHook(() => {
const ref = useRef<HTMLDivElement>(document.createElement('div'));
useEventListener('click', handler, ref);
return ref;
});

act(() => {
result.current?.current?.dispatchEvent(new Event('click'));
});

expect(handler).toHaveBeenCalled();

unmount();
});

it('removes event listener when component unmounts', () => {
const handler = vi.fn();
const { unmount } = renderHook(() => useEventListener('click', handler));

unmount();

act(() => {
window.dispatchEvent(new Event('click'));
});

expect(handler).not.toHaveBeenCalled();
});

it('updates event listener when handler changes', () => {
const handler1 = vi.fn();
const handler2 = vi.fn();
const { rerender, unmount } = renderHook(
({ handler }) => useEventListener('click', handler),
{ initialProps: { handler: handler1 } }
);

act(() => {
window.dispatchEvent(new Event('click'));
});

expect(handler1).toHaveBeenCalled();

rerender({ handler: handler2 });

act(() => {
window.dispatchEvent(new Event('click'));
});

expect(handler2).toHaveBeenCalled();

unmount();
});
});
12 changes: 12 additions & 0 deletions hooks/use-mounted.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { renderHook } from '@testing-library/react-hooks';
import { useMounted } from './use-mounted';

describe('useMounted', () => {
it('should return true after the component has been mounted', () => {
const { result, waitForNextUpdate } = renderHook(() => useMounted());

waitForNextUpdate().then(() => {
expect(result.current).toBe(true);
});
});
});
16 changes: 11 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
{
"name": "@risc0/ui",
"version": "0.0.64",
"version": "0.0.65",
"sideEffects": false,
"type": "module",
"scripts": {
"bump:version": "bunx changelogen --bump --no-output",
"check": "tsc && bunx @biomejs/biome check . --apply-unsafe",
"prepare": "npx husky",
"sort-package": "bunx sort-package-json 'package.json'",
"test": "bun test spec"
"test": "bun test spec && vitest run --silent"
},
"dependencies": {
"@biomejs/biome": "1.7.3",
"@radix-ui/react-avatar": "1.0.4",
"@radix-ui/react-checkbox": "1.0.4",
"@radix-ui/react-dialog": "1.0.5",
Expand All @@ -28,8 +27,6 @@
"@radix-ui/react-switch": "1.0.3",
"@radix-ui/react-tabs": "1.0.4",
"@radix-ui/react-tooltip": "1.0.7",
"@types/jest": "29.5.12",
"@types/lodash-es": "4.17.12",
"autoprefixer": "10.4.19",
"class-variance-authority": "0.7.0",
"clsx": "2.1.1",
Expand All @@ -45,6 +42,15 @@
"tailwindcss-animate": "1.0.7",
"typescript": "5.4.5"
},
"devDependencies": {
"@biomejs/biome": "1.7.3",
"@testing-library/react-hooks": "8.0.1",
"@types/jest": "29.5.12",
"@types/lodash-es": "4.17.12",
"@vitejs/plugin-react-swc": "3.6.0",
"happy-dom": "14.10.1",
"vitest": "1.6.0"
},
"peerDependencies": {
"@types/react": "^18",
"@types/react-dom": "^18",
Expand Down
25 changes: 25 additions & 0 deletions utils/parse-json.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { parseJson } from './parse-json';

describe('parseJson', () => {
it('should return an object when a valid JSON string is passed', () => {
const jsonString = '{"key":"value"}';
expect(parseJson(jsonString)).toEqual({ key: 'value' });
});

it('should return undefined when an invalid JSON string is passed', () => {
const invalidJsonString = '{key:value}';
expect(parseJson(invalidJsonString)).toBeUndefined();
});

it('should return undefined when "undefined" is passed', () => {
expect(parseJson("undefined")).toBeUndefined();
});

it('should return undefined when null is passed', () => {
expect(parseJson(null)).toBeUndefined();
});

it('should return undefined when an empty string is passed', () => {
expect(parseJson("")).toBeUndefined();
});
});
4 changes: 2 additions & 2 deletions utils/parse-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const parseJson = <T>(value?: string | null): T | undefined => {
return value === "undefined" ? undefined : (JSON.parse(value ?? "") as T);
} catch {
console.error("parsing error on", { value });

return undefined;
}

return;
};
14 changes: 14 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// <reference types="vitest" />

import react from "@vitejs/plugin-react-swc";
import { defineConfig } from "vitest/config";

export default defineConfig({
plugins: [react()],
test: {
environment: "happy-dom",
globals: true,
restoreMocks: true,
include: ["**/*.test.?(c|m)[jt]s?(x)"],
},
});

0 comments on commit e0037bf

Please sign in to comment.