mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-09 00:19:13 +08:00
update unit tests
This commit is contained in:
parent
8fa4e876ef
commit
cce0035ce0
@ -1,16 +1,15 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { Channel, type ChannelTransport } from 'storybook/internal/channels';
|
||||
import {
|
||||
TESTING_MODULE_CANCEL_TEST_RUN_REQUEST,
|
||||
TESTING_MODULE_PROGRESS_REPORT,
|
||||
TESTING_MODULE_RUN_REQUEST,
|
||||
} from 'storybook/internal/core-events';
|
||||
|
||||
// eslint-disable-next-line depend/ban-dependencies
|
||||
import { execaNode } from 'execa';
|
||||
|
||||
import type { MockUniversalStore } from '../../../../core/src/shared/universal-store/mock';
|
||||
import { storeOptions } from '../constants';
|
||||
import { log } from '../logger';
|
||||
import type { StoreEvent } from '../types';
|
||||
import type { StoreState } from '../types';
|
||||
import { killTestRunner, runTestRunner } from './boot-test-runner';
|
||||
|
||||
let stdout: (chunk: any) => void;
|
||||
@ -43,6 +42,26 @@ vi.mock('../logger', () => ({
|
||||
log: vi.fn(),
|
||||
}));
|
||||
|
||||
let statusStoreSubscriber = vi.hoisted(() => undefined);
|
||||
let testProviderStoreSubscriber = vi.hoisted(() => undefined);
|
||||
|
||||
vi.mock('storybook/internal/core-server', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('storybook/internal/core-server')>();
|
||||
return {
|
||||
...actual,
|
||||
internal_universalStatusStore: {
|
||||
subscribe: (listener: any) => {
|
||||
statusStoreSubscriber = listener;
|
||||
},
|
||||
},
|
||||
internal_universalTestProviderStore: {
|
||||
subscribe: (listener: any) => {
|
||||
testProviderStoreSubscriber = listener;
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
killTestRunner();
|
||||
@ -56,8 +75,17 @@ const transport = { setHandler: vi.fn(), send: vi.fn() } satisfies ChannelTransp
|
||||
const mockChannel = new Channel({ transport });
|
||||
|
||||
describe('bootTestRunner', () => {
|
||||
let mockStore: MockUniversalStore<any, any>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const { experimental_MockUniversalStore: MockUniversalStore } = await import(
|
||||
'storybook/internal/core-server'
|
||||
);
|
||||
mockStore = new MockUniversalStore<StoreState, StoreEvent>(storeOptions);
|
||||
});
|
||||
|
||||
it('should execute vitest.js', async () => {
|
||||
runTestRunner(mockChannel);
|
||||
runTestRunner(mockChannel, mockStore);
|
||||
expect(execaNode).toHaveBeenCalledWith(expect.stringMatching(/vitest\.mjs$/), {
|
||||
env: {
|
||||
NODE_ENV: 'test',
|
||||
@ -69,7 +97,7 @@ describe('bootTestRunner', () => {
|
||||
});
|
||||
|
||||
it('should log stdout and stderr', async () => {
|
||||
runTestRunner(mockChannel);
|
||||
runTestRunner(mockChannel, mockStore);
|
||||
stdout('foo');
|
||||
stderr('bar');
|
||||
expect(log).toHaveBeenCalledWith('foo');
|
||||
@ -78,7 +106,7 @@ describe('bootTestRunner', () => {
|
||||
|
||||
it('should wait for vitest to be ready', async () => {
|
||||
let ready;
|
||||
const promise = runTestRunner(mockChannel).then(() => {
|
||||
const promise = runTestRunner(mockChannel, mockStore).then(() => {
|
||||
ready = true;
|
||||
});
|
||||
expect(ready).toBeUndefined();
|
||||
@ -88,35 +116,42 @@ describe('bootTestRunner', () => {
|
||||
});
|
||||
|
||||
it('should abort if vitest doesn’t become ready in time', async () => {
|
||||
const promise = runTestRunner(mockChannel);
|
||||
const promise = runTestRunner(mockChannel, mockStore);
|
||||
vi.advanceTimersByTime(30001);
|
||||
await expect(promise).rejects.toThrow();
|
||||
});
|
||||
|
||||
it('should forward channel events', async () => {
|
||||
runTestRunner(mockChannel);
|
||||
it('should forward universal store events', async () => {
|
||||
runTestRunner(mockChannel, mockStore);
|
||||
message({ type: 'ready' });
|
||||
|
||||
message({ type: TESTING_MODULE_PROGRESS_REPORT, args: ['foo'] });
|
||||
expect(mockChannel.last(TESTING_MODULE_PROGRESS_REPORT)).toEqual(['foo']);
|
||||
|
||||
mockChannel.emit(TESTING_MODULE_RUN_REQUEST, 'foo');
|
||||
mockStore.send({ type: 'TRIGGER_RUN', payload: { triggeredBy: 'global', storyIds: ['foo'] } });
|
||||
expect(child.send).toHaveBeenCalledWith({
|
||||
args: ['foo'],
|
||||
args: [
|
||||
{
|
||||
event: {
|
||||
payload: { storyIds: ['foo'], triggeredBy: 'global' },
|
||||
type: 'TRIGGER_RUN',
|
||||
},
|
||||
eventInfo: {
|
||||
actor: {
|
||||
environment: 'MOCK',
|
||||
id: expect.any(String),
|
||||
type: 'LEADER',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
from: 'server',
|
||||
type: TESTING_MODULE_RUN_REQUEST,
|
||||
type: 'UNIVERSAL_STORE:storybook/test',
|
||||
});
|
||||
|
||||
mockChannel.emit(TESTING_MODULE_CANCEL_TEST_RUN_REQUEST, 'qux');
|
||||
expect(child.send).toHaveBeenCalledWith({
|
||||
args: ['qux'],
|
||||
from: 'server',
|
||||
type: TESTING_MODULE_CANCEL_TEST_RUN_REQUEST,
|
||||
});
|
||||
message({ type: 'some-event', args: ['foo'] });
|
||||
expect(mockChannel.last('some-event')).toEqual(['foo']);
|
||||
});
|
||||
|
||||
it('should resend init event', async () => {
|
||||
runTestRunner(mockChannel, 'init', ['foo']);
|
||||
runTestRunner(mockChannel, mockStore, 'init', ['foo']);
|
||||
message({ type: 'ready' });
|
||||
expect(child.send).toHaveBeenCalledWith({
|
||||
args: ['foo'],
|
||||
|
@ -15,10 +15,10 @@ import type { EventInfo } from '../../../../core/src/shared/universal-store/type
|
||||
import {
|
||||
STATUS_STORE_CHANNEL_EVENT_NAME,
|
||||
STORE_CHANNEL_EVENT_NAME,
|
||||
type Store,
|
||||
TEST_PROVIDER_STORE_CHANNEL_EVENT_NAME,
|
||||
} from '../constants';
|
||||
import { log } from '../logger';
|
||||
import type { Store } from '../types';
|
||||
|
||||
const MAX_START_TIME = 30000;
|
||||
|
||||
|
@ -3,13 +3,17 @@ import { createVitest as actualCreateVitest } from 'vitest/node';
|
||||
|
||||
import { Channel, type ChannelTransport } from 'storybook/internal/channels';
|
||||
import { experimental_MockUniversalStore } from 'storybook/internal/core-server';
|
||||
import type { StoryIndex } from 'storybook/internal/types';
|
||||
import type {
|
||||
StatusStoreByTypeId,
|
||||
StoryIndex,
|
||||
TestProviderStoreById,
|
||||
} from 'storybook/internal/types';
|
||||
|
||||
import path from 'pathe';
|
||||
|
||||
import { storeOptions } from '../constants';
|
||||
import { STATUS_TYPE_ID_A11Y, STATUS_TYPE_ID_COMPONENT_TEST, storeOptions } from '../constants';
|
||||
import type { StoreEvent, StoreState } from '../types';
|
||||
import { TestManager } from './test-manager';
|
||||
import { TestManager, type TestManagerOptions } from './test-manager';
|
||||
|
||||
const setTestNamePattern = vi.hoisted(() => vi.fn());
|
||||
const vitest = vi.hoisted(() => ({
|
||||
@ -17,9 +21,9 @@ const vitest = vi.hoisted(() => ({
|
||||
init: vi.fn(),
|
||||
close: vi.fn(),
|
||||
onCancel: vi.fn(),
|
||||
runFiles: vi.fn(),
|
||||
runTestSpecifications: vi.fn(),
|
||||
cancelCurrentRun: vi.fn(),
|
||||
globTestSpecs: vi.fn(),
|
||||
globTestSpecifications: vi.fn(),
|
||||
getModuleProjects: vi.fn(() => []),
|
||||
setGlobalTestNamePattern: setTestNamePattern,
|
||||
vite: {
|
||||
@ -32,6 +36,9 @@ const vitest = vi.hoisted(() => ({
|
||||
invalidateModule: vi.fn(),
|
||||
},
|
||||
},
|
||||
config: {
|
||||
coverage: { enabled: false },
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('vitest/node', async (importOriginal) => ({
|
||||
@ -42,6 +49,38 @@ const createVitest = vi.mocked(actualCreateVitest);
|
||||
|
||||
const transport = { setHandler: vi.fn(), send: vi.fn() } satisfies ChannelTransport;
|
||||
const mockChannel = new Channel({ transport });
|
||||
const mockStore = new experimental_MockUniversalStore<StoreState, StoreEvent>(
|
||||
{
|
||||
...storeOptions,
|
||||
initialState: { ...storeOptions.initialState, indexUrl: 'http://localhost:6006/index.json' },
|
||||
},
|
||||
vi
|
||||
);
|
||||
const mockComponentTestStatusStore: StatusStoreByTypeId = {
|
||||
set: vi.fn(),
|
||||
getAll: vi.fn(),
|
||||
onAllStatusChange: vi.fn(),
|
||||
onSelect: vi.fn(),
|
||||
unset: vi.fn(),
|
||||
typeId: STATUS_TYPE_ID_COMPONENT_TEST,
|
||||
};
|
||||
const mockA11yStatusStore: StatusStoreByTypeId = {
|
||||
set: vi.fn(),
|
||||
getAll: vi.fn(),
|
||||
onAllStatusChange: vi.fn(),
|
||||
onSelect: vi.fn(),
|
||||
unset: vi.fn(),
|
||||
typeId: STATUS_TYPE_ID_A11Y,
|
||||
};
|
||||
const mockTestProviderStore: TestProviderStoreById = {
|
||||
getState: vi.fn(),
|
||||
setState: vi.fn(),
|
||||
settingsChanged: vi.fn(),
|
||||
onRunAll: vi.fn(),
|
||||
onClearAll: vi.fn(),
|
||||
runWithState: vi.fn((callback) => callback()),
|
||||
testProviderId: 'test-provider-id',
|
||||
};
|
||||
|
||||
const tests = [
|
||||
{
|
||||
@ -81,7 +120,11 @@ global.fetch = vi.fn().mockResolvedValue({
|
||||
),
|
||||
});
|
||||
|
||||
const options: ConstructorParameters<typeof TestManager>[2] = {
|
||||
const options: TestManagerOptions = {
|
||||
store: mockStore,
|
||||
componentTestStatusStore: mockComponentTestStatusStore,
|
||||
a11yStatusStore: mockA11yStatusStore,
|
||||
testProviderStore: mockTestProviderStore,
|
||||
onError: (message, error) => {
|
||||
throw error;
|
||||
},
|
||||
@ -90,160 +133,94 @@ const options: ConstructorParameters<typeof TestManager>[2] = {
|
||||
|
||||
describe('TestManager', () => {
|
||||
it('should create a vitest instance', async () => {
|
||||
new TestManager(mockChannel, new experimental_MockUniversalStore(storeOptions, vi), options);
|
||||
new TestManager(options);
|
||||
await vi.waitFor(() => {
|
||||
expect(createVitest).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should call onReady callback', async () => {
|
||||
new TestManager(mockChannel, new experimental_MockUniversalStore(storeOptions, vi), options);
|
||||
new TestManager(options);
|
||||
await vi.waitFor(() => {
|
||||
expect(options.onReady).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('TestManager.start should start vitest and resolve when ready', async () => {
|
||||
const testManager = await TestManager.start(
|
||||
mockChannel,
|
||||
new experimental_MockUniversalStore(storeOptions, vi),
|
||||
options
|
||||
);
|
||||
const testManager = await TestManager.start(options);
|
||||
|
||||
expect(testManager).toBeInstanceOf(TestManager);
|
||||
expect(createVitest).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle watch mode request', async () => {
|
||||
const testManager = await TestManager.start(
|
||||
mockChannel,
|
||||
new experimental_MockUniversalStore(storeOptions, vi),
|
||||
options
|
||||
);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
|
||||
await testManager.handleToggleWatchingEvent(true);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1); // shouldn't restart vitest
|
||||
});
|
||||
|
||||
it('should handle run request', async () => {
|
||||
vitest.globTestSpecs.mockImplementation(() => tests);
|
||||
const testManager = await TestManager.start(
|
||||
mockChannel,
|
||||
new experimental_MockUniversalStore(storeOptions, vi),
|
||||
options
|
||||
);
|
||||
vitest.globTestSpecifications.mockImplementation(() => tests);
|
||||
const testManager = await TestManager.start(options);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
|
||||
await testManager.handleTriggerRunEvent({
|
||||
type: 'TRIGGER_RUN',
|
||||
payload: {
|
||||
indexUrl: 'http://localhost:6006/index.json',
|
||||
triggeredBy: 'global',
|
||||
},
|
||||
});
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
expect(vitest.runFiles).toHaveBeenCalledWith(tests, true);
|
||||
expect(vitest.runTestSpecifications).toHaveBeenCalledWith(tests, true);
|
||||
});
|
||||
|
||||
it('should filter tests', async () => {
|
||||
vitest.globTestSpecs.mockImplementation(() => tests);
|
||||
const testManager = await TestManager.start(
|
||||
mockChannel,
|
||||
new experimental_MockUniversalStore(storeOptions, vi),
|
||||
options
|
||||
);
|
||||
vitest.globTestSpecifications.mockImplementation(() => tests);
|
||||
const testManager = await TestManager.start(options);
|
||||
|
||||
await testManager.handleTriggerRunEvent({
|
||||
type: 'TRIGGER_RUN',
|
||||
payload: {
|
||||
indexUrl: 'http://localhost:6006/index.json',
|
||||
storyIds: [],
|
||||
},
|
||||
});
|
||||
expect(vitest.runFiles).toHaveBeenCalledWith([], true);
|
||||
|
||||
await testManager.handleTriggerRunEvent({
|
||||
type: 'TRIGGER_RUN',
|
||||
payload: {
|
||||
indexUrl: 'http://localhost:6006/index.json',
|
||||
storyIds: ['story--one'],
|
||||
triggeredBy: 'global',
|
||||
},
|
||||
});
|
||||
expect(setTestNamePattern).toHaveBeenCalledWith(/^One$/);
|
||||
expect(vitest.runFiles).toHaveBeenCalledWith(tests.slice(0, 1), true);
|
||||
expect(vitest.runTestSpecifications).toHaveBeenCalledWith(tests.slice(0, 1), true);
|
||||
});
|
||||
|
||||
it('should handle coverage toggling', async () => {
|
||||
const testManager = await TestManager.start(
|
||||
mockChannel,
|
||||
new experimental_MockUniversalStore(storeOptions, vi),
|
||||
options
|
||||
);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
createVitest.mockClear();
|
||||
|
||||
await testManager.handleConfigChange(
|
||||
{
|
||||
coverage: true,
|
||||
a11y: false,
|
||||
},
|
||||
{
|
||||
coverage: false,
|
||||
a11y: false,
|
||||
}
|
||||
);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
createVitest.mockClear();
|
||||
|
||||
await testManager.handleConfigChange(
|
||||
{
|
||||
coverage: false,
|
||||
a11y: false,
|
||||
},
|
||||
{
|
||||
coverage: true,
|
||||
a11y: false,
|
||||
}
|
||||
);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should temporarily disable coverage on focused tests', async () => {
|
||||
vitest.globTestSpecs.mockImplementation(() => tests);
|
||||
const mockStore = new experimental_MockUniversalStore<StoreState, StoreEvent>(storeOptions, vi);
|
||||
const testManager = await TestManager.start(mockChannel, mockStore, options);
|
||||
|
||||
it('should restart Vitest before a test run if coverage is enabled', async () => {
|
||||
const testManager = await TestManager.start(options);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
createVitest.mockClear();
|
||||
|
||||
mockStore.setState((s) => ({ ...s, config: { coverage: true, a11y: false } }));
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
await testManager.handleTriggerRunEvent({
|
||||
type: 'TRIGGER_RUN',
|
||||
payload: {
|
||||
triggeredBy: 'global',
|
||||
},
|
||||
});
|
||||
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
expect(createVitest).toHaveBeenCalledWith(
|
||||
'test',
|
||||
expect.objectContaining({
|
||||
coverage: expect.objectContaining({ enabled: true }),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should not restart with coverage enabled Vitest before a focused test run', async () => {
|
||||
const testManager = await TestManager.start(options);
|
||||
expect(createVitest).toHaveBeenCalledTimes(1);
|
||||
createVitest.mockClear();
|
||||
|
||||
mockStore.setState((s) => ({ ...s, config: { coverage: true, a11y: false } }));
|
||||
|
||||
await testManager.handleTriggerRunEvent({
|
||||
type: 'TRIGGER_RUN',
|
||||
payload: {
|
||||
indexUrl: 'http://localhost:6006/index.json',
|
||||
storyIds: ['button--primary', 'button--secondary'],
|
||||
storyIds: ['story--one'],
|
||||
triggeredBy: 'global',
|
||||
},
|
||||
});
|
||||
|
||||
// expect vitest to be restarted twice, without and with coverage
|
||||
expect(createVitest).toHaveBeenCalledTimes(2);
|
||||
expect(vitest.runFiles).toHaveBeenCalledWith([], true);
|
||||
createVitest.mockClear();
|
||||
|
||||
await testManager.handleTriggerRunEvent({
|
||||
type: 'TRIGGER_RUN',
|
||||
payload: {
|
||||
indexUrl: 'http://localhost:6006/index.json',
|
||||
},
|
||||
});
|
||||
// don't expect vitest to be restarted, as we're running all tests
|
||||
expect(createVitest).not.toHaveBeenCalled();
|
||||
expect(vitest.runFiles).toHaveBeenCalledWith(tests, true);
|
||||
});
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ import type { RunTrigger, StoreEvent, StoreState, TriggerRunEvent, VitestError }
|
||||
import { errorToErrorLike } from '../utils';
|
||||
import { VitestManager } from './vitest-manager';
|
||||
|
||||
type TestManagerOptions = {
|
||||
export type TestManagerOptions = {
|
||||
store: experimental_UniversalStore<StoreState, StoreEvent>;
|
||||
componentTestStatusStore: StatusStoreByTypeId;
|
||||
a11yStatusStore: StatusStoreByTypeId;
|
||||
@ -166,6 +166,20 @@ export class TestManager {
|
||||
this.throttledFlushTestCaseResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throttled function to process batched test case results.
|
||||
*
|
||||
* This function:
|
||||
*
|
||||
* 1. Takes all batched test case results and clears the batch
|
||||
* 2. Updates the store state with new test counts (component tests and a11y tests)
|
||||
* 3. Adjusts the totalTestCount if more tests were run than initially anticipated
|
||||
* 4. Creates status objects for component tests and updates the component test status store
|
||||
* 5. Creates status objects for a11y tests (if any) and updates the a11y status store
|
||||
*
|
||||
* The throttling (500ms) is necessary as the channel would otherwise get overwhelmed with events,
|
||||
* eventually causing the manager and dev server to loose connection.
|
||||
*/
|
||||
throttledFlushTestCaseResults = throttle(() => {
|
||||
const testCaseResultsToFlush = this.batchedTestCaseResults;
|
||||
this.batchedTestCaseResults = [];
|
||||
|
@ -75,7 +75,7 @@ describe('testProviderStore', () => {
|
||||
|
||||
describe('getTestProviderStoreById', () => {
|
||||
describe('getState', () => {
|
||||
it('should set initial provider state to pending', () => {
|
||||
it('should initially return pending state for new provider', () => {
|
||||
// Arrange - create empty test provider store
|
||||
const { getTestProviderStoreById, fullTestProviderStore } = createTestProviderStore({
|
||||
universalTestProviderStore: new MockUniversalStore<
|
||||
@ -89,12 +89,6 @@ describe('testProviderStore', () => {
|
||||
|
||||
// Assert - verify initial state is pending
|
||||
expect(store.getState()).toBe('test-provider-state:pending');
|
||||
|
||||
// Assert - verify provider was added to full state
|
||||
const fullState = fullTestProviderStore.getFullState();
|
||||
expect(fullState).toEqual({
|
||||
'provider-1': 'test-provider-state:pending',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return current state for existing provider', () => {
|
||||
@ -172,7 +166,9 @@ describe('testProviderStore', () => {
|
||||
store.runWithState(gatedSuccessCallback);
|
||||
|
||||
// Assert - verify running state
|
||||
expect(store.getState()).toBe('test-provider-state:running');
|
||||
await vi.waitFor(() => {
|
||||
expect(store.getState()).toBe('test-provider-state:running');
|
||||
});
|
||||
|
||||
// Act - complete execution
|
||||
runningGate!();
|
||||
@ -206,7 +202,9 @@ describe('testProviderStore', () => {
|
||||
store.runWithState(gatedErrorCallback);
|
||||
|
||||
// Assert - verify running state
|
||||
expect(store.getState()).toBe('test-provider-state:running');
|
||||
await vi.waitFor(() => {
|
||||
expect(store.getState()).toBe('test-provider-state:running');
|
||||
});
|
||||
|
||||
// Act - trigger error
|
||||
runningGate!();
|
||||
@ -253,7 +251,7 @@ describe('testProviderStore', () => {
|
||||
});
|
||||
|
||||
describe('onClearAll', () => {
|
||||
it('should register and call listener when clearAll is triggered', () => {
|
||||
it('should register and call listener when clearAll is triggered', async () => {
|
||||
// Arrange - create store and setup listener
|
||||
const mockUniversalStore = new MockUniversalStore<
|
||||
TestProviderStateByProviderId,
|
||||
@ -275,7 +273,9 @@ describe('testProviderStore', () => {
|
||||
fullTestProviderStore.clearAll();
|
||||
|
||||
// Assert - verify listener was called
|
||||
expect(listener).toHaveBeenCalledTimes(1);
|
||||
await vi.waitFor(() => {
|
||||
expect(listener).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
// Act - unsubscribe and trigger again
|
||||
unsubscribe();
|
||||
@ -287,7 +287,7 @@ describe('testProviderStore', () => {
|
||||
});
|
||||
|
||||
describe('settingsChanged', () => {
|
||||
it('should register and call listener when settingsChanged is triggered', () => {
|
||||
it('should register and call listener when settingsChanged is triggered', async () => {
|
||||
// Arrange - create store and setup listener
|
||||
const mockUniversalStore = new MockUniversalStore<
|
||||
TestProviderStateByProviderId,
|
||||
@ -309,7 +309,9 @@ describe('testProviderStore', () => {
|
||||
store.settingsChanged();
|
||||
|
||||
// Assert - verify listener was called
|
||||
expect(listener).toHaveBeenCalledTimes(1);
|
||||
await vi.waitFor(() => {
|
||||
expect(listener).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
// Act - unsubscribe and trigger again
|
||||
unsubscribe();
|
||||
|
Loading…
x
Reference in New Issue
Block a user