@@ -6,11 +6,13 @@ import {
|
||||
evaluateConditionViaEvent,
|
||||
getOverriddenConfig,
|
||||
} from '../../src/card-controller/conditions-manager';
|
||||
import { MicrophoneState } from '../../src/card-controller/types';
|
||||
import { FrigateCardCondition } from '../../src/config/types';
|
||||
import {
|
||||
createCardAPI,
|
||||
createCondition,
|
||||
createConfig,
|
||||
createMediaLoadedInfo,
|
||||
createStateEntity,
|
||||
createUser,
|
||||
} from '../test-utils';
|
||||
@@ -780,9 +782,9 @@ describe('ConditionsManager', () => {
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
const conditions = [{ condition: 'media_loaded' as const, media_loaded: true }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ media_loaded: true });
|
||||
manager.setState({ mediaLoadedInfo: createMediaLoadedInfo() });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({ media_loaded: false });
|
||||
manager.setState({ mediaLoadedInfo: null });
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -898,17 +900,27 @@ describe('ConditionsManager', () => {
|
||||
});
|
||||
|
||||
describe('with microphone condition', () => {
|
||||
const createMicrophoneState = (
|
||||
state: Partial<MicrophoneState>,
|
||||
): MicrophoneState => {
|
||||
return {
|
||||
connected: false,
|
||||
muted: false,
|
||||
forbidden: false,
|
||||
...state,
|
||||
};
|
||||
};
|
||||
it('empty', () => {
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
const conditions = [{ condition: 'microphone' as const }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({ microphone: { connected: true } });
|
||||
manager.setState({ microphone: createMicrophoneState({ connected: true }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({ microphone: { connected: false } });
|
||||
manager.setState({ microphone: createMicrophoneState({ connected: false }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({ microphone: { muted: true } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: true }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({ microphone: { muted: false } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: false }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
});
|
||||
|
||||
@@ -916,9 +928,9 @@ describe('ConditionsManager', () => {
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
const conditions = [{ condition: 'microphone' as const, connected: true }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { connected: true } });
|
||||
manager.setState({ microphone: createMicrophoneState({ connected: true }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({ microphone: { connected: false } });
|
||||
manager.setState({ microphone: createMicrophoneState({ connected: false }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -926,9 +938,9 @@ describe('ConditionsManager', () => {
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
const conditions = [{ condition: 'microphone' as const, connected: false }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { connected: true } });
|
||||
manager.setState({ microphone: createMicrophoneState({ connected: true }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { connected: false } });
|
||||
manager.setState({ microphone: createMicrophoneState({ connected: false }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
});
|
||||
|
||||
@@ -936,9 +948,9 @@ describe('ConditionsManager', () => {
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
const conditions = [{ condition: 'microphone' as const, muted: true }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { muted: true } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: true }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({ microphone: { muted: false } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: false }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
});
|
||||
|
||||
@@ -946,9 +958,9 @@ describe('ConditionsManager', () => {
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
const conditions = [{ condition: 'microphone' as const, muted: false }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { muted: true } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: true }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { muted: false } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: false }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
});
|
||||
|
||||
@@ -958,13 +970,17 @@ describe('ConditionsManager', () => {
|
||||
{ condition: 'microphone' as const, muted: false, connected: true },
|
||||
];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { muted: true } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: true }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { muted: false } });
|
||||
manager.setState({ microphone: createMicrophoneState({ muted: false }) });
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { connected: false, muted: false } });
|
||||
manager.setState({
|
||||
microphone: createMicrophoneState({ connected: false, muted: false }),
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({ microphone: { connected: true, muted: false } });
|
||||
manager.setState({
|
||||
microphone: createMicrophoneState({ connected: true, muted: false }),
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1033,11 +1049,11 @@ describe('ConditionsManager', () => {
|
||||
const conditions = [{ condition: 'user_agent' as const, user_agent: userAgent }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({
|
||||
user_agent: userAgent,
|
||||
userAgent: userAgent,
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({
|
||||
user_agent: 'Something else',
|
||||
userAgent: 'Something else',
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
});
|
||||
@@ -1049,11 +1065,11 @@ describe('ConditionsManager', () => {
|
||||
];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({
|
||||
user_agent: userAgent,
|
||||
userAgent: userAgent,
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({
|
||||
user_agent: 'Something else',
|
||||
userAgent: 'Something else',
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
});
|
||||
@@ -1063,11 +1079,11 @@ describe('ConditionsManager', () => {
|
||||
const conditions = [{ condition: 'user_agent' as const, companion: true }];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({
|
||||
user_agent: 'Home Assistant/',
|
||||
userAgent: 'Home Assistant/',
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({
|
||||
user_agent: userAgent,
|
||||
userAgent: userAgent,
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
});
|
||||
@@ -1084,14 +1100,37 @@ describe('ConditionsManager', () => {
|
||||
];
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
manager.setState({
|
||||
user_agent: 'Home Assistant/',
|
||||
userAgent: 'Home Assistant/',
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeTruthy();
|
||||
manager.setState({
|
||||
user_agent: 'Something else',
|
||||
userAgent: 'Something else',
|
||||
});
|
||||
expect(manager.evaluateConditions(conditions)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should add listener', () => {
|
||||
const listener = vi.fn();
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
manager.addListener(listener);
|
||||
|
||||
const state = { fullscreen: true };
|
||||
manager.setState(state);
|
||||
|
||||
expect(listener).toBeCalledWith(state, {});
|
||||
});
|
||||
|
||||
it('should remove listener', () => {
|
||||
const listener = vi.fn();
|
||||
const manager = new ConditionsManager(createCardAPI());
|
||||
manager.addListener(listener);
|
||||
manager.removeListener(listener);
|
||||
|
||||
const state = { fullscreen: true };
|
||||
manager.setState(state);
|
||||
|
||||
expect(listener).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ import { CardController } from '../../src/card-controller/controller';
|
||||
import { DefaultManager } from '../../src/card-controller/default-manager';
|
||||
import { DownloadManager } from '../../src/card-controller/download-manager';
|
||||
import { ExpandManager } from '../../src/card-controller/expand-manager';
|
||||
import { FullscreenManager } from '../../src/card-controller/fullscreen-manager';
|
||||
import { FullscreenManager } from '../../src/card-controller/fullscreen/fullscreen-manager';
|
||||
import { HASSManager } from '../../src/card-controller/hass/hass-manager';
|
||||
import { InitializationManager } from '../../src/card-controller/initialization-manager';
|
||||
import { InteractionManager } from '../../src/card-controller/interaction-manager';
|
||||
@@ -42,7 +42,7 @@ vi.mock('../../src/card-controller/config/config-manager');
|
||||
vi.mock('../../src/card-controller/default-manager');
|
||||
vi.mock('../../src/card-controller/download-manager');
|
||||
vi.mock('../../src/card-controller/expand-manager');
|
||||
vi.mock('../../src/card-controller/fullscreen-manager');
|
||||
vi.mock('../../src/card-controller/fullscreen/fullscreen-manager');
|
||||
vi.mock('../../src/card-controller/hass/hass-manager');
|
||||
vi.mock('../../src/card-controller/initialization-manager');
|
||||
vi.mock('../../src/card-controller/interaction-manager');
|
||||
|
||||
@@ -25,7 +25,7 @@ describe('ExpandManager', () => {
|
||||
manager.setExpanded(true);
|
||||
|
||||
expect(manager.isExpanded()).toBeTruthy();
|
||||
expect(api.getFullscreenManager().stopFullscreen).toBeCalled();
|
||||
expect(api.getFullscreenManager().setFullscreen).toBeCalledWith(false);
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith({ expand: true });
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
});
|
||||
@@ -37,7 +37,7 @@ describe('ExpandManager', () => {
|
||||
|
||||
manager.setExpanded(true);
|
||||
|
||||
expect(api.getFullscreenManager().stopFullscreen).not.toBeCalled();
|
||||
expect(api.getFullscreenManager().setFullscreen).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should toggle expanded', () => {
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
import screenfull from 'screenfull';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { FullscreenManager } from '../../src/card-controller/fullscreen-manager';
|
||||
import { createCardAPI } from '../test-utils';
|
||||
|
||||
vi.mock('screenfull', () => ({
|
||||
default: {
|
||||
exit: vi.fn(),
|
||||
toggle: vi.fn(),
|
||||
off: vi.fn(),
|
||||
on: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const setScreenfulEnabled = (enabled: boolean): void => {
|
||||
Object.defineProperty(screenfull, 'isEnabled', { value: enabled, writable: true });
|
||||
};
|
||||
|
||||
const setScreenfulFullscreen = (fullscreen: boolean): void => {
|
||||
Object.defineProperty(screenfull, 'isFullscreen', {
|
||||
value: fullscreen,
|
||||
writable: true,
|
||||
});
|
||||
};
|
||||
|
||||
// @vitest-environment jsdom
|
||||
describe('FullscreenManager', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should initialize', () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new FullscreenManager(api);
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
setScreenfulFullscreen(false);
|
||||
|
||||
manager.initialize();
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith({ fullscreen: false });
|
||||
});
|
||||
|
||||
it('should correctly determine whether in fullscreen', () => {
|
||||
const manager = new FullscreenManager(createCardAPI());
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
setScreenfulFullscreen(true);
|
||||
expect(manager.isInFullscreen()).toBeTruthy();
|
||||
|
||||
setScreenfulFullscreen(false);
|
||||
expect(manager.isInFullscreen()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should toggle fullscreen', () => {
|
||||
const toggle = vi.mocked(screenfull.toggle);
|
||||
const element = document.createElement('div');
|
||||
const api = createCardAPI();
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const manager = new FullscreenManager(api);
|
||||
|
||||
manager.toggleFullscreen();
|
||||
|
||||
expect(toggle).toBeCalledWith(element);
|
||||
});
|
||||
|
||||
it('should stop fullscreen', () => {
|
||||
const manager = new FullscreenManager(createCardAPI());
|
||||
const exit = vi.mocked(screenfull.exit);
|
||||
|
||||
manager.stopFullscreen();
|
||||
|
||||
expect(exit).toBeCalled();
|
||||
});
|
||||
|
||||
it('should disconnect', () => {
|
||||
const manager = new FullscreenManager(createCardAPI());
|
||||
const off = vi.mocked(screenfull.off);
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
manager.disconnect();
|
||||
|
||||
expect(off).toBeCalledWith('change', expect.anything());
|
||||
});
|
||||
|
||||
it('should not disconnect when screenfull disabled', () => {
|
||||
const manager = new FullscreenManager(createCardAPI());
|
||||
const off = vi.mocked(screenfull.off);
|
||||
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
manager.disconnect();
|
||||
|
||||
expect(off).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should connect', () => {
|
||||
const manager = new FullscreenManager(createCardAPI());
|
||||
const on = vi.mocked(screenfull.on);
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
manager.connect();
|
||||
|
||||
expect(on).toBeCalledWith('change', expect.anything());
|
||||
});
|
||||
|
||||
it('should not connect when screenfull disabled', () => {
|
||||
const manager = new FullscreenManager(createCardAPI());
|
||||
const on = vi.mocked(screenfull.on);
|
||||
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
manager.connect();
|
||||
|
||||
expect(on).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should make correct api calls on fullscreen change', () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new FullscreenManager(api);
|
||||
const on = vi.mocked(screenfull.on);
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
setScreenfulFullscreen(true);
|
||||
|
||||
manager.connect();
|
||||
|
||||
expect(on).toBeCalled();
|
||||
on.mock.calls[0][1](new Event('fullscreen'));
|
||||
|
||||
expect(api.getExpandManager().setExpanded).toBeCalledWith(false);
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith({
|
||||
fullscreen: true,
|
||||
});
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
import { FullscreenProviderFactory } from '../../../src/card-controller/fullscreen/factory';
|
||||
import { ScreenfullFullScreenProvider } from '../../../src/card-controller/fullscreen/screenfull';
|
||||
import { WebkitFullScreenProvider } from '../../../src/card-controller/fullscreen/webkit';
|
||||
import { WebkitHTMLVideoElement } from '../../../src/types';
|
||||
import { createCardAPI, setScreenfulEnabled } from '../../test-utils';
|
||||
|
||||
// @vitest-environment jsdom
|
||||
describe('FullscreenProviderFactory', () => {
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('should return screenful when enabled', () => {
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
expect(FullscreenProviderFactory.create(createCardAPI(), vi.fn())).toBeInstanceOf(
|
||||
ScreenfullFullScreenProvider,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return webkit when enabled', () => {
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
const element = document.createElement('video') as HTMLVideoElement &
|
||||
Partial<WebkitHTMLVideoElement>;
|
||||
element['webkitEnterFullscreen'] = vi.fn();
|
||||
|
||||
const stubDocument = mock<Document>();
|
||||
stubDocument.createElement.mockReturnValue(element);
|
||||
|
||||
vi.stubGlobal('document', stubDocument);
|
||||
|
||||
expect(FullscreenProviderFactory.create(createCardAPI(), vi.fn())).toBeInstanceOf(
|
||||
WebkitFullScreenProvider,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return null without any provider', () => {
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
const element = document.createElement('video') as HTMLVideoElement &
|
||||
Partial<WebkitHTMLVideoElement>;
|
||||
element['webkitEnterFullscreen'] = undefined;
|
||||
|
||||
const stubDocument = mock<Document>();
|
||||
stubDocument.createElement.mockReturnValue(element);
|
||||
|
||||
vi.stubGlobal('document', stubDocument);
|
||||
|
||||
expect(FullscreenProviderFactory.create(createCardAPI(), vi.fn())).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,149 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
import { FullscreenProviderFactory } from '../../../src/card-controller/fullscreen/factory';
|
||||
import { FullscreenManager } from '../../../src/card-controller/fullscreen/fullscreen-manager';
|
||||
import { FullscreenProvider } from '../../../src/card-controller/fullscreen/types';
|
||||
import { createCardAPI } from '../../test-utils';
|
||||
|
||||
vi.mock('../../../src/card-controller/fullscreen/factory');
|
||||
|
||||
describe('FullscreenManager', () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should initialize', () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new FullscreenManager(api, mock<FullscreenProvider>());
|
||||
|
||||
manager.initialize();
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith({ fullscreen: false });
|
||||
});
|
||||
|
||||
it('should correctly determine whether in fullscreen', () => {
|
||||
const provider = mock<FullscreenProvider>();
|
||||
const manager = new FullscreenManager(createCardAPI(), provider);
|
||||
|
||||
provider.isInFullscreen.mockReturnValue(true);
|
||||
|
||||
expect(manager.isInFullscreen()).toBeTruthy();
|
||||
|
||||
provider.isInFullscreen.mockReturnValue(false);
|
||||
|
||||
expect(manager.isInFullscreen()).toBeFalsy();
|
||||
});
|
||||
|
||||
describe('describe toggle fullscreen', () => {
|
||||
it.each([
|
||||
[true, false],
|
||||
[false, true],
|
||||
])('%s -> %s', async (state: boolean, expected: boolean) => {
|
||||
const provider = mock<FullscreenProvider>();
|
||||
provider.isInFullscreen.mockReturnValue(state);
|
||||
|
||||
const manager = new FullscreenManager(createCardAPI(), provider);
|
||||
|
||||
manager.toggleFullscreen();
|
||||
|
||||
expect(provider.setFullscreen).toBeCalledWith(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('describe set fullscreen', () => {
|
||||
it.each([[true], [false]])('%s', async (fullscreen: boolean) => {
|
||||
const provider = mock<FullscreenProvider>();
|
||||
const manager = new FullscreenManager(createCardAPI(), provider);
|
||||
|
||||
manager.setFullscreen(fullscreen);
|
||||
|
||||
expect(provider.setFullscreen).toBeCalledWith(fullscreen);
|
||||
});
|
||||
});
|
||||
|
||||
it('should connect', () => {
|
||||
const provider = mock<FullscreenProvider>();
|
||||
const manager = new FullscreenManager(createCardAPI(), provider);
|
||||
|
||||
manager.connect();
|
||||
|
||||
expect(provider.connect).toBeCalled();
|
||||
});
|
||||
|
||||
it('should disconnect', () => {
|
||||
const provider = mock<FullscreenProvider>();
|
||||
const manager = new FullscreenManager(createCardAPI(), provider);
|
||||
|
||||
manager.disconnect();
|
||||
|
||||
expect(provider.disconnect).toBeCalled();
|
||||
});
|
||||
|
||||
describe('should confirm whether fullscreen is supported', () => {
|
||||
beforeEach(() => {
|
||||
vi.stubGlobal('navigator', { userAgent: 'foo' });
|
||||
});
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('when being casted', () => {
|
||||
vi.stubGlobal('navigator', { userAgent: 'CrKey/' });
|
||||
|
||||
const api = createCardAPI();
|
||||
const provider = mock<FullscreenProvider>();
|
||||
provider.isSupported.mockReturnValue(true);
|
||||
|
||||
const manager = new FullscreenManager(api, provider);
|
||||
|
||||
expect(manager.isSupported()).toBeFalsy();
|
||||
});
|
||||
|
||||
describe('should return provider support', () => {
|
||||
it.each([[true], [false]])('%s', async (support: boolean) => {
|
||||
const api = createCardAPI();
|
||||
const provider = mock<FullscreenProvider>();
|
||||
provider.isSupported.mockReturnValue(support);
|
||||
const manager = new FullscreenManager(api, provider);
|
||||
|
||||
expect(manager.isSupported()).toBe(support);
|
||||
});
|
||||
});
|
||||
|
||||
it('without a provider', () => {
|
||||
vi.mocked(FullscreenProviderFactory).create.mockReturnValue(null);
|
||||
|
||||
const manager = new FullscreenManager(createCardAPI());
|
||||
|
||||
expect(manager.isSupported()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should handle state change', () => {
|
||||
it.each([[true], [false]])('%s', async (fullscreen: boolean) => {
|
||||
const api = createCardAPI();
|
||||
|
||||
const provider = mock<FullscreenProvider>();
|
||||
vi.mocked(FullscreenProviderFactory.create).mockReturnValue(provider);
|
||||
|
||||
new FullscreenManager(api);
|
||||
|
||||
const handler = vi.mocked(FullscreenProviderFactory.create).mock.calls[0][1];
|
||||
|
||||
provider.isInFullscreen.mockReturnValue(fullscreen);
|
||||
|
||||
handler();
|
||||
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith({
|
||||
fullscreen: fullscreen,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should create provider from factory', () => {
|
||||
const api = createCardAPI();
|
||||
|
||||
new FullscreenManager(api);
|
||||
|
||||
expect(FullscreenProviderFactory.create).toBeCalledWith(api, expect.anything());
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,162 @@
|
||||
import screenfull from 'screenfull';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { ScreenfullFullScreenProvider } from '../../../../src/card-controller/fullscreen/screenfull';
|
||||
import { createCardAPI, setScreenfulEnabled } from '../../../test-utils';
|
||||
|
||||
vi.mock('screenfull', () => ({
|
||||
default: {
|
||||
exit: vi.fn(),
|
||||
request: vi.fn(),
|
||||
off: vi.fn(),
|
||||
on: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const setScreenfulFullscreen = (fullscreen: boolean): void => {
|
||||
Object.defineProperty(screenfull, 'isFullscreen', {
|
||||
value: fullscreen,
|
||||
writable: true,
|
||||
});
|
||||
};
|
||||
|
||||
// @vitest-environment jsdom
|
||||
describe('ScreenfullFullScreenProvider', () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('should connect', () => {
|
||||
it('should connect if enabled', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
const on = vi.mocked(screenfull.on);
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
provider.connect();
|
||||
|
||||
expect(on).toBeCalledWith('change', expect.anything());
|
||||
});
|
||||
|
||||
it('should not connect if not enabled', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
const on = vi.mocked(screenfull.on);
|
||||
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
provider.connect();
|
||||
|
||||
expect(on).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should disconnect', () => {
|
||||
it('should disconnect if enabled', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
const off = vi.mocked(screenfull.off);
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
provider.disconnect();
|
||||
|
||||
expect(off).toBeCalledWith('change', expect.anything());
|
||||
});
|
||||
|
||||
it('should not disconnect if not enabled', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
const off = vi.mocked(screenfull.off);
|
||||
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
provider.disconnect();
|
||||
|
||||
expect(off).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should return if in fullscreen', () => {
|
||||
it('should return true if in fullscreen', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
setScreenfulFullscreen(true);
|
||||
|
||||
expect(provider.isInFullscreen()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if not in fullscreen', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
setScreenfulFullscreen(false);
|
||||
|
||||
expect(provider.isInFullscreen()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false if not supported', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
|
||||
setScreenfulEnabled(false);
|
||||
setScreenfulFullscreen(true);
|
||||
|
||||
expect(provider.isInFullscreen()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should return if supported', () => {
|
||||
it('should return true if supported', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
expect(provider.isSupported()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if not supported', () => {
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
expect(provider.isSupported()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should set fullscreen', () => {
|
||||
it('should request fullscreen if fullscreen is true', () => {
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const provider = new ScreenfullFullScreenProvider(api, vi.fn());
|
||||
|
||||
provider.setFullscreen(true);
|
||||
|
||||
expect(screenfull.request).toBeCalledWith(element);
|
||||
});
|
||||
|
||||
it('should exit fullscreen if fullscreen is false', () => {
|
||||
setScreenfulEnabled(true);
|
||||
|
||||
const provider = new ScreenfullFullScreenProvider(createCardAPI(), vi.fn());
|
||||
|
||||
provider.setFullscreen(false);
|
||||
|
||||
expect(screenfull.exit).toBeCalled();
|
||||
});
|
||||
|
||||
it('should take no action if not supported', () => {
|
||||
setScreenfulEnabled(false);
|
||||
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const provider = new ScreenfullFullScreenProvider(api, vi.fn());
|
||||
|
||||
provider.setFullscreen(true);
|
||||
provider.setFullscreen(false);
|
||||
|
||||
expect(screenfull.request).not.toBeCalled();
|
||||
expect(screenfull.exit).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,236 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { mock } from 'vitest-mock-extended';
|
||||
import { CardController } from '../../../../src/card-controller/controller';
|
||||
import { WebkitFullScreenProvider } from '../../../../src/card-controller/fullscreen/webkit';
|
||||
import { FrigateCardMediaPlayer, WebkitHTMLVideoElement } from '../../../../src/types';
|
||||
import { createCardAPI, createMediaLoadedInfo } from '../../../test-utils';
|
||||
|
||||
const createWebkitVideoElement = (): HTMLVideoElement &
|
||||
Partial<WebkitHTMLVideoElement> => {
|
||||
return document.createElement('video');
|
||||
};
|
||||
|
||||
const setElement = (api: CardController, element: HTMLElement): void => {
|
||||
const player = mock<FrigateCardMediaPlayer>();
|
||||
player.getFullscreenElement.mockReturnValue(element);
|
||||
|
||||
vi.mocked(api.getMediaLoadedInfoManager().get).mockReturnValue(
|
||||
createMediaLoadedInfo({
|
||||
player: player,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
// @vitest-environment jsdom
|
||||
describe('WebkitFullScreenProvider', () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should connect', () => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
provider.connect();
|
||||
|
||||
expect(api.getConditionsManager().addListener).toBeCalledWith(expect.anything());
|
||||
});
|
||||
|
||||
it('should disconnect', () => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
provider.disconnect();
|
||||
|
||||
expect(api.getConditionsManager().removeListener).toBeCalledWith(expect.anything());
|
||||
});
|
||||
|
||||
describe('should return if in fullscreen', () => {
|
||||
it.each([[true], [false]])('%s', async (fullscreen: boolean) => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
const element = createWebkitVideoElement();
|
||||
element.webkitDisplayingFullscreen = fullscreen;
|
||||
|
||||
setElement(api, element);
|
||||
|
||||
expect(provider.isInFullscreen()).toBe(fullscreen);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should return if supported', () => {
|
||||
it.each([[true], [false]])('%s', async (supported: boolean) => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
const element = createWebkitVideoElement();
|
||||
element.webkitSupportsFullscreen = supported;
|
||||
|
||||
setElement(api, element);
|
||||
|
||||
expect(provider.isSupported()).toBe(supported);
|
||||
});
|
||||
});
|
||||
|
||||
describe('should set fullscreen', () => {
|
||||
it('should request fullscreen if fullscreen is true', () => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
const element = createWebkitVideoElement();
|
||||
element.webkitEnterFullscreen = vi.fn();
|
||||
element.webkitSupportsFullscreen = true;
|
||||
|
||||
setElement(api, element);
|
||||
|
||||
provider.setFullscreen(true);
|
||||
|
||||
expect(element.webkitEnterFullscreen).toBeCalled();
|
||||
});
|
||||
|
||||
it('should exit fullscreen if fullscreen is true', () => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
const element = createWebkitVideoElement();
|
||||
element.webkitExitFullscreen = vi.fn();
|
||||
element.webkitSupportsFullscreen = true;
|
||||
|
||||
setElement(api, element);
|
||||
|
||||
provider.setFullscreen(false);
|
||||
|
||||
expect(element.webkitExitFullscreen).toBeCalled();
|
||||
});
|
||||
|
||||
it('should take no action if not supported', () => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
const element = createWebkitVideoElement();
|
||||
element.webkitEnterFullscreen = vi.fn();
|
||||
element.webkitExitFullscreen = vi.fn();
|
||||
element.webkitSupportsFullscreen = false;
|
||||
|
||||
setElement(api, element);
|
||||
|
||||
provider.setFullscreen(true);
|
||||
provider.setFullscreen(false);
|
||||
|
||||
expect(element.webkitEnterFullscreen).not.toBeCalled();
|
||||
expect(element.webkitExitFullscreen).not.toBeCalled();
|
||||
});
|
||||
|
||||
it('should take no action if element is not a video', () => {
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, vi.fn());
|
||||
|
||||
const element = document.createElement('img') as HTMLImageElement &
|
||||
Partial<WebkitHTMLVideoElement>;
|
||||
element.webkitEnterFullscreen = vi.fn();
|
||||
element.webkitExitFullscreen = vi.fn();
|
||||
|
||||
setElement(api, element);
|
||||
|
||||
provider.setFullscreen(true);
|
||||
provider.setFullscreen(false);
|
||||
|
||||
expect(element.webkitEnterFullscreen).not.toBeCalled();
|
||||
expect(element.webkitExitFullscreen).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should handle state changes', () => {
|
||||
describe('should call handler when fullscreen state changes', () => {
|
||||
it.each([['webkitbeginfullscreen'], ['webkitendfullscreen']])(
|
||||
'%s',
|
||||
(event: string) => {
|
||||
const handler = vi.fn();
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, handler);
|
||||
|
||||
provider.connect();
|
||||
|
||||
const conditionChangeHandler = vi.mocked(
|
||||
api.getConditionsManager().addListener,
|
||||
).mock.calls[0][0];
|
||||
|
||||
const element_1 = createWebkitVideoElement();
|
||||
const player_1 = mock<FrigateCardMediaPlayer>();
|
||||
player_1.getFullscreenElement.mockReturnValue(element_1);
|
||||
const mediaLoadedInfo_1 = createMediaLoadedInfo({ player: player_1 });
|
||||
|
||||
conditionChangeHandler({ mediaLoadedInfo: mediaLoadedInfo_1 });
|
||||
|
||||
element_1.dispatchEvent(new Event(event));
|
||||
|
||||
expect(handler).toBeCalledTimes(1);
|
||||
|
||||
const element_2 = createWebkitVideoElement();
|
||||
const player_2 = mock<FrigateCardMediaPlayer>();
|
||||
player_2.getFullscreenElement.mockReturnValue(element_2);
|
||||
const mediaLoadedInfo_2 = createMediaLoadedInfo({ player: player_2 });
|
||||
|
||||
conditionChangeHandler(
|
||||
{ mediaLoadedInfo: mediaLoadedInfo_2 },
|
||||
{ mediaLoadedInfo: mediaLoadedInfo_1 },
|
||||
);
|
||||
|
||||
element_2.dispatchEvent(new Event(event));
|
||||
|
||||
expect(handler).toBeCalledTimes(2);
|
||||
|
||||
// Events on the old element should be ignored.
|
||||
element_1.dispatchEvent(new Event(event));
|
||||
|
||||
expect(handler).toBeCalledTimes(2);
|
||||
|
||||
// Test the media loaded info not changing.
|
||||
conditionChangeHandler(
|
||||
{ mediaLoadedInfo: mediaLoadedInfo_2 },
|
||||
{ mediaLoadedInfo: mediaLoadedInfo_2 },
|
||||
);
|
||||
|
||||
// Events on the new element should still be handled.
|
||||
element_2.dispatchEvent(new Event(event));
|
||||
|
||||
expect(handler).toBeCalledTimes(3);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should play the video after fullscreen ends', () => {
|
||||
vi.useFakeTimers();
|
||||
|
||||
const handler = vi.fn();
|
||||
const api = createCardAPI();
|
||||
const provider = new WebkitFullScreenProvider(api, handler);
|
||||
|
||||
provider.connect();
|
||||
|
||||
const conditionChangeHandler = vi.mocked(api.getConditionsManager().addListener).mock
|
||||
.calls[0][0];
|
||||
|
||||
const element = createWebkitVideoElement();
|
||||
element.play = vi.fn();
|
||||
|
||||
setElement(api, element);
|
||||
|
||||
const player = mock<FrigateCardMediaPlayer>();
|
||||
player.getFullscreenElement.mockReturnValue(element);
|
||||
const mediaLoadedInfo = createMediaLoadedInfo({ player });
|
||||
|
||||
conditionChangeHandler({ mediaLoadedInfo });
|
||||
|
||||
element.dispatchEvent(new Event('webkitendfullscreen'));
|
||||
|
||||
expect(element.play).not.toBeCalled();
|
||||
|
||||
vi.runOnlyPendingTimers();
|
||||
|
||||
expect(element.play).toBeCalled();
|
||||
});
|
||||
});
|
||||
@@ -8,7 +8,9 @@ describe('MediaLoadedInfoManager', () => {
|
||||
const manager = new MediaLoadedInfoManager(api);
|
||||
|
||||
manager.initialize();
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith({ media_loaded: false });
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith({
|
||||
mediaLoadedInfo: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('should set', () => {
|
||||
@@ -21,7 +23,7 @@ describe('MediaLoadedInfoManager', () => {
|
||||
expect(manager.has()).toBeTruthy();
|
||||
expect(manager.get()).toBe(mediaInfo);
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith(
|
||||
expect.objectContaining({ media_loaded: true }),
|
||||
expect.objectContaining({ mediaLoadedInfo: mediaInfo }),
|
||||
);
|
||||
expect(api.getStyleManager().setExpandedMode).toBeCalled();
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
@@ -30,9 +32,9 @@ describe('MediaLoadedInfoManager', () => {
|
||||
it('should not set invalid media info', () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new MediaLoadedInfoManager(api);
|
||||
const mediaInfo = createMediaLoadedInfo({ width: 0, height: 0 });
|
||||
const mediaLoadedInfo = createMediaLoadedInfo({ width: 0, height: 0 });
|
||||
|
||||
manager.set(mediaInfo);
|
||||
manager.set(mediaLoadedInfo);
|
||||
|
||||
expect(manager.has()).toBeFalsy();
|
||||
expect(manager.get()).toBeNull();
|
||||
@@ -42,18 +44,18 @@ describe('MediaLoadedInfoManager', () => {
|
||||
it('should get last known', () => {
|
||||
const api = createCardAPI();
|
||||
const manager = new MediaLoadedInfoManager(api);
|
||||
const mediaInfo = createMediaLoadedInfo();
|
||||
const mediaLoadedInfo = createMediaLoadedInfo();
|
||||
|
||||
manager.set(mediaInfo);
|
||||
manager.set(mediaLoadedInfo);
|
||||
|
||||
expect(manager.has()).toBeTruthy();
|
||||
|
||||
manager.clear();
|
||||
|
||||
expect(manager.has()).toBeFalsy();
|
||||
expect(manager.getLastKnown()).toBe(mediaInfo);
|
||||
expect(manager.getLastKnown()).toBe(mediaLoadedInfo);
|
||||
expect(api.getConditionsManager().setState).toBeCalledWith(
|
||||
expect.objectContaining({ media_loaded: false }),
|
||||
expect.objectContaining({ mediaLoadedInfo }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user