import { renderHook, act } from '@testing-library/react'; import { ThemeProvider } from './ThemeProvider'; import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const'; import { useTheme } from './useTheme'; describe('useTheme', () => { it('returns default light theme', () => { jest.spyOn(console, 'warn').mockImplementation(); const { result: { current }, } = renderHook(() => useTheme()); expect(current).toMatchObject({ theme: DEFAULT_BASE_THEME, screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal', }); expect(current.setTheme).toBeInstanceOf(Function); expect(current.setScreenMode).toBeInstanceOf(Function); jest.clearAllMocks(); }); it('returns personal theme', () => { const { result: { current }, } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(current).toMatchObject({ theme: 'personal', screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal', }); expect(current.setTheme).toBeInstanceOf(Function); expect(current.setScreenMode).toBeInstanceOf(Function); }); it('returns forest-green theme', () => { const { result: { current }, } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(current).toMatchObject({ theme: 'forest-green', screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: true, isScreenModeDark: false, className: 'np-theme-personal np-theme-personal--forest-green', }); expect(current.setTheme).toBeInstanceOf(Function); expect(current.setScreenMode).toBeInstanceOf(Function); }); it('returns bright-green theme', () => { const { result: { current }, } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(current).toMatchObject({ theme: 'bright-green', screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal np-theme-personal--bright-green', }); expect(current.setTheme).toBeInstanceOf(Function); expect(current.setScreenMode).toBeInstanceOf(Function); }); it('returns default screen mode if used light theme', () => { const { result: { current }, } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(current).toMatchObject({ theme: DEFAULT_BASE_THEME, screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal', }); expect(current.setTheme).toBeInstanceOf(Function); expect(current.setScreenMode).toBeInstanceOf(Function); }); it('returns dark screen mode if used light theme + dark screen mode', () => { const { result: { current }, } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(current).toMatchObject({ theme: DEFAULT_BASE_THEME, screenMode: 'dark', isModern: true, isForestGreenTheme: false, isScreenModeDark: true, className: 'np-theme-personal np-theme-personal--dark', }); expect(current.setTheme).toBeInstanceOf(Function); expect(current.setScreenMode).toBeInstanceOf(Function); }); it('returns dark screen mode', () => { const { result: { current }, } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(current).toMatchObject({ theme: 'personal', screenMode: 'dark', isModern: true, isForestGreenTheme: false, isScreenModeDark: true, className: 'np-theme-personal np-theme-personal--dark', }); expect(current.setTheme).toBeInstanceOf(Function); expect(current.setScreenMode).toBeInstanceOf(Function); }); it('warns when used outside a theme provider on staging or localhost', () => { jest.spyOn(console, 'warn').mockImplementation(); Object.defineProperty(window, 'location', { value: { hostname: 'wise.com', }, writable: true, }); const { result: { current: productionValue }, } = renderHook(() => useTheme()); expect(productionValue).toMatchObject({ theme: DEFAULT_BASE_THEME, screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal', }); expect(productionValue.setTheme).toBeInstanceOf(Function); expect(productionValue.setScreenMode).toBeInstanceOf(Function); // eslint-disable-next-line no-console expect(console.warn).not.toHaveBeenCalled(); Object.defineProperty(window, 'location', { value: { hostname: 'dev-wi.se', }, writable: true, }); const { result: { current: stagingValue }, } = renderHook(() => useTheme()); expect(stagingValue).toMatchObject({ theme: DEFAULT_BASE_THEME, screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal', }); expect(stagingValue.setTheme).toBeInstanceOf(Function); expect(stagingValue.setScreenMode).toBeInstanceOf(Function); // eslint-disable-next-line no-console expect(console.warn).toHaveBeenCalledTimes(1); Object.defineProperty(window, 'location', { value: { hostname: 'localhost', }, writable: true, }); const { result: { current: localhostValue }, } = renderHook(() => useTheme()); expect(localhostValue).toMatchObject({ theme: DEFAULT_BASE_THEME, screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal', }); expect(localhostValue.setTheme).toBeInstanceOf(Function); expect(localhostValue.setScreenMode).toBeInstanceOf(Function); // eslint-disable-next-line no-console expect(console.warn).toHaveBeenCalledTimes(2); Object.defineProperty(window, 'location', { value: undefined, writable: true, }); const { result: { current: noHostnameValue }, } = renderHook(() => useTheme()); expect(noHostnameValue).toMatchObject({ theme: DEFAULT_BASE_THEME, screenMode: DEFAULT_SCREEN_MODE, isModern: true, isForestGreenTheme: false, isScreenModeDark: false, className: 'np-theme-personal', }); expect(noHostnameValue.setTheme).toBeInstanceOf(Function); expect(noHostnameValue.setScreenMode).toBeInstanceOf(Function); // eslint-disable-next-line no-console expect(console.warn).toHaveBeenCalledTimes(2); jest.clearAllMocks(); }); it('allows theme changes from child components via setTheme', async () => { const { result } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(result.current.theme).toBe('personal'); // Change theme using setTheme await act(async () => { result.current.setTheme('business'); }); expect(result.current.theme).toBe('business'); }); it('allows screen mode changes from child components via setScreenMode', async () => { const { result } = renderHook(() => useTheme(), { wrapper: (props) => , }); expect(result.current.screenMode).toBe('light'); // Change screen mode using setScreenMode await act(async () => { result.current.setScreenMode('dark'); }); expect(result.current.screenMode).toBe('dark'); }); });