feat: Add a simple mode to the visual card editor (#2588)
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
import { assert, describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
applyConfigChanges,
|
||||
computeConfigChanges,
|
||||
computeDisplayedData,
|
||||
} from '../../../src/components-lib/editor/form-data';
|
||||
import {
|
||||
deriveEditorMode,
|
||||
getEditorMode,
|
||||
} from '../../../src/components-lib/editor/mode';
|
||||
import { getSimpleMenuForms } from '../../../src/components-lib/editor/schema/simple';
|
||||
import { getConfigValue } from '../../../src/config/management';
|
||||
import { configDefaults } from '../../../src/config/schema/types';
|
||||
|
||||
// The card type is in every configuration Home Assistant hands the editor.
|
||||
const createConfig = (config: Record<string, unknown> = {}) => ({
|
||||
type: 'custom:advanced-camera-card',
|
||||
...config,
|
||||
});
|
||||
|
||||
describe('deriveEditorMode', () => {
|
||||
it('should choose the simple editor for a configuration that sets nothing', () => {
|
||||
expect(deriveEditorMode(createConfig())).toBe('simple');
|
||||
});
|
||||
|
||||
it('should choose the simple editor for the settings it shows', () => {
|
||||
expect(
|
||||
deriveEditorMode(
|
||||
createConfig({
|
||||
cameras: [
|
||||
{ camera_entity: 'camera.office', live_provider: 'go2rtc' },
|
||||
{ camera_entity: 'camera.kitchen', title: 'Kitchen', icon: 'mdi:cctv' },
|
||||
],
|
||||
menu: {
|
||||
style: 'outside',
|
||||
position: 'left',
|
||||
buttons: { clips: { enabled: true } },
|
||||
},
|
||||
dimensions: { aspect_ratio_mode: 'static', aspect_ratio: '16:9' },
|
||||
view: { default: 'clips' },
|
||||
profiles: ['casting'],
|
||||
}),
|
||||
),
|
||||
).toBe('simple');
|
||||
});
|
||||
|
||||
it('should choose the full editor for a setting the simple editor does not show', () => {
|
||||
expect(deriveEditorMode(createConfig({ view: { dim: true } }))).toBe('full');
|
||||
});
|
||||
|
||||
it('should choose the full editor for a menu button property it does not show', () => {
|
||||
expect(
|
||||
deriveEditorMode(createConfig({ menu: { buttons: { clips: { priority: 5 } } } })),
|
||||
).toBe('full');
|
||||
});
|
||||
|
||||
it.each([
|
||||
[{ live: { preload: true } }],
|
||||
[{ timeline: { window_seconds: 7200 } }],
|
||||
[{ folders: [{ type: 'ha' }] }],
|
||||
[{ cameras: [{ camera_entity: 'camera.office', engine: 'frigate' }] }],
|
||||
])('should choose the full editor for %j', (config) => {
|
||||
expect(deriveEditorMode(createConfig(config))).toBe('full');
|
||||
});
|
||||
|
||||
it.each([
|
||||
// Not a setting of the card at all.
|
||||
[{ fake: true }],
|
||||
|
||||
// Settings the full editor does not show either, so sending the user there
|
||||
// would show them nothing more.
|
||||
[{ debug: { logging: true } }],
|
||||
[{ card_mod: { style: 'body {}' } }],
|
||||
[{ cameras_global: { live_provider: 'go2rtc' } }],
|
||||
[{ elements: [{ type: 'custom:foo' }] }],
|
||||
[{ automations: [{ conditions: [{ condition: 'fullscreen' }] }] }],
|
||||
[{ overrides: [{ merge: { menu: { style: 'none' } } }] }],
|
||||
[{ cameras: [{ camera_entity: 'camera.office', ptz: { presets: {} } }] }],
|
||||
])('should choose the simple editor for %j', (config) => {
|
||||
expect(deriveEditorMode(createConfig(config))).toBe('simple');
|
||||
});
|
||||
|
||||
it('should disregard a section that sets nothing', () => {
|
||||
expect(deriveEditorMode(createConfig({ live: {}, folders: [{}] }))).toBe('simple');
|
||||
});
|
||||
|
||||
it('should disregard the editor mode itself', () => {
|
||||
expect(deriveEditorMode(createConfig({ editor: { mode: 'full' } }))).toBe('simple');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEditorMode', () => {
|
||||
it.each([['simple' as const], ['full' as const]])(
|
||||
'should use the configured %s mode',
|
||||
(mode) => {
|
||||
// A configuration the derivation would send to the other editor, so that
|
||||
// the configured mode is what the result comes from.
|
||||
const config = createConfig({
|
||||
editor: { mode },
|
||||
...(mode === 'simple' ? { view: { dim: true } } : {}),
|
||||
});
|
||||
expect(getEditorMode(config)).toBe(mode);
|
||||
},
|
||||
);
|
||||
|
||||
it('should derive the mode when the configuration does not say', () => {
|
||||
expect(getEditorMode(createConfig())).toBe('simple');
|
||||
expect(getEditorMode(createConfig({ view: { dim: true } }))).toBe('full');
|
||||
});
|
||||
|
||||
it('should derive the mode when the configured one is not an editor', () => {
|
||||
expect(getEditorMode(createConfig({ editor: { mode: 'simpel' } }))).toBe('simple');
|
||||
});
|
||||
|
||||
it('should still choose the simple editor after an edit made in it', () => {
|
||||
const config = createConfig({ cameras: [{ camera_entity: 'camera.office' }] });
|
||||
expect(getEditorMode(config)).toBe('simple');
|
||||
|
||||
// A menu style chosen in the simple editor, written the way the editor
|
||||
// writes it.
|
||||
const [form] = getSimpleMenuForms();
|
||||
const displayed = computeDisplayedData(form, config, configDefaults);
|
||||
const edited = applyConfigChanges(
|
||||
config,
|
||||
computeConfigChanges(
|
||||
form,
|
||||
displayed,
|
||||
{ ...displayed, menu_style: 'outside' },
|
||||
config,
|
||||
configDefaults,
|
||||
),
|
||||
);
|
||||
assert(edited);
|
||||
|
||||
expect(getConfigValue(edited, 'menu.style')).toBe('outside');
|
||||
expect(getEditorMode(edited)).toBe('simple');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user