-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(useAutoDetectAppearance): rm window from useState (#6243)
Не учёл, что `useState()` вызывается и на сервере. Первое, что может придти в голову – это проверять в `useState` существует ли `window`, но так сделать не можем, т.к. на клиенте, если пользователь не передал `appearance`, то условие отработает удовлетворительно и в первый мы получим автоматическое определение `appearance`, тем самым у нас уже будет разница между клиентом и сервером. В `useState` теперь возвращаем либо пользовательский `appearance`, либо `'light'` по умолчанию. В самом эффекте добавил условие для `window`, чтобы убрать неочевидный **Non-null Assertion Operator** (`!`).
- Loading branch information
Showing
2 changed files
with
95 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { act, renderHook } from '@testing-library/react'; | ||
import { noop } from '@vkontakte/vkjs'; | ||
import { Appearance } from '../lib/appearance'; | ||
import * as LibDOM from '../lib/dom'; | ||
import { useAutoDetectAppearance } from './useAutoDetectAppearance'; | ||
|
||
jest.mock('../lib/dom', () => { | ||
return { | ||
__esModule: true, | ||
...jest.requireActual('../lib/dom'), | ||
}; | ||
}); | ||
|
||
describe(useAutoDetectAppearance, () => { | ||
describe('client', () => { | ||
it.each([Appearance.LIGHT, Appearance.DARK])( | ||
'should return appearance by property (%s)', | ||
(appearanceProp) => { | ||
const { result } = renderHook(() => useAutoDetectAppearance(appearanceProp)); | ||
expect(result.current).toBe(appearanceProp); | ||
}, | ||
); | ||
|
||
it.each([ | ||
{ | ||
initialMatches: false, | ||
listenerMatches: false, | ||
appearance: { before: Appearance.LIGHT, after: Appearance.LIGHT }, | ||
}, | ||
{ | ||
initialMatches: true, | ||
listenerMatches: true, | ||
appearance: { before: Appearance.DARK, after: Appearance.DARK }, | ||
}, | ||
{ | ||
initialMatches: false, | ||
listenerMatches: true, | ||
appearance: { before: Appearance.LIGHT, after: Appearance.DARK }, | ||
}, | ||
{ | ||
initialMatches: true, | ||
listenerMatches: false, | ||
appearance: { before: Appearance.DARK, after: Appearance.LIGHT }, | ||
}, | ||
])( | ||
'should auto detect appearance (initialMatches is $initialMatches, listenerMatches is $listenerMatches, appearance is $appearance)', | ||
({ initialMatches, listenerMatches, appearance }) => { | ||
let addEventListenerHandler = noop; | ||
const addEventListener = jest.fn().mockImplementation((_, handlerByHook) => { | ||
addEventListenerHandler = () => { | ||
handlerByHook({ matches: listenerMatches }); | ||
}; | ||
}); | ||
|
||
// Объявление скопировано из документации https://jestjs.io/docs/manual-mocks | ||
Object.defineProperty(window, 'matchMedia', { | ||
writable: true, | ||
value: jest.fn().mockImplementation((query) => ({ | ||
matches: initialMatches, | ||
media: query, | ||
onchange: null, | ||
addListener: addEventListener, // устарело | ||
removeListener: jest.fn(), // устарело | ||
addEventListener: addEventListener, | ||
removeEventListener: jest.fn(), | ||
dispatchEvent: jest.fn(), | ||
})), | ||
}); | ||
const { result } = renderHook(() => useAutoDetectAppearance()); | ||
expect(result.current).toBe(appearance.before); | ||
act(addEventListenerHandler); | ||
expect(result.current).toBe(appearance.after); | ||
}, | ||
); | ||
}); | ||
|
||
describe('server', () => { | ||
it('should auto detect appearance ($appearance)', () => { | ||
jest.spyOn<any, any>(LibDOM, 'useDOM').mockReturnValue(() => { | ||
return { | ||
document: undefined, | ||
window: undefined, | ||
}; | ||
}); | ||
const { result } = renderHook(() => useAutoDetectAppearance()); | ||
expect(result.current).toBe(Appearance.LIGHT); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters