130 lines
4.5 KiB
TypeScript
130 lines
4.5 KiB
TypeScript
// @vitest-environment jsdom
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { createIssueManager } from '../../../src/card-controller/issues/factory';
|
|
import { IssueManager } from '../../../src/card-controller/issues/issue-manager';
|
|
import { ConditionStateManager } from '../../../src/condition-trigger/conditions/state-manager';
|
|
import { createCardAPI } from '../../test-utils';
|
|
import { createView } from '../../view/test-utils';
|
|
import { createSubscriptionHealth } from '../test-utils';
|
|
|
|
describe('createIssueManager', () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('should return a IssueManager instance', () => {
|
|
const manager = createIssueManager(createCardAPI(), createSubscriptionHealth());
|
|
expect(manager).toBeInstanceOf(IssueManager);
|
|
});
|
|
|
|
it('should register all expected issues', () => {
|
|
const manager = createIssueManager(
|
|
createCardAPI(),
|
|
createSubscriptionHealth(),
|
|
).getStateManager();
|
|
|
|
expect(manager.getIssueDescriptions()).toHaveLength(0);
|
|
|
|
const expectedKeys = [
|
|
'config_error',
|
|
'config_upgrade',
|
|
'config_upgrade_failure',
|
|
'connection',
|
|
'event_subscription',
|
|
'initialization',
|
|
'legacy_resource',
|
|
'media_query',
|
|
'media_unavailable',
|
|
'view_incompatible',
|
|
] as const;
|
|
|
|
for (const key of expectedKeys) {
|
|
expect(() => manager.getNotification(key)).not.toThrow();
|
|
}
|
|
});
|
|
|
|
it('should register issues in an order that determines priority', () => {
|
|
// Lock the registration order. The relative order of these issues
|
|
// governs full-card display priority (getFullCardIssue returns the
|
|
// first active full-card issue) and retry-loop priority. Alphabetizing
|
|
// the list in factory.ts would silently change both. Triggering in a
|
|
// scrambled order proves getIssueDescriptions reflects registration
|
|
// order, not trigger order.
|
|
const api = createCardAPI();
|
|
const stateManager = new ConditionStateManager();
|
|
vi.mocked(api.getConditionStateManager).mockReturnValue(stateManager);
|
|
const manager = createIssueManager(api, createSubscriptionHealth());
|
|
|
|
manager.trigger('media_query', { error: new Error('x') });
|
|
manager.trigger('initialization', { error: new Error('x') });
|
|
manager.trigger('config_error', { error: new Error('x') });
|
|
manager.trigger('view_incompatible', { error: new Error('x') });
|
|
|
|
const keys = manager
|
|
.getStateManager()
|
|
.getIssueDescriptions()
|
|
.map((d) => d.key);
|
|
|
|
expect(keys).toEqual([
|
|
'config_error',
|
|
'view_incompatible',
|
|
'initialization',
|
|
'media_query',
|
|
]);
|
|
});
|
|
|
|
it('should wire changeCallback so an issue can ask for a re-evaluation', () => {
|
|
const api = createCardAPI();
|
|
vi.mocked(api.getConditionStateManager).mockReturnValue(new ConditionStateManager());
|
|
const health = createSubscriptionHealth();
|
|
|
|
const manager = createIssueManager(api, health);
|
|
vi.mocked(api.getCardElementManager().update).mockClear();
|
|
|
|
// A subscription starts failing. Nothing has asked the IssueManager to
|
|
// re-evaluate, so it does not know yet.
|
|
health.getFailures.mockReturnValue([{ key: 'camera-1', error: 'failed' }]);
|
|
expect(api.getCardElementManager().update).not.toHaveBeenCalled();
|
|
|
|
// The callback EventSubscriptionIssue registered is what asks it to
|
|
// re-evaluate.
|
|
const changeCallback = health.addListener.mock.calls[0][0];
|
|
changeCallback();
|
|
|
|
expect(manager.getStateManager().getIssuePresence().has('event_subscription')).toBe(
|
|
true,
|
|
);
|
|
expect(api.getCardElementManager().update).toHaveBeenCalled();
|
|
});
|
|
|
|
it('should report a media failure raised by a component', () => {
|
|
const api = createCardAPI();
|
|
const stateManager = new ConditionStateManager();
|
|
vi.mocked(api.getConditionStateManager).mockReturnValue(stateManager);
|
|
vi.mocked(api.getViewManager().getView).mockReturnValue(
|
|
createView({ view: 'live', camera: 'camera-1' }),
|
|
);
|
|
|
|
const manager = createIssueManager(api, createSubscriptionHealth());
|
|
|
|
stateManager.setState({ targetID: 'camera-1', view: 'live' });
|
|
expect(manager.getStateManager().getIssuePresence().has('media_unavailable')).toBe(
|
|
false,
|
|
);
|
|
|
|
manager.trigger('media_unavailable', {
|
|
targetID: 'camera-1',
|
|
reason: 'not_loading',
|
|
});
|
|
|
|
expect(manager.getStateManager().getIssuePresence().has('media_unavailable')).toBe(
|
|
true,
|
|
);
|
|
});
|
|
});
|