Move card-controller out of utils.
This commit is contained in:
@@ -0,0 +1,387 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { FrigateCardView } from '../../src/config/types';
|
||||
import { setPerformanceCSSStyles } from '../../src/performance';
|
||||
import { StyleManager } from '../../src/card-controller/style-manager';
|
||||
import { createCardAPI, createConfig, createHASS, createView } from '../test-utils';
|
||||
|
||||
vi.mock('../../src/performance');
|
||||
|
||||
// @vitest-environment jsdom
|
||||
describe('StyleManager', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('setLightOrDarkMode', () => {
|
||||
it('dark mode unspecified', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setLightOrDarkMode();
|
||||
|
||||
expect(element.getAttribute('dark')).toBeNull();
|
||||
});
|
||||
|
||||
it('dark mode explicitly off', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
view: {
|
||||
dark_mode: 'off',
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setLightOrDarkMode();
|
||||
|
||||
expect(element.getAttribute('dark')).toBeNull();
|
||||
});
|
||||
|
||||
it('dark mode explicitly set', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
view: {
|
||||
dark_mode: 'on',
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setLightOrDarkMode();
|
||||
|
||||
expect(element.getAttribute('dark')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('dark mode auto without interaction', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
view: {
|
||||
dark_mode: 'auto',
|
||||
},
|
||||
}),
|
||||
);
|
||||
vi.mocked(api.getInteractionManager().hasInteraction).mockReturnValue(false);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setLightOrDarkMode();
|
||||
|
||||
expect(element.getAttribute('dark')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('dark mode auto with HA dark mode', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
view: {
|
||||
dark_mode: 'auto',
|
||||
},
|
||||
}),
|
||||
);
|
||||
vi.mocked(api.getInteractionManager().hasInteraction).mockReturnValue(true);
|
||||
const hass = createHASS();
|
||||
hass.themes.darkMode = true;
|
||||
vi.mocked(api.getHASSManager().getHASS).mockReturnValue(hass);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setLightOrDarkMode();
|
||||
|
||||
expect(element.getAttribute('dark')).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setExpandedMode', () => {
|
||||
it('with no view or known media', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
vi.mocked(api.getMediaLoadedInfoManager().getLastKnown).mockReturnValue(null);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setExpandedMode();
|
||||
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-aspect-ratio')).toBe(
|
||||
'unset',
|
||||
);
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-width')).toBe(
|
||||
'var(--frigate-card-expand-max-width)',
|
||||
);
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-height')).toBe(
|
||||
'var(--frigate-card-expand-max-height)',
|
||||
);
|
||||
});
|
||||
|
||||
it('with view but without media', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const view = createView({ view: 'media', displayMode: 'single' });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getMediaLoadedInfoManager().getLastKnown).mockReturnValue(null);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setExpandedMode();
|
||||
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-aspect-ratio')).toBe(
|
||||
'unset',
|
||||
);
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-width')).toBe('none');
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-height')).toBe(
|
||||
'none',
|
||||
);
|
||||
});
|
||||
|
||||
it('with view and media', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const view = createView({ view: 'media', displayMode: 'single' });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getMediaLoadedInfoManager().getLastKnown).mockReturnValue({
|
||||
width: 800,
|
||||
height: 600,
|
||||
});
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setExpandedMode();
|
||||
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-aspect-ratio')).toBe(
|
||||
'800 / 600',
|
||||
);
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-width')).toBe('none');
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-height')).toBe(
|
||||
'none',
|
||||
);
|
||||
});
|
||||
|
||||
it('with view and grid display mode', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const view = createView({ view: 'media', displayMode: 'grid' });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getMediaLoadedInfoManager().getLastKnown).mockReturnValue({
|
||||
width: 800,
|
||||
height: 600,
|
||||
});
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setExpandedMode();
|
||||
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-aspect-ratio')).toBe(
|
||||
'800 / 600',
|
||||
);
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-width')).toBe(
|
||||
'var(--frigate-card-expand-max-width)',
|
||||
);
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-height')).toBe(
|
||||
'var(--frigate-card-expand-max-height)',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setMinMaxHeight', () => {
|
||||
it('without a config', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setMinMaxHeight();
|
||||
|
||||
expect(element.style.getPropertyValue('--frigate-card-max-height')).toBeFalsy();
|
||||
expect(element.style.getPropertyValue('--frigate-card-expand-height')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('with a config', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
dimensions: {
|
||||
max_height: '800px',
|
||||
min_height: '400px',
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setMinMaxHeight();
|
||||
|
||||
expect(element.style.getPropertyValue('--frigate-card-min-height')).toBe('400px');
|
||||
expect(element.style.getPropertyValue('--frigate-card-max-height')).toBe('800px');
|
||||
});
|
||||
});
|
||||
|
||||
it('setPerformance', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const config = createConfig();
|
||||
vi.mocked(api.getConfigManager().getCardWideConfig).mockReturnValue({
|
||||
performance: config.performance,
|
||||
});
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setPerformance();
|
||||
|
||||
expect(setPerformanceCSSStyles).toBeCalledWith(element, config.performance);
|
||||
});
|
||||
|
||||
describe('getAspectRatioStyle', () => {
|
||||
it('without config or view', () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new StyleManager(api);
|
||||
expect(manager.getAspectRatioStyle()).toBe('16 / 9');
|
||||
});
|
||||
|
||||
it('should be auto with unconstrained aspect ratio', () => {
|
||||
const api = createCardAPI();
|
||||
const view = createView({ view: 'media' });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
dimensions: {
|
||||
aspect_ratio_mode: 'unconstrained',
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
expect(manager.getAspectRatioStyle()).toBe('auto');
|
||||
});
|
||||
|
||||
it('should be auto in fullscreen', () => {
|
||||
const api = createCardAPI();
|
||||
const view = createView({ view: 'media' });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getFullscreenManager().isInFullscreen).mockReturnValue(true);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
expect(manager.getAspectRatioStyle()).toBe('auto');
|
||||
});
|
||||
|
||||
it('should be auto when expanded', () => {
|
||||
const api = createCardAPI();
|
||||
const view = createView({ view: 'media' });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
vi.mocked(api.getExpandManager().isExpanded).mockReturnValue(true);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
expect(manager.getAspectRatioStyle()).toBe('auto');
|
||||
});
|
||||
|
||||
it('should be auto when there is yet to be a view', () => {
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(null);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(createConfig());
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
expect(manager.getAspectRatioStyle()).toBe('auto');
|
||||
});
|
||||
|
||||
describe('should be auto when dynamic in certain views', () => {
|
||||
it.each([
|
||||
['clip' as const],
|
||||
['diagnostics' as const],
|
||||
['image' as const],
|
||||
['media' as const],
|
||||
['live' as const],
|
||||
['recording' as const],
|
||||
['snapshot' as const],
|
||||
['timeline' as const],
|
||||
])('%s', (viewName: FrigateCardView) => {
|
||||
const api = createCardAPI();
|
||||
const view = createView({ view: viewName });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
dimensions: {
|
||||
aspect_ratio_mode: 'dynamic',
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
expect(manager.getAspectRatioStyle()).toBe('auto');
|
||||
});
|
||||
});
|
||||
|
||||
describe('should be enforced when dynamic in certain views', () => {
|
||||
it.each([['clips' as const], ['recordings' as const], ['snapshots' as const]])(
|
||||
'%s',
|
||||
(viewName: FrigateCardView) => {
|
||||
const api = createCardAPI();
|
||||
const view = createView({ view: viewName });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
dimensions: {
|
||||
aspect_ratio_mode: 'dynamic',
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
expect(manager.getAspectRatioStyle()).toBe('16 / 9');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('should use media dimensions in dynamic', () => {
|
||||
it.each([['clips' as const], ['recordings' as const], ['snapshots' as const]])(
|
||||
'%s',
|
||||
(viewName: FrigateCardView) => {
|
||||
const api = createCardAPI();
|
||||
const view = createView({ view: viewName });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
dimensions: {
|
||||
aspect_ratio_mode: 'dynamic',
|
||||
},
|
||||
}),
|
||||
);
|
||||
vi.mocked(api.getMediaLoadedInfoManager().getLastKnown).mockReturnValue({
|
||||
width: 800,
|
||||
height: 600,
|
||||
});
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
expect(manager.getAspectRatioStyle()).toBe('800 / 600');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should respect default aspect ratio', () => {
|
||||
const api = createCardAPI();
|
||||
const view = createView({ view: 'clips' });
|
||||
vi.mocked(api.getViewManager().getView).mockReturnValue(view);
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue(
|
||||
createConfig({
|
||||
dimensions: {
|
||||
aspect_ratio_mode: 'dynamic',
|
||||
aspect_ratio: '4:3',
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
expect(manager.getAspectRatioStyle()).toBe('4 / 3');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user