forked from openedx/frontend-platform
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add testing to useParagonTheme hooks (openedx#514)
* test: add testing to useParagonThemeCore * test: add test to useThemeVariants hook * fix: Paragon definition and remove onload mock * test: change test message to be clear
- Loading branch information
1 parent
ec4a51c
commit 5366993
Showing
2 changed files
with
241 additions
and
0 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,101 @@ | ||
import { renderHook, act } from '@testing-library/react-hooks'; | ||
import { getConfig } from '../../../config'; | ||
import { logError } from '../../../logging'; | ||
import useParagonThemeCore from './useParagonThemeCore'; | ||
|
||
jest.mock('../../../logging'); | ||
|
||
describe('useParagonThemeCore', () => { | ||
const themeOnLoad = jest.fn(); | ||
|
||
afterEach(() => { | ||
document.head.innerHTML = ''; | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should load the core url and change the loading state to true', () => { | ||
const coreConfig = { | ||
themeCore: { | ||
urls: { default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/core.min.css' }, | ||
}, | ||
onLoad: themeOnLoad, | ||
}; | ||
|
||
renderHook(() => useParagonThemeCore(coreConfig)); | ||
const createdLinkTag = document.head.querySelector('link'); | ||
act(() => createdLinkTag.onload()); | ||
expect(createdLinkTag.href).toBe(coreConfig.themeCore.urls.default); | ||
expect(themeOnLoad).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should load the core default and brand url and change the loading state to true', () => { | ||
const coreConfig = { | ||
themeCore: { | ||
urls: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/core.min.css', | ||
brandOverride: 'https://cdn.jsdelivr.net/npm/@edx/brand@$2.0.0Version/dist/core.min.css', | ||
}, | ||
}, | ||
onLoad: themeOnLoad, | ||
}; | ||
|
||
renderHook(() => useParagonThemeCore(coreConfig)); | ||
const createdLinkTag = document.head.querySelector('link[data-paragon-theme-core="true"]'); | ||
const createdBrandLinkTag = document.head.querySelector('link[data-brand-theme-core="true"]'); | ||
|
||
act(() => { createdLinkTag.onload(); createdBrandLinkTag.onload(); }); | ||
expect(createdLinkTag.href).toBe(coreConfig.themeCore.urls.default); | ||
expect(createdBrandLinkTag.href).toBe(coreConfig.themeCore.urls.brandOverride); | ||
expect(themeOnLoad).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should dispatch a log error and fallback to PARAGON_THEME if can not load the core theme link', () => { | ||
global.PARAGON_THEME = { | ||
paragon: { | ||
version: '1.0.0', | ||
themeUrls: { | ||
core: { | ||
fileName: 'core.min.css', | ||
}, | ||
defaults: { | ||
light: 'light', | ||
}, | ||
variants: { | ||
light: { | ||
fileName: 'light.min.css', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
const coreConfig = { | ||
themeCore: { | ||
urls: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/core.min.css', | ||
}, | ||
}, | ||
onLoad: themeOnLoad, | ||
}; | ||
|
||
renderHook(() => useParagonThemeCore(coreConfig)); | ||
const createdLinkTag = document.head.querySelector('link[data-paragon-theme-core="true"]'); | ||
|
||
act(() => { createdLinkTag.onerror(); }); | ||
expect(logError).toHaveBeenCalledTimes(1); | ||
expect(logError).toHaveBeenCalledWith(`Failed to load core theme CSS from ${coreConfig.themeCore.urls.default}`); | ||
expect(document.querySelector('link').href).toBe(`${getConfig().BASE_URL}/${PARAGON_THEME.paragon.themeUrls.core.fileName}`); | ||
}); | ||
|
||
it('should not create any core link if can not find themeCore urls definition', () => { | ||
const coreConfig = { | ||
themeCore: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/core.min.css', | ||
}, | ||
onLoad: themeOnLoad, | ||
}; | ||
|
||
renderHook(() => useParagonThemeCore(coreConfig)); | ||
expect(document.head.querySelectorAll('link').length).toBe(0); | ||
expect(themeOnLoad).toHaveBeenCalledTimes(1); | ||
}); | ||
}); |
140 changes: 140 additions & 0 deletions
140
src/react/hooks/paragon/useParagonThemeVariants.test.js
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,140 @@ | ||
import { act, renderHook } from '@testing-library/react-hooks'; | ||
import { getConfig } from '../../../config'; | ||
import { logError } from '../../../logging'; | ||
import useParagonThemeVariants from './useParagonThemeVariants'; | ||
|
||
jest.mock('../../../logging'); | ||
|
||
const mockAddEventListener = jest.fn(); | ||
const mockRemoveEventListener = jest.fn(); | ||
const mockOnChange = jest.fn(); | ||
|
||
Object.defineProperty(window, 'matchMedia', { | ||
value: jest.fn(() => ({ | ||
addEventListener: mockAddEventListener, | ||
removeEventListener: mockRemoveEventListener, | ||
onchange: mockOnChange, | ||
})), | ||
}); | ||
|
||
describe('useParagonThemeVariants', () => { | ||
const themeOnLoad = jest.fn(); | ||
|
||
afterEach(() => { | ||
document.head.innerHTML = ''; | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should create the links tags for each theme variant and change the state to true when all variants are loaded', () => { | ||
const themeVariants = { | ||
light: { | ||
urls: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/light.min.css', | ||
brandOverride: 'https://cdn.jsdelivr.net/npm/@edx/brand@$2.0.0/dist/light.min.css', | ||
}, | ||
}, | ||
dark: { | ||
urls: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/dark.min.css', | ||
brandOverride: 'https://cdn.jsdelivr.net/npm/@edx/brand@$2.0.0/dist/dark.min.css', | ||
}, | ||
}, | ||
}; | ||
const currentThemeVariant = 'light'; | ||
|
||
renderHook(() => useParagonThemeVariants({ themeVariants, currentThemeVariant, onLoad: themeOnLoad })); | ||
const themeLinks = document.head.querySelectorAll('link'); | ||
act(() => { themeLinks.forEach((link) => link.onload()); }); | ||
|
||
expect(themeLinks.length).toBe(4); | ||
}); | ||
|
||
it('should dispatch a log error and fallback to PARAGON_THEME if can not load the variant theme link', () => { | ||
global.PARAGON_THEME = { | ||
paragon: { | ||
version: '1.0.0', | ||
themeUrls: { | ||
core: { | ||
fileName: 'core.min.css', | ||
}, | ||
defaults: { | ||
light: 'light', | ||
}, | ||
variants: { | ||
light: { | ||
fileName: 'light.min.css', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
const themeVariants = { | ||
light: { | ||
urls: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/light.min.css', | ||
}, | ||
}, | ||
}; | ||
const currentThemeVariant = 'light'; | ||
|
||
renderHook(() => useParagonThemeVariants({ themeVariants, currentThemeVariant, onLoad: themeOnLoad })); | ||
const createdLinkTag = document.head.querySelector('link'); | ||
act(() => { createdLinkTag.onerror(); }); | ||
expect(logError).toHaveBeenCalledTimes(1); | ||
expect(logError).toHaveBeenCalledWith(`Failed to load theme variant (${currentThemeVariant}) CSS from ${themeVariants.light.urls.default}`); | ||
expect(document.querySelector('link').href).toBe(`${getConfig().BASE_URL}/${PARAGON_THEME.paragon.themeUrls.variants.light.fileName}`); | ||
}); | ||
|
||
it('should configure theme variants according with system preference and add the change event listener', () => { | ||
window.matchMedia['prefers-color-scheme'] = 'dark'; | ||
|
||
const themeVariants = { | ||
light: { | ||
urls: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/light.min.css', | ||
brandOverride: 'https://cdn.jsdelivr.net/npm/@edx/brand@$2.0.0/dist/light.min.css', | ||
}, | ||
}, | ||
dark: { | ||
urls: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/dark.min.css', | ||
brandOverride: 'https://cdn.jsdelivr.net/npm/@edx/brand@$2.0.0/dist/dark.min.css', | ||
}, | ||
}, | ||
}; | ||
|
||
const currentThemeVariant = 'light'; | ||
|
||
renderHook(() => useParagonThemeVariants({ themeVariants, currentThemeVariant, onLoad: themeOnLoad })); | ||
|
||
const themeLinks = document.head.querySelectorAll('link'); | ||
act(() => { themeLinks.forEach((link) => link.onload()); }); | ||
|
||
expect(mockAddEventListener).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('should do nothing if themeVariants is not configured', () => { | ||
const themeVariants = null; | ||
const currentTheme = 'light'; | ||
|
||
renderHook(() => useParagonThemeVariants({ themeVariants, currentTheme, onLoad: themeOnLoad })); | ||
expect(document.head.querySelectorAll('link').length).toBe(0); | ||
}); | ||
|
||
it('should not create any core link if can not find themeVariant urls definition', () => { | ||
const themeVariants = { | ||
light: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/light.min.css', | ||
}, | ||
dark: { | ||
default: 'https://cdn.jsdelivr.net/npm/@edx/paragon@$21.0.0/dist/dark.min.css', | ||
}, | ||
}; | ||
|
||
const currentTheme = 'light'; | ||
|
||
renderHook(() => useParagonThemeVariants({ themeVariants, currentTheme, onLoad: themeOnLoad })); | ||
|
||
expect(document.head.querySelectorAll('link').length).toBe(0); | ||
}); | ||
}); |