Skip to content

Commit

Permalink
Add tests for Dark mode feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Zach Price committed Jan 17, 2025
1 parent c0d8a18 commit 54ab6c8
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 14 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"eslint-plugin-testing-library": "^7.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"mock-match-media": "^0.4.3",
"msw": "1.3.5",
"postcss": "8.4.31",
"prettier": "2.2.1",
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/App/recoil/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export const localStorageEffect = (key: string): AtomEffect<boolean> => ({ setSe
const savedValue = localStorage.getItem(key);
if (savedValue != null) {
setSelf(savedValue === 'true');
} else {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
setSelf(mediaQuery.matches);
}

onSet((newValue, _, isReset) => {
Expand Down
91 changes: 90 additions & 1 deletion frontend/src/components/NavBar/RightMenu.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import { render, screen } from '@testing-library/react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { setMedia } from 'mock-match-media';
import customRender from '../../test/custom-render';
import Support from '../Support';
import RightMenu, { Props } from './RightMenu';
Expand Down Expand Up @@ -159,3 +162,89 @@ it('the the right drawer display for news button and hide news button', async ()

await user.click(hideBtn);
});

describe('Dark Mode', () => {
it('respects (prefers-color-scheme: dark) when preference unset', () => {
setMedia({
'prefers-color-scheme': 'dark',
});
localStorage.clear();
render(
<RecoilRoot>
<MemoryRouter>
<RightMenu
mode="vertical"
numCartItems={0}
numSavedSearches={0}
supportModalVisible={() => false}
></RightMenu>
</MemoryRouter>
</RecoilRoot>
);
expect(screen.getByTestId('isDarkModeSwitch')).not.toBeChecked();
});

it('respects (prefers-color-scheme: light) when preference unset', () => {
setMedia({
'prefers-color-scheme': 'light',
});
localStorage.clear();
render(
<RecoilRoot>
<MemoryRouter>
<RightMenu
mode="vertical"
numCartItems={0}
numSavedSearches={0}
supportModalVisible={() => false}
></RightMenu>
</MemoryRouter>
</RecoilRoot>
);
expect(screen.getByTestId('isDarkModeSwitch')).toBeChecked();
});

it('gives precedence to stored preference over prefers-color-scheme', () => {
setMedia({
'prefers-color-scheme': 'dark',
});
localStorage.setItem('isDarkMode', 'false');
render(
<RecoilRoot>
<MemoryRouter>
<RightMenu
mode="vertical"
numCartItems={0}
numSavedSearches={0}
supportModalVisible={() => false}
></RightMenu>
</MemoryRouter>
</RecoilRoot>
);
expect(screen.getByTestId('isDarkModeSwitch')).toBeChecked();
});

it('stores preference when selected', async () => {
setMedia({});
localStorage.clear();
render(
<RecoilRoot>
<MemoryRouter>
<RightMenu
mode="vertical"
numCartItems={0}
numSavedSearches={0}
supportModalVisible={() => false}
></RightMenu>
</MemoryRouter>
</RecoilRoot>
);
const isDarkModeSwitch = await screen.findByTestId('isDarkModeSwitch');
expect(isDarkModeSwitch).not.toBeChecked();
waitFor(() => {
fireEvent.click(isDarkModeSwitch);
});
expect(await screen.findByTestId('isDarkModeSwitch')).toBeChecked();
expect(localStorage.getItem('isDarkMode')).toBe('false');
});
});
1 change: 1 addition & 0 deletions frontend/src/components/NavBar/RightMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ const RightMenu: React.FC<React.PropsWithChildren<Props>> = ({
unCheckedChildren="Dark"
onChange={(checked) => setIsDarkMode(!checked)}
defaultChecked={!isDarkMode}
data-testid="isDarkModeSwitch"
></Switch>
<span>Theme</span>
</Space>
Expand Down
14 changes: 1 addition & 13 deletions frontend/src/setupTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
sessionStorageMock,
} from './test/jestTestFunctions';
import 'cross-fetch/polyfill';
import 'mock-match-media/jest-setup';

jest.setTimeout(60000);

Expand All @@ -20,19 +21,6 @@ const location = JSON.stringify(window.location);

Object.defineProperty(window, 'localStorage', { value: sessionStorageMock });
Object.defineProperty(window, 'METAGRID', { value: mockConfig });
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query: string) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});

beforeAll(() => {
server.listen();
Expand Down
12 changes: 12 additions & 0 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,11 @@ crypto-js@^4.0.0:
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==

css-mediaquery@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0"
integrity sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==

css.escape@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
Expand Down Expand Up @@ -4925,6 +4930,13 @@ minimist@^1.2.0, minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==

mock-match-media@^0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/mock-match-media/-/mock-match-media-0.4.3.tgz#e28c6f3911e55bee15451cb6d408accf742a0986"
integrity sha512-8nqA2fh5mmgtZEN6sDPlEbLqlqEkF8kCIL17ozbWNHLxnLPF/cli0B6sLffOyfqSBBuVWprEKjYyN8tPXMYmVA==
dependencies:
css-mediaquery "^0.1.2"

ms@^2.1.1, ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
Expand Down

0 comments on commit 54ab6c8

Please sign in to comment.