forked from Github/frigate
test(web): add unit test framework
This commit is contained in:
committed by
Blake Blackshear
parent
daa759cc55
commit
a803ab8577
217
web/src/context/__tests__/index.test.jsx
Normal file
217
web/src/context/__tests__/index.test.jsx
Normal file
@@ -0,0 +1,217 @@
|
||||
import { h } from 'preact';
|
||||
import * as IDB from 'idb-keyval';
|
||||
import { DarkModeProvider, useDarkMode, usePersistence } from '..';
|
||||
import { fireEvent, render, screen } from '@testing-library/preact';
|
||||
import { useCallback } from 'preact/hooks';
|
||||
|
||||
function DarkModeChecker() {
|
||||
const { currentMode } = useDarkMode();
|
||||
return <div data-testid={currentMode}>{currentMode}</div>;
|
||||
}
|
||||
|
||||
describe('DarkMode', () => {
|
||||
let MockIDB;
|
||||
beforeEach(() => {
|
||||
MockIDB = {
|
||||
get: jest.spyOn(IDB, 'get').mockImplementation(() => Promise.resolve(undefined)),
|
||||
set: jest.spyOn(IDB, 'set').mockImplementation(() => Promise.resolve(true)),
|
||||
};
|
||||
});
|
||||
|
||||
test('uses media by default', async () => {
|
||||
render(
|
||||
<DarkModeProvider>
|
||||
<DarkModeChecker />
|
||||
</DarkModeProvider>
|
||||
);
|
||||
const el = await screen.findByTestId('media');
|
||||
expect(el).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('uses the mode stored in idb - dark', async () => {
|
||||
MockIDB.get.mockResolvedValue('dark');
|
||||
render(
|
||||
<DarkModeProvider>
|
||||
<DarkModeChecker />
|
||||
</DarkModeProvider>
|
||||
);
|
||||
const el = await screen.findByTestId('dark');
|
||||
expect(el).toBeInTheDocument();
|
||||
expect(document.body.classList.contains('dark')).toBe(true);
|
||||
});
|
||||
|
||||
test('uses the mode stored in idb - light', async () => {
|
||||
MockIDB.get.mockResolvedValue('light');
|
||||
render(
|
||||
<DarkModeProvider>
|
||||
<DarkModeChecker />
|
||||
</DarkModeProvider>
|
||||
);
|
||||
const el = await screen.findByTestId('light');
|
||||
expect(el).toBeInTheDocument();
|
||||
expect(document.body.classList.contains('dark')).toBe(false);
|
||||
});
|
||||
|
||||
test('allows updating the mode', async () => {
|
||||
MockIDB.get.mockResolvedValue('dark');
|
||||
|
||||
function Updater() {
|
||||
const { setDarkMode } = useDarkMode();
|
||||
const handleClick = useCallback(() => {
|
||||
setDarkMode('light');
|
||||
}, [setDarkMode]);
|
||||
return <div onClick={handleClick}>click me</div>;
|
||||
}
|
||||
|
||||
render(
|
||||
<DarkModeProvider>
|
||||
<DarkModeChecker />
|
||||
<Updater />
|
||||
</DarkModeProvider>
|
||||
);
|
||||
|
||||
const dark = await screen.findByTestId('dark');
|
||||
expect(dark).toBeInTheDocument();
|
||||
expect(document.body.classList.contains('dark')).toBe(true);
|
||||
|
||||
const button = await screen.findByText('click me');
|
||||
fireEvent.click(button);
|
||||
|
||||
const light = await screen.findByTestId('light');
|
||||
expect(light).toBeInTheDocument();
|
||||
expect(document.body.classList.contains('dark')).toBe(false);
|
||||
});
|
||||
|
||||
test('when using media, matches on preference', async () => {
|
||||
MockIDB.get.mockResolvedValue('media');
|
||||
jest.spyOn(window, 'matchMedia').mockImplementation((query) => {
|
||||
if (query === '(prefers-color-scheme: dark)') {
|
||||
return { matches: true, addEventListener: jest.fn(), removeEventListener: jest.fn() };
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected query to matchMedia: ${query}`);
|
||||
});
|
||||
render(
|
||||
<DarkModeProvider>
|
||||
<DarkModeChecker />
|
||||
</DarkModeProvider>
|
||||
);
|
||||
|
||||
const el = await screen.findByTestId('dark');
|
||||
expect(el).toBeInTheDocument();
|
||||
expect(document.body.classList.contains('dark')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('usePersistence', () => {
|
||||
let MockIDB;
|
||||
beforeEach(() => {
|
||||
MockIDB = {
|
||||
get: jest.spyOn(IDB, 'get').mockImplementation(() => Promise.resolve(undefined)),
|
||||
set: jest.spyOn(IDB, 'set').mockImplementation(() => Promise.resolve(true)),
|
||||
};
|
||||
});
|
||||
|
||||
test('returns a defaultValue initially', async () => {
|
||||
MockIDB.get.mockImplementationOnce(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve('foo');
|
||||
}, 1);
|
||||
})
|
||||
);
|
||||
|
||||
function Component() {
|
||||
const [value, , loaded] = usePersistence('tacos', 'my-default');
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="loaded">{loaded ? 'loaded' : 'not loaded'}</div>
|
||||
<div data-testid="value">{value}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(<Component />);
|
||||
|
||||
expect(screen.getByTestId('loaded')).toMatchInlineSnapshot(`
|
||||
<div
|
||||
data-testid="loaded"
|
||||
>
|
||||
not loaded
|
||||
</div>
|
||||
`);
|
||||
expect(screen.getByTestId('value')).toMatchInlineSnapshot(`
|
||||
<div
|
||||
data-testid="value"
|
||||
>
|
||||
my-default
|
||||
</div>
|
||||
`);
|
||||
|
||||
jest.runAllTimers();
|
||||
});
|
||||
|
||||
test('updates with the previously-persisted value', async () => {
|
||||
MockIDB.get.mockResolvedValue('are delicious');
|
||||
|
||||
function Component() {
|
||||
const [value, , loaded] = usePersistence('tacos', 'my-default');
|
||||
return (
|
||||
<div>
|
||||
<div data-testid="loaded">{loaded ? 'loaded' : 'not loaded'}</div>
|
||||
<div data-testid="value">{value}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(<Component />);
|
||||
|
||||
await screen.findByText('loaded');
|
||||
|
||||
expect(screen.getByTestId('loaded')).toMatchInlineSnapshot(`
|
||||
<div
|
||||
data-testid="loaded"
|
||||
>
|
||||
loaded
|
||||
</div>
|
||||
`);
|
||||
expect(screen.getByTestId('value')).toMatchInlineSnapshot(`
|
||||
<div
|
||||
data-testid="value"
|
||||
>
|
||||
are delicious
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
test('can be updated manually', async () => {
|
||||
MockIDB.get.mockResolvedValue('are delicious');
|
||||
|
||||
function Component() {
|
||||
const [value, setValue] = usePersistence('tacos', 'my-default');
|
||||
const handleClick = useCallback(() => {
|
||||
setValue('super delicious');
|
||||
}, [setValue]);
|
||||
return (
|
||||
<div>
|
||||
<div onClick={handleClick}>click me</div>
|
||||
<div data-testid="value">{value}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(<Component />);
|
||||
|
||||
const button = await screen.findByText('click me');
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(screen.getByTestId('value')).toMatchInlineSnapshot(`
|
||||
<div
|
||||
data-testid="value"
|
||||
>
|
||||
super delicious
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user