mirror of
https://github.com/navidrome/navidrome.git
synced 2026-10-15 13:57:09 +02:00
* fix(ui): make playlist toggle switches visible in all themes The Public and Auto-import switches in the playlist list did not set a color, so Material-UI used the theme's secondary color. Many themes use secondary as a surface color close to the table background, which made checked switches nearly invisible (Catppuccin, Rosé Pine, Monokai, Moonbase and others). Set color="primary" on the playlist switch, like every other switch in the app, and make primary the default MuiSwitch color in useCurrentTheme so future switches cannot regress. Fixes #6272. * refactor(ui): drop secondary switch overrides from themes Dracula, Gruvbox Dark, Tokyo Night and Tokyo Night Light styled checked MuiSwitch colorSecondary to work around the same invisible-switch problem (Gruvbox in #5064). With primary as the default switch color and every switch in the app using it, no switch renders with colorSecondary anymore, so these overrides are dead code.
191 lines
6.1 KiB
JavaScript
191 lines
6.1 KiB
JavaScript
import React from 'react'
|
|
import { Provider } from 'react-redux'
|
|
import { createStore } from 'redux'
|
|
import mediaQuery from 'css-mediaquery'
|
|
import { renderHook } from '@testing-library/react-hooks'
|
|
import { render, screen } from '@testing-library/react'
|
|
import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles'
|
|
import Switch from '@material-ui/core/Switch'
|
|
import themes from './index'
|
|
import useCurrentTheme from './useCurrentTheme'
|
|
import { themeReducer } from '../reducers/themeReducer'
|
|
import { AUTO_THEME_ID } from '../consts'
|
|
|
|
function createMatchMedia(theme) {
|
|
return (query) => ({
|
|
matches: mediaQuery.match(query, { 'prefers-color-scheme': theme }),
|
|
addListener: () => {},
|
|
removeListener: () => {},
|
|
})
|
|
}
|
|
|
|
beforeEach(() => {
|
|
document.body.style.backgroundColor = ''
|
|
})
|
|
|
|
describe('useCurrentTheme', () => {
|
|
describe('with user preference theme as light', () => {
|
|
beforeAll(() => {
|
|
window.matchMedia = createMatchMedia('light')
|
|
})
|
|
it('sets theme as light in auto mode', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: AUTO_THEME_ID })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
expect(result.current.themeName).toMatch('Light')
|
|
})
|
|
it('sets theme as dark', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: 'DarkTheme' })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
|
|
expect(result.current.themeName).toMatch('Dark')
|
|
})
|
|
it('sets theme as light', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: 'LightTheme' })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
|
|
expect(result.current.themeName).toMatch('Light')
|
|
})
|
|
it('sets theme as spotify-ish', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider
|
|
store={createStore(themeReducer, { theme: 'SpotifyTheme' })}
|
|
>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
|
|
expect(result.current.themeName).toMatch('Spotify-ish')
|
|
})
|
|
})
|
|
describe('with user preference theme as dark', () => {
|
|
beforeAll(() => {
|
|
window.matchMedia = createMatchMedia('dark')
|
|
})
|
|
it('sets theme as dark in auto mode', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: AUTO_THEME_ID })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
|
|
expect(result.current.themeName).toMatch('Dark')
|
|
})
|
|
it('sets theme as dark', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: 'DarkTheme' })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
|
|
expect(result.current.themeName).toMatch('Dark')
|
|
})
|
|
it('sets theme as light', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: 'LightTheme' })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
|
|
expect(result.current.themeName).toMatch('Light')
|
|
})
|
|
it('sets theme as spotify-ish', () => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider
|
|
store={createStore(themeReducer, { theme: 'SpotifyTheme' })}
|
|
>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
|
|
expect(result.current.themeName).toMatch('Spotify-ish')
|
|
})
|
|
})
|
|
describe('body background color', () => {
|
|
beforeAll(() => {
|
|
window.matchMedia = createMatchMedia('dark')
|
|
})
|
|
it('sets body background for dark theme', () => {
|
|
renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: 'DarkTheme' })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
// Dark theme uses MUI default dark background
|
|
expect(document.body.style.backgroundColor).toBe('rgb(48, 48, 48)')
|
|
})
|
|
it('sets body background for light theme', () => {
|
|
renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme: 'LightTheme' })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
// Light theme uses MUI default light background
|
|
expect(document.body.style.backgroundColor).toBe('rgb(250, 250, 250)')
|
|
})
|
|
it('sets body background for theme with custom background', () => {
|
|
renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider
|
|
store={createStore(themeReducer, { theme: 'SpotifyTheme' })}
|
|
>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
// Spotify theme has explicit background.default: #121212
|
|
expect(document.body.style.backgroundColor).toBe('rgb(18, 18, 18)')
|
|
})
|
|
})
|
|
describe('switch color', () => {
|
|
it.each(Object.keys(themes))(
|
|
'renders switches with the primary color in %s',
|
|
(theme) => {
|
|
const { result } = renderHook(() => useCurrentTheme(), {
|
|
wrapper: ({ children }) => (
|
|
<Provider store={createStore(themeReducer, { theme })}>
|
|
{children}
|
|
</Provider>
|
|
),
|
|
})
|
|
render(
|
|
<ThemeProvider theme={createMuiTheme(result.current)}>
|
|
<Switch checked onChange={() => {}} />
|
|
</ThemeProvider>,
|
|
)
|
|
const switchBase = screen
|
|
.getByRole('checkbox')
|
|
.closest('.MuiSwitch-switchBase')
|
|
expect(switchBase.classList).toContain('MuiSwitch-colorPrimary')
|
|
},
|
|
)
|
|
})
|
|
})
|