test: Split test utilities to improve test times (#2622)
This commit is contained in:
@@ -17,9 +17,9 @@ import type {
|
||||
} from '../../../src/card-controller/issues/types';
|
||||
import { ConditionStateManager } from '../../../src/condition-trigger/conditions/state-manager';
|
||||
import type { InteractionMode } from '../../../src/config/schema/view';
|
||||
import { createConfig } from '../../config/test-utils';
|
||||
import {
|
||||
createCardAPI,
|
||||
createConfig,
|
||||
createHASS,
|
||||
createMediaLoadedInfo,
|
||||
flushPromises,
|
||||
@@ -109,7 +109,7 @@ describe('IssueManager', () => {
|
||||
|
||||
stateManager.setState({ view: 'live' });
|
||||
|
||||
expect(issue.detectDynamic).toBeCalled();
|
||||
expect(issue.detectDynamic).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should keep a liveness-triggered error active while its media still reads as loaded', () => {
|
||||
@@ -170,7 +170,7 @@ describe('IssueManager', () => {
|
||||
conditionStateManager.setState({ initialized: true });
|
||||
await flushPromises();
|
||||
|
||||
expect(detectStatic).toBeCalledWith(hass);
|
||||
expect(detectStatic).toHaveBeenCalledWith(hass);
|
||||
});
|
||||
|
||||
it('should not run static detection when hass is unset', () => {
|
||||
@@ -185,7 +185,7 @@ describe('IssueManager', () => {
|
||||
|
||||
conditionStateManager.setState({ initialized: true });
|
||||
|
||||
expect(detectStatic).not.toBeCalled();
|
||||
expect(detectStatic).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not run static detection on unrelated state changes', () => {
|
||||
@@ -202,7 +202,7 @@ describe('IssueManager', () => {
|
||||
conditionStateManager.setState({ hass });
|
||||
conditionStateManager.setState({ view: 'live' });
|
||||
|
||||
expect(detectStatic).not.toBeCalled();
|
||||
expect(detectStatic).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -219,7 +219,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.trigger('config_error', { error: new Error('cfg') });
|
||||
|
||||
expect(issue.trigger).toBeCalledWith({ error: expect.any(Error) });
|
||||
expect(issue.trigger).toHaveBeenCalledWith({ error: expect.any(Error) });
|
||||
});
|
||||
|
||||
it('should update the card even when state was mutated before detectDynamic', () => {
|
||||
@@ -242,7 +242,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.trigger('config_error', { error: new Error('cfg') });
|
||||
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
expect(api.getCardElementManager().update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should never auto-popup on trigger -- non-full-card issues surface via the status-bar icon; user clicks to open', () => {
|
||||
@@ -261,7 +261,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.trigger('view_incompatible', { error: new Error('mismatch') });
|
||||
|
||||
expect(api.getNotificationManager().setNotification).not.toBeCalled();
|
||||
expect(api.getNotificationManager().setNotification).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -273,14 +273,14 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
manager.retry('media_unavailable');
|
||||
|
||||
expect(issue.retry).toBeCalled();
|
||||
expect(issue.retry).toHaveBeenCalled();
|
||||
|
||||
// Timer should have been reset -- advancing less than retrySeconds should
|
||||
// not fire it again.
|
||||
assert(issue.retry);
|
||||
vi.mocked(issue.retry).mockClear();
|
||||
vi.advanceTimersByTime(500);
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should force retry even when needsRetry is false', () => {
|
||||
@@ -293,7 +293,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.retry('media_unavailable', true);
|
||||
|
||||
expect(issue.retry).toBeCalled();
|
||||
expect(issue.retry).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -311,7 +311,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.evaluate();
|
||||
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
expect(api.getCardElementManager().update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not write issue presence back into the condition state', () => {
|
||||
@@ -328,7 +328,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.evaluate();
|
||||
|
||||
expect(api.getConditionStateManager().setState).not.toBeCalled();
|
||||
expect(api.getConditionStateManager().setState).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not update the card when there are no issues', () => {
|
||||
@@ -340,7 +340,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.evaluate();
|
||||
|
||||
expect(api.getCardElementManager().update).not.toBeCalled();
|
||||
expect(api.getCardElementManager().update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call update when an active issue swaps sub-states without changing the key set', () => {
|
||||
@@ -371,7 +371,7 @@ describe('IssueManager', () => {
|
||||
);
|
||||
manager.evaluate();
|
||||
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
expect(api.getCardElementManager().update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call update when content is identical across evaluations', () => {
|
||||
@@ -390,7 +390,7 @@ describe('IssueManager', () => {
|
||||
// Re-evaluate without any change.
|
||||
manager.evaluate();
|
||||
|
||||
expect(api.getCardElementManager().update).not.toBeCalled();
|
||||
expect(api.getCardElementManager().update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not request repeated updates as retry callback closures churn', () => {
|
||||
@@ -418,7 +418,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.evaluate();
|
||||
|
||||
expect(api.getCardElementManager().update).not.toBeCalled();
|
||||
expect(api.getCardElementManager().update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trigger evaluate from listener on condition state manager', () => {
|
||||
@@ -435,7 +435,7 @@ describe('IssueManager', () => {
|
||||
|
||||
stateManager.setState({ view: 'live' });
|
||||
|
||||
expect(issue.detectDynamic).toBeCalled();
|
||||
expect(issue.detectDynamic).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -452,7 +452,9 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.showNotification('media_query');
|
||||
|
||||
expect(api.getNotificationManager().setNotification).toBeCalledWith(notification);
|
||||
expect(api.getNotificationManager().setNotification).toHaveBeenCalledWith(
|
||||
notification,
|
||||
);
|
||||
});
|
||||
|
||||
it('should not call setNotification when no notification exists for key', () => {
|
||||
@@ -460,7 +462,9 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.showNotification('initialization');
|
||||
|
||||
expect(createCardAPI().getNotificationManager().setNotification).not.toBeCalled();
|
||||
expect(
|
||||
createCardAPI().getNotificationManager().setNotification,
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -476,7 +480,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.runAllTimers();
|
||||
|
||||
expect(api.getViewManager().setViewWithMergedContext).not.toBeCalled();
|
||||
expect(api.getViewManager().setViewWithMergedContext).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not schedule a retry when config is null', () => {
|
||||
@@ -495,7 +499,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.runAllTimers();
|
||||
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not schedule a retry when retry_seconds is 0', () => {
|
||||
@@ -504,7 +508,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.runAllTimers();
|
||||
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should schedule a retry when an issue wants retry and retry_seconds > 0', () => {
|
||||
@@ -513,7 +517,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(5000);
|
||||
|
||||
expect(issue.retry).toBeCalled();
|
||||
expect(issue.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call retry on the issue when the timer fires', () => {
|
||||
@@ -522,7 +526,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
|
||||
expect(issue.retry).toBeCalled();
|
||||
expect(issue.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not schedule a second timer if one is already running', () => {
|
||||
@@ -533,7 +537,7 @@ describe('IssueManager', () => {
|
||||
|
||||
vi.advanceTimersByTime(10000);
|
||||
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should stop repeated timer when needsRetry becomes false', () => {
|
||||
@@ -541,16 +545,16 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
|
||||
assert(issue.needsRetry);
|
||||
vi.mocked(issue.needsRetry).mockReturnValue(false);
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should skip scheduled retry when user is interacting and mode is inactive', () => {
|
||||
@@ -561,7 +565,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow scheduled retry when user is not interacting and mode is inactive', () => {
|
||||
@@ -572,7 +576,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
|
||||
expect(issue.retry).toBeCalled();
|
||||
expect(issue.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should allow scheduled retry when mode is all regardless of interaction', () => {
|
||||
@@ -584,7 +588,7 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
|
||||
expect(issue.retry).toBeCalled();
|
||||
expect(issue.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should retry on next interval after interaction ends', () => {
|
||||
@@ -594,11 +598,11 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
|
||||
vi.mocked(api.getInteractionManager().hasInteraction).mockReturnValue(false);
|
||||
vi.advanceTimersByTime(DEFAULT_RETRY_SECONDS * 1000);
|
||||
expect(issue.retry).toBeCalled();
|
||||
expect(issue.retry).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -610,10 +614,10 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.5 * 1000 - 1);
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
|
||||
vi.advanceTimersByTime(1);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should schedule the first retry at the upper bound when jitter is max', () => {
|
||||
@@ -623,10 +627,10 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 1.0 * 1000 - 1);
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
|
||||
vi.advanceTimersByTime(1);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should double the base delay on each successive attempt', () => {
|
||||
@@ -636,13 +640,13 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 2 * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(2);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(2);
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 4 * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(3);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it('should cap the backoff at the max delay', () => {
|
||||
@@ -662,15 +666,15 @@ describe('IssueManager', () => {
|
||||
vi.advanceTimersByTime(delaySeconds * 1000);
|
||||
attempts++;
|
||||
}
|
||||
expect(issue.retry).toBeCalledTimes(attempts);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(attempts);
|
||||
|
||||
// The next attempt clamps to MAX instead of the would-be larger delay.
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_MAX_SECONDS * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(attempts + 1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(attempts + 1);
|
||||
|
||||
// And it stays capped at MAX rather than growing further.
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_MAX_SECONDS * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(attempts + 2);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(attempts + 2);
|
||||
});
|
||||
|
||||
it('should reset the attempt counter when the issue clears', () => {
|
||||
@@ -681,14 +685,14 @@ describe('IssueManager', () => {
|
||||
// Run two retries -- second delay should be 2x the first.
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 2 * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(2);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(2);
|
||||
|
||||
// Clear the issue: needsRetry returns false. The next timer fire sees
|
||||
// it cleared and resets the attempt counter.
|
||||
assert(issue.needsRetry);
|
||||
vi.mocked(issue.needsRetry).mockReturnValue(false);
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 4 * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(2);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(2);
|
||||
|
||||
// Re-arm: needsRetry returns true again, evaluate to re-schedule.
|
||||
vi.mocked(issue.needsRetry).mockReturnValue(true);
|
||||
@@ -697,7 +701,7 @@ describe('IssueManager', () => {
|
||||
// Next delay should be back at the base (attempt 0), not continuing
|
||||
// from where we left off.
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(3);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it('should not grow the delay while retries are gated by user interaction', () => {
|
||||
@@ -717,13 +721,13 @@ describe('IssueManager', () => {
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
|
||||
// Clear the interaction. The next firing -- still at the base delay -- is
|
||||
// now allowed and the retry runs.
|
||||
vi.mocked(api.getInteractionManager().hasInteraction).mockReturnValue(false);
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should reset the attempt counter when retries are disabled and re-enabled', () => {
|
||||
@@ -736,7 +740,7 @@ describe('IssueManager', () => {
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 2 * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(2);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(2);
|
||||
|
||||
// Disable retries via config.
|
||||
const config = createConfig();
|
||||
@@ -751,7 +755,7 @@ describe('IssueManager', () => {
|
||||
// Let the pending timer fire. The retry runs (#3), then evaluate sees
|
||||
// retry_seconds=0 and resets _retryAttempt.
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 4 * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(3);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(3);
|
||||
|
||||
// Re-enable.
|
||||
vi.mocked(api.getConfigManager().getConfig).mockReturnValue({
|
||||
@@ -767,7 +771,7 @@ describe('IssueManager', () => {
|
||||
// delay BASE * 8 * 0.75 = 180s. With the reset, it's BASE * 0.75 = 22.5s,
|
||||
// so advancing only the base interval triggers the next retry.
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(4);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -799,7 +803,7 @@ describe('IssueManager', () => {
|
||||
// First attempt fires at the base delay, advancing the backoff to
|
||||
// attempt 1.
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
|
||||
// The attempt is now in flight: the problem is still unresolved
|
||||
// (needsRetry) but cannot be retried right now (canRetryNow). The running
|
||||
@@ -807,7 +811,7 @@ describe('IssueManager', () => {
|
||||
canRetryNow.mockReturnValue(false);
|
||||
manager.evaluate();
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_MAX_SECONDS * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
|
||||
// The attempt fails and becomes retryable again. Because the backoff was
|
||||
// preserved, the next delay is the attempt-1 step (base*2), not base.
|
||||
@@ -815,10 +819,10 @@ describe('IssueManager', () => {
|
||||
manager.evaluate();
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(1);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(1);
|
||||
|
||||
vi.advanceTimersByTime(RETRY_EXPONENTIAL_BASE_SECONDS * 2 * 0.75 * 1000);
|
||||
expect(issue.retry).toBeCalledTimes(2);
|
||||
expect(issue.retry).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -837,7 +841,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.reset('config_error');
|
||||
|
||||
expect(issue.reset).toBeCalled();
|
||||
expect(issue.reset).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should skip reset when targeted key has no active issue', () => {
|
||||
@@ -854,8 +858,8 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.reset('config_error');
|
||||
|
||||
expect(issue.reset).not.toBeCalled();
|
||||
expect(issue.detectDynamic).not.toBeCalled();
|
||||
expect(issue.reset).not.toHaveBeenCalled();
|
||||
expect(issue.detectDynamic).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -868,7 +872,7 @@ describe('IssueManager', () => {
|
||||
|
||||
vi.advanceTimersByTime(5000);
|
||||
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should gate evaluate while suspended', () => {
|
||||
@@ -884,7 +888,7 @@ describe('IssueManager', () => {
|
||||
manager.suspend();
|
||||
manager.evaluate();
|
||||
|
||||
expect(issue.detectDynamic).not.toBeCalled();
|
||||
expect(issue.detectDynamic).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should preserve issue state across suspend', () => {
|
||||
@@ -918,8 +922,8 @@ describe('IssueManager', () => {
|
||||
manager.suspend();
|
||||
manager.resume();
|
||||
|
||||
expect(issue.detectDynamic).toBeCalled();
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
expect(issue.detectDynamic).toHaveBeenCalled();
|
||||
expect(api.getCardElementManager().update).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should invoke Issue.suspend on timer-backed issues when suspended', () => {
|
||||
@@ -931,7 +935,7 @@ describe('IssueManager', () => {
|
||||
|
||||
manager.suspend();
|
||||
|
||||
expect(issue.suspend).toBeCalled();
|
||||
expect(issue.suspend).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should tolerate issues without a suspend hook', () => {
|
||||
@@ -961,8 +965,8 @@ describe('IssueManager', () => {
|
||||
|
||||
vi.advanceTimersByTime(5000);
|
||||
|
||||
expect(issue.retry).not.toBeCalled();
|
||||
expect(issue.reset).toBeCalled();
|
||||
expect(issue.retry).not.toHaveBeenCalled();
|
||||
expect(issue.reset).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ describe('ConfigUpgradeFailureIssue', () => {
|
||||
await issue.detectStatic();
|
||||
|
||||
expect(issue.hasIssue()).toBe(true);
|
||||
expect(hasConfigUpgradeFailures).toBeCalledWith(rawConfig);
|
||||
expect(hasConfigUpgradeFailures).toHaveBeenCalledWith(rawConfig);
|
||||
expect(issue.getIssue()).toEqual(
|
||||
expect.objectContaining({
|
||||
icon: 'mdi:update',
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('ConfigUpgradeIssue', () => {
|
||||
await issue.detectStatic();
|
||||
|
||||
expect(issue.hasIssue()).toBe(true);
|
||||
expect(isConfigUpgradeable).toBeCalledWith(rawConfig);
|
||||
expect(isConfigUpgradeable).toHaveBeenCalledWith(rawConfig);
|
||||
});
|
||||
|
||||
it('should detect non-upgradeable config', async () => {
|
||||
|
||||
@@ -19,7 +19,7 @@ describe('EventSubscriptionIssue', () => {
|
||||
|
||||
new EventSubscriptionIssue(health, changeCallback);
|
||||
|
||||
expect(health.addListener).toBeCalledWith(changeCallback);
|
||||
expect(health.addListener).toHaveBeenCalledWith(changeCallback);
|
||||
});
|
||||
|
||||
it('should have no issue when there are no failures', () => {
|
||||
@@ -65,7 +65,7 @@ describe('EventSubscriptionIssue', () => {
|
||||
const issue = new EventSubscriptionIssue(health, vi.fn());
|
||||
|
||||
expect(issue.retry()).toBe(true);
|
||||
expect(health.retry).toBeCalledTimes(1);
|
||||
expect(health.retry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not opt into IssueManager-scheduled retries', () => {
|
||||
@@ -84,6 +84,6 @@ describe('EventSubscriptionIssue', () => {
|
||||
|
||||
issue.destroy();
|
||||
|
||||
expect(unsubscribe).toBeCalledTimes(1);
|
||||
expect(unsubscribe).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('InitializationIssue', () => {
|
||||
const tapAction = control.actions?.tap_action as InternalCallbackActionConfig;
|
||||
await tapAction.callback(api);
|
||||
|
||||
expect(api.getIssueManager().retry).toBeCalledWith('initialization', true);
|
||||
expect(api.getIssueManager().retry).toHaveBeenCalledWith('initialization', true);
|
||||
});
|
||||
|
||||
describe('detectDynamic', () => {
|
||||
@@ -190,8 +190,8 @@ describe('InitializationIssue', () => {
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(issue.hasIssue()).toBe(false);
|
||||
expect(api.getInitializationManager().uninitializeMandatory).toBeCalled();
|
||||
expect(api.getCameraManager().destroy).toBeCalled();
|
||||
expect(api.getInitializationManager().uninitializeMandatory).toHaveBeenCalled();
|
||||
expect(api.getCameraManager().destroy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be a no-op while a retry is already in flight', () => {
|
||||
@@ -205,8 +205,10 @@ describe('InitializationIssue', () => {
|
||||
const result = issue.retry();
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(api.getInitializationManager().uninitializeMandatory).not.toBeCalled();
|
||||
expect(api.getCameraManager().destroy).not.toBeCalled();
|
||||
expect(
|
||||
api.getInitializationManager().uninitializeMandatory,
|
||||
).not.toHaveBeenCalled();
|
||||
expect(api.getCameraManager().destroy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -179,14 +179,14 @@ describe('LegacyResourceIssue', () => {
|
||||
const result = await issue.fix(hass);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(hass.callWS).toBeCalledWith(
|
||||
expect(hass.callWS).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: 'lovelace/resources/delete',
|
||||
resource_id: '1',
|
||||
}),
|
||||
);
|
||||
expect(issue.hasIssue()).toBe(false);
|
||||
expect(onChange).toBeCalled();
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not fix when only legacy resource exists', async () => {
|
||||
@@ -238,7 +238,7 @@ describe('LegacyResourceIssue', () => {
|
||||
|
||||
const result = await issue.fix(hass);
|
||||
expect(result).toBe(false);
|
||||
expect(onChange).not.toBeCalled();
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return false when the verification fetch silently fails after a successful delete', async () => {
|
||||
@@ -272,7 +272,7 @@ describe('LegacyResourceIssue', () => {
|
||||
const result = await issue.fix(hass);
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(onChange).not.toBeCalled();
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return false when re-detection still finds legacy resource', async () => {
|
||||
@@ -314,7 +314,7 @@ describe('LegacyResourceIssue', () => {
|
||||
const result = await issue.fix(hass);
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(onChange).not.toBeCalled();
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fix multiple legacy resources', async () => {
|
||||
@@ -437,7 +437,7 @@ describe('LegacyResourceIssue', () => {
|
||||
|
||||
await callback?.(api);
|
||||
|
||||
expect(hass.callWS).toBeCalledWith(
|
||||
expect(hass.callWS).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: 'lovelace/resources/delete',
|
||||
}),
|
||||
|
||||
@@ -87,7 +87,7 @@ describe('MediaQueryIssue', () => {
|
||||
const tapAction = control?.actions?.tap_action as InternalCallbackActionConfig;
|
||||
await tapAction.callback(api);
|
||||
|
||||
expect(api.getIssueManager().retry).toBeCalledWith('media_query', true);
|
||||
expect(api.getIssueManager().retry).toHaveBeenCalledWith('media_query', true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,7 +133,7 @@ describe('MediaQueryIssue', () => {
|
||||
const result = issue.retry();
|
||||
|
||||
expect(result).toEqual(true);
|
||||
expect(api.getViewManager().setViewByParametersWithNewQuery).toBeCalledWith({
|
||||
expect(api.getViewManager().setViewByParametersWithNewQuery).toHaveBeenCalledWith({
|
||||
intent: 'retry',
|
||||
});
|
||||
|
||||
@@ -189,7 +189,9 @@ describe('MediaQueryIssue', () => {
|
||||
const result = issue.retry();
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(api.getViewManager().setViewByParametersWithNewQuery).toBeCalledTimes(1);
|
||||
expect(api.getViewManager().setViewByParametersWithNewQuery).toHaveBeenCalledTimes(
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
it('should stop treating the retry as in flight once the query settles without an outcome', async () => {
|
||||
|
||||
@@ -69,7 +69,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
vi.advanceTimersByTime(10000);
|
||||
|
||||
expect(issue.hasIssue()).toBe(true);
|
||||
expect(onChange).toBeCalled();
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not start timer when targetID is null (no provider rendering)', () => {
|
||||
@@ -229,7 +229,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
// Full 10s from camera-2's timer start.
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(issue.hasIssue()).toBe(true);
|
||||
expect(onChange).toBeCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not restart timer for same target while running', () => {
|
||||
@@ -251,7 +251,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
// 5 more seconds completes the original 10s timer.
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(issue.hasIssue()).toBe(true);
|
||||
expect(onChange).toBeCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not restart timer when targetID is undefined and matches', () => {
|
||||
@@ -266,7 +266,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
|
||||
vi.advanceTimersByTime(5000);
|
||||
expect(issue.hasIssue()).toBe(true);
|
||||
expect(onChange).toBeCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not restart timer if already timed out', () => {
|
||||
@@ -275,12 +275,12 @@ describe('MediaUnavailableIssue', () => {
|
||||
|
||||
issue.detectDynamic({ targetID: 'camera-1', view: 'live' });
|
||||
vi.advanceTimersByTime(10000);
|
||||
expect(onChange).toBeCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Calling detectDynamic again should not restart timer.
|
||||
issue.detectDynamic({ targetID: 'camera-1', view: 'live' });
|
||||
vi.advanceTimersByTime(10000);
|
||||
expect(onChange).toBeCalledTimes(1);
|
||||
expect(onChange).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -535,7 +535,10 @@ describe('MediaUnavailableIssue', () => {
|
||||
const tapAction = control?.actions?.tap_action as InternalCallbackActionConfig;
|
||||
await tapAction.callback(api);
|
||||
|
||||
expect(api.getIssueManager().retry).toBeCalledWith('media_unavailable', true);
|
||||
expect(api.getIssueManager().retry).toHaveBeenCalledWith(
|
||||
'media_unavailable',
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -618,7 +621,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
const result = issue.retry();
|
||||
|
||||
expect(result).toEqual(false);
|
||||
expect(api.getViewManager().setViewWithMergedContext).toBeCalledWith({
|
||||
expect(api.getViewManager().setViewWithMergedContext).toHaveBeenCalledWith({
|
||||
mediaEpoch: { 'camera-1': 1, 'media-1': 1 },
|
||||
});
|
||||
});
|
||||
@@ -633,7 +636,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
const result = issue.retry();
|
||||
|
||||
expect(result).toEqual(false);
|
||||
expect(api.getViewManager().setViewWithMergedContext).toBeCalledWith({
|
||||
expect(api.getViewManager().setViewWithMergedContext).toHaveBeenCalledWith({
|
||||
mediaEpoch: { [IMAGE_VIEW_TARGET_ID_SENTINEL]: 1 },
|
||||
});
|
||||
});
|
||||
@@ -650,7 +653,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
const result = issue.retry();
|
||||
|
||||
expect(result).toEqual(false);
|
||||
expect(api.getViewManager().setViewWithMergedContext).toBeCalledWith({
|
||||
expect(api.getViewManager().setViewWithMergedContext).toHaveBeenCalledWith({
|
||||
mediaEpoch: { 'camera-1': 6, 'camera-2': 3 },
|
||||
});
|
||||
});
|
||||
@@ -665,7 +668,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
|
||||
issue.retry();
|
||||
|
||||
expect(api.getViewManager().setViewWithMergedContext).toBeCalledWith({
|
||||
expect(api.getViewManager().setViewWithMergedContext).toHaveBeenCalledWith({
|
||||
mediaEpoch: { 'camera-1': 1 },
|
||||
});
|
||||
});
|
||||
@@ -701,7 +704,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
vi.advanceTimersByTime(10000);
|
||||
|
||||
expect(issue.hasIssue()).toBe(false);
|
||||
expect(onChange).not.toBeCalled();
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -714,7 +717,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
issue.trigger({ targetID: 'camera-1', reason: 'stalled' });
|
||||
fireMediaLoad(api, 'camera-1');
|
||||
|
||||
expect(onChange).toBeCalled();
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should unsubscribe from media loads on destroy', () => {
|
||||
@@ -725,7 +728,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
|
||||
issue.destroy();
|
||||
|
||||
expect(unsubscribe).toBeCalled();
|
||||
expect(unsubscribe).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -746,7 +749,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
// offscreen and that time does not count against them.
|
||||
vi.advanceTimersByTime(20000);
|
||||
expect(issue.hasIssue()).toBe(false);
|
||||
expect(onChange).not.toBeCalled();
|
||||
expect(onChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should preserve an already-active issue across suspend', () => {
|
||||
@@ -780,7 +783,7 @@ describe('MediaUnavailableIssue', () => {
|
||||
expect(issue.hasIssue()).toBe(false);
|
||||
vi.advanceTimersByTime(1);
|
||||
expect(issue.hasIssue()).toBe(true);
|
||||
expect(onChange).toBeCalled();
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,6 +20,6 @@ describe('createRetryControl', () => {
|
||||
const tapAction = control.actions?.tap_action as InternalCallbackActionConfig;
|
||||
await tapAction.callback(api);
|
||||
|
||||
expect(api.getIssueManager().retry).toBeCalledWith('media_query', true);
|
||||
expect(api.getIssueManager().retry).toHaveBeenCalledWith('media_query', true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -65,9 +65,9 @@ describe('IssueStateManager', () => {
|
||||
assert(mockConfigUpgrade.detectStatic);
|
||||
assert(mockLegacyResource.detectStatic);
|
||||
assert(mockMediaLoad.detectStatic);
|
||||
expect(mockConfigUpgrade.detectStatic).toBeCalledWith(hass);
|
||||
expect(mockLegacyResource.detectStatic).toBeCalledWith(hass);
|
||||
expect(mockMediaLoad.detectStatic).toBeCalledWith(hass);
|
||||
expect(mockConfigUpgrade.detectStatic).toHaveBeenCalledWith(hass);
|
||||
expect(mockLegacyResource.detectStatic).toHaveBeenCalledWith(hass);
|
||||
expect(mockMediaLoad.detectStatic).toHaveBeenCalledWith(hass);
|
||||
});
|
||||
|
||||
it('should isolate a failing issue and continue detecting the rest', async () => {
|
||||
@@ -87,8 +87,8 @@ describe('IssueStateManager', () => {
|
||||
await expect(manager.detectStatic(hass)).resolves.toBeUndefined();
|
||||
|
||||
// Detection continued to the final issue despite the two earlier failures.
|
||||
expect(mockMediaLoad.detectStatic).toBeCalledWith(hass);
|
||||
expect(spy).toBeCalledTimes(2);
|
||||
expect(mockMediaLoad.detectStatic).toHaveBeenCalledWith(hass);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
spy.mockRestore();
|
||||
});
|
||||
});
|
||||
@@ -100,7 +100,7 @@ describe('IssueStateManager', () => {
|
||||
manager.trigger('media_unavailable', { targetID: 'cam1', reason: 'stalled' });
|
||||
|
||||
assert(mockMediaLoad.trigger);
|
||||
expect(mockMediaLoad.trigger).toBeCalledWith({
|
||||
expect(mockMediaLoad.trigger).toHaveBeenCalledWith({
|
||||
targetID: 'cam1',
|
||||
reason: 'stalled',
|
||||
});
|
||||
@@ -112,7 +112,7 @@ describe('IssueStateManager', () => {
|
||||
manager.trigger('unknown' as never, {} as never);
|
||||
|
||||
assert(mockMediaLoad.trigger);
|
||||
expect(mockMediaLoad.trigger).not.toBeCalled();
|
||||
expect(mockMediaLoad.trigger).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,7 +123,7 @@ describe('IssueStateManager', () => {
|
||||
manager.detectDynamic({ view: 'live' });
|
||||
|
||||
assert(mockMediaLoad.detectDynamic);
|
||||
expect(mockMediaLoad.detectDynamic).toBeCalledWith({ view: 'live' });
|
||||
expect(mockMediaLoad.detectDynamic).toHaveBeenCalledWith({ view: 'live' });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -255,7 +255,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
manager.retry();
|
||||
|
||||
expect(mockMediaLoad.retry).toBeCalled();
|
||||
expect(mockMediaLoad.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call retry on issues that want retry with exclusive result', () => {
|
||||
@@ -266,7 +266,7 @@ describe('IssueStateManager', () => {
|
||||
|
||||
createManager().retry();
|
||||
|
||||
expect(mockMediaLoad.retry).toBeCalled();
|
||||
expect(mockMediaLoad.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call retry on issues that do not want retry', () => {
|
||||
@@ -277,7 +277,7 @@ describe('IssueStateManager', () => {
|
||||
manager.retry();
|
||||
|
||||
assert(mockMediaLoad.retry);
|
||||
expect(mockMediaLoad.retry).not.toBeCalled();
|
||||
expect(mockMediaLoad.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should stop after exclusive result and not call retry on subsequent issues', () => {
|
||||
@@ -293,9 +293,9 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
manager.retry();
|
||||
|
||||
expect(mockConfigUpgrade.retry).toBeCalled();
|
||||
expect(mockConfigUpgrade.retry).toHaveBeenCalled();
|
||||
assert(mockMediaLoad.retry);
|
||||
expect(mockMediaLoad.retry).not.toBeCalled();
|
||||
expect(mockMediaLoad.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should continue after non-exclusive result and call retry on subsequent issues', () => {
|
||||
@@ -312,8 +312,8 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
manager.retry();
|
||||
|
||||
expect(mockConfigUpgrade.retry).toBeCalled();
|
||||
expect(mockMediaLoad.retry).toBeCalled();
|
||||
expect(mockConfigUpgrade.retry).toHaveBeenCalled();
|
||||
expect(mockMediaLoad.retry).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -326,7 +326,7 @@ describe('IssueStateManager', () => {
|
||||
|
||||
createManager().retry('media_unavailable');
|
||||
|
||||
expect(mockMediaLoad.retry).toBeCalled();
|
||||
expect(mockMediaLoad.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call retry on the matching issue when needsRetry is false', () => {
|
||||
@@ -336,7 +336,7 @@ describe('IssueStateManager', () => {
|
||||
createManager().retry('media_unavailable');
|
||||
|
||||
assert(mockMediaLoad.retry);
|
||||
expect(mockMediaLoad.retry).not.toBeCalled();
|
||||
expect(mockMediaLoad.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call retry when force is true even if needsRetry is false', () => {
|
||||
@@ -347,14 +347,14 @@ describe('IssueStateManager', () => {
|
||||
|
||||
createManager().retry('media_unavailable', true);
|
||||
|
||||
expect(mockMediaLoad.retry).toBeCalled();
|
||||
expect(mockMediaLoad.retry).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing for unknown key', () => {
|
||||
createManager().retry('unknown' as never);
|
||||
|
||||
assert(mockMediaLoad.retry);
|
||||
expect(mockMediaLoad.retry).not.toBeCalled();
|
||||
expect(mockMediaLoad.retry).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -383,7 +383,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
await manager.detectStatic(createHASS());
|
||||
|
||||
expect(spy).toBeCalledWith(
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'Advanced Camera Card [issue=legacy_resource]: Legacy issue',
|
||||
);
|
||||
spy.mockRestore();
|
||||
@@ -400,7 +400,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
manager.detectDynamic({ view: 'live' });
|
||||
|
||||
expect(spy).toBeCalledWith(
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'Advanced Camera Card [issue=media_unavailable]: Stream issue',
|
||||
);
|
||||
spy.mockRestore();
|
||||
@@ -416,7 +416,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
manager.trigger('media_unavailable', { targetID: 'cam1', reason: 'stalled' });
|
||||
|
||||
expect(spy).toBeCalledWith(
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
'Advanced Camera Card [issue=media_unavailable]: Triggered',
|
||||
);
|
||||
spy.mockRestore();
|
||||
@@ -429,7 +429,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
manager.trigger('media_unavailable', { targetID: 'cam1', reason: 'stalled' });
|
||||
|
||||
expect(spy).not.toBeCalled();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
@@ -439,7 +439,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
manager.trigger('unknown' as never, {} as never);
|
||||
|
||||
expect(spy).not.toBeCalled();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
@@ -455,7 +455,7 @@ describe('IssueStateManager', () => {
|
||||
await manager.detectStatic(createHASS());
|
||||
await manager.detectStatic(createHASS());
|
||||
|
||||
expect(spy).toBeCalledTimes(1);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
@@ -466,7 +466,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
await manager.detectStatic(createHASS());
|
||||
|
||||
expect(spy).not.toBeCalled();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
@@ -482,7 +482,7 @@ describe('IssueStateManager', () => {
|
||||
const manager = createManager();
|
||||
await manager.detectStatic(createHASS());
|
||||
|
||||
expect(spy).not.toBeCalled();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
spy.mockRestore();
|
||||
});
|
||||
|
||||
@@ -507,7 +507,7 @@ describe('IssueStateManager', () => {
|
||||
// Re-activate with a different payload → log Second.
|
||||
await manager.detectStatic(createHASS());
|
||||
|
||||
expect(spy).toBeCalledTimes(2);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
expect(spy).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'Advanced Camera Card [issue=legacy_resource]: First',
|
||||
@@ -539,7 +539,7 @@ describe('IssueStateManager', () => {
|
||||
// Then it re-activates (e.g. new trigger arrives).
|
||||
manager.detectDynamic({ view: 'live' });
|
||||
|
||||
expect(spy).toBeCalledTimes(2);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
spy.mockRestore();
|
||||
});
|
||||
});
|
||||
@@ -550,9 +550,9 @@ describe('IssueStateManager', () => {
|
||||
manager.reset('media_unavailable');
|
||||
|
||||
assert(mockMediaLoad.reset);
|
||||
expect(mockMediaLoad.reset).toBeCalled();
|
||||
expect(mockMediaLoad.reset).toHaveBeenCalled();
|
||||
assert(mockConfigUpgrade.reset);
|
||||
expect(mockConfigUpgrade.reset).not.toBeCalled();
|
||||
expect(mockConfigUpgrade.reset).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reset all issues when no key is given', () => {
|
||||
@@ -562,9 +562,9 @@ describe('IssueStateManager', () => {
|
||||
assert(mockConfigUpgrade.reset);
|
||||
assert(mockLegacyResource.reset);
|
||||
assert(mockMediaLoad.reset);
|
||||
expect(mockConfigUpgrade.reset).toBeCalled();
|
||||
expect(mockLegacyResource.reset).toBeCalled();
|
||||
expect(mockMediaLoad.reset).toBeCalled();
|
||||
expect(mockConfigUpgrade.reset).toHaveBeenCalled();
|
||||
expect(mockLegacyResource.reset).toHaveBeenCalled();
|
||||
expect(mockMediaLoad.reset).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should do nothing for unknown key', () => {
|
||||
@@ -572,7 +572,7 @@ describe('IssueStateManager', () => {
|
||||
manager.reset('unknown' as never);
|
||||
|
||||
assert(mockMediaLoad.reset);
|
||||
expect(mockMediaLoad.reset).not.toBeCalled();
|
||||
expect(mockMediaLoad.reset).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -584,9 +584,9 @@ describe('IssueStateManager', () => {
|
||||
assert(mockConfigUpgrade.suspend);
|
||||
assert(mockLegacyResource.suspend);
|
||||
assert(mockMediaLoad.suspend);
|
||||
expect(mockConfigUpgrade.suspend).toBeCalled();
|
||||
expect(mockLegacyResource.suspend).toBeCalled();
|
||||
expect(mockMediaLoad.suspend).toBeCalled();
|
||||
expect(mockConfigUpgrade.suspend).toHaveBeenCalled();
|
||||
expect(mockLegacyResource.suspend).toHaveBeenCalled();
|
||||
expect(mockMediaLoad.suspend).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -598,16 +598,16 @@ describe('IssueStateManager', () => {
|
||||
assert(mockConfigUpgrade.reset);
|
||||
assert(mockLegacyResource.reset);
|
||||
assert(mockMediaLoad.reset);
|
||||
expect(mockConfigUpgrade.reset).toBeCalled();
|
||||
expect(mockLegacyResource.reset).toBeCalled();
|
||||
expect(mockMediaLoad.reset).toBeCalled();
|
||||
expect(mockConfigUpgrade.reset).toHaveBeenCalled();
|
||||
expect(mockLegacyResource.reset).toHaveBeenCalled();
|
||||
expect(mockMediaLoad.reset).toHaveBeenCalled();
|
||||
|
||||
assert(mockConfigUpgrade.destroy);
|
||||
assert(mockLegacyResource.destroy);
|
||||
assert(mockMediaLoad.destroy);
|
||||
expect(mockConfigUpgrade.destroy).toBeCalled();
|
||||
expect(mockLegacyResource.destroy).toBeCalled();
|
||||
expect(mockMediaLoad.destroy).toBeCalled();
|
||||
expect(mockConfigUpgrade.destroy).toHaveBeenCalled();
|
||||
expect(mockLegacyResource.destroy).toHaveBeenCalled();
|
||||
expect(mockMediaLoad.destroy).toHaveBeenCalled();
|
||||
|
||||
expect(manager.getIssuePresence().size).toBe(0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user