@storybook/addon-vitest
Version:
Storybook addon for testing components
185 lines (179 loc) • 6.39 kB
TypeScript
import { Vitest, TestSpecification, TestProject, WorkspaceProject, ResolvedCoverageOptions } from 'vitest/node';
import { ReportBase, Visitor, ReportNode } from 'istanbul-lib-report';
import { ThrottledFunction } from './function/throttle.js';
import { TestResult } from 'vitest/dist/node.js';
import { experimental_UniversalStore } from 'storybook/internal/core-server';
import { API_HashEntry, PreviewAnnotation, StoryId, Options, StatusStoreByTypeId, TestProviderStoreById } from 'storybook/internal/types';
import { Report } from 'storybook/preview-api';
interface VitestError extends Error {
VITEST_TEST_PATH?: string;
VITEST_TEST_NAME?: string;
stacks?: Array<{
line: number;
column: number;
file: string;
method: string;
}>;
}
type ErrorLike = {
message: string;
name?: string;
stack?: string;
cause?: ErrorLike;
};
type RunTrigger = 'run-all' | 'global' | 'watch' | Extract<API_HashEntry['type'], string>;
type StoreState = {
config: {
coverage: boolean;
a11y: boolean;
};
watching: boolean;
cancelling: boolean;
indexUrl: string | undefined;
previewAnnotations: PreviewAnnotation[];
fatalError: {
message: string | undefined;
error: ErrorLike;
} | undefined;
currentRun: {
triggeredBy: RunTrigger | undefined;
config: StoreState['config'];
componentTestCount: {
success: number;
error: number;
};
a11yCount: {
success: number;
warning: number;
error: number;
};
totalTestCount: number | undefined;
storyIds: StoryId[] | undefined;
startedAt: number | undefined;
finishedAt: number | undefined;
unhandledErrors: VitestError[];
coverageSummary: {
status: 'positive' | 'warning' | 'negative' | 'unknown';
percentage: number;
} | undefined;
};
};
type TriggerRunEvent = {
type: 'TRIGGER_RUN';
payload: {
storyIds?: string[] | undefined;
triggeredBy: RunTrigger;
};
};
type CancelRunEvent = {
type: 'CANCEL_RUN';
};
type ToggleWatchingEvent = {
type: 'TOGGLE_WATCHING';
payload: {
to: boolean;
};
};
type FatalErrorEvent = {
type: 'FATAL_ERROR';
payload: {
message: string;
error: ErrorLike;
};
};
type TestRunCompletedEvent = {
type: 'TEST_RUN_COMPLETED';
payload: StoreState['currentRun'];
};
type StoreEvent = TriggerRunEvent | CancelRunEvent | FatalErrorEvent | ToggleWatchingEvent | TestRunCompletedEvent;
declare class VitestManager {
private testManager;
vitest: Vitest | null;
vitestStartupCounter: number;
vitestRestartPromise: Promise<void> | null;
runningPromise: Promise<any> | null;
constructor(testManager: TestManager);
startVitest({ coverage }: {
coverage: boolean;
}): Promise<void>;
restartVitest({ coverage }: {
coverage: boolean;
}): Promise<void>;
private resetGlobalTestNamePattern;
private updateLastChanged;
private fetchStories;
private filterTestSpecifications;
runTests(runPayload: TriggerRunEvent['payload']): Promise<void>;
cancelCurrentRun(): Promise<void>;
getStorybookTestSpecifications(): Promise<TestSpecification[]>;
runAffectedTestsAfterChange(changedFilePath: string, event: 'change' | 'add'): Promise<void>;
private getTestDependencies;
registerVitestConfigListener(): Promise<void>;
setupWatchers(): Promise<void>;
isStorybookProject(project: TestProject | WorkspaceProject): boolean;
}
type TestManagerOptions = {
storybookOptions: Options;
store: experimental_UniversalStore<StoreState, StoreEvent>;
componentTestStatusStore: StatusStoreByTypeId;
a11yStatusStore: StatusStoreByTypeId;
testProviderStore: TestProviderStoreById;
onError?: (message: string, error: Error) => void;
onReady?: () => void;
};
declare class TestManager {
store: TestManagerOptions['store'];
vitestManager: VitestManager;
private componentTestStatusStore;
private a11yStatusStore;
private testProviderStore;
private onReady?;
storybookOptions: Options;
private batchedTestCaseResults;
constructor(options: TestManagerOptions);
handleTriggerRunEvent(event: TriggerRunEvent): Promise<void>;
handleCancelEvent(): Promise<void>;
runTestsWithState({ storyIds, triggeredBy, callback, }: {
storyIds?: string[];
triggeredBy: RunTrigger;
callback: () => Promise<void>;
}): Promise<void>;
onTestModuleCollected(collectedTestCount: number): void;
onTestCaseResult(result: {
storyId?: string;
testResult: TestResult;
reports?: Report[];
}): void;
/**
* 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 lose connection.
*/
throttledFlushTestCaseResults: ThrottledFunction<() => void>;
onTestRunEnd(endResult: {
totalTestCount: number;
unhandledErrors: VitestError[];
}): void;
onCoverageCollected(coverageSummary: StoreState['currentRun']['coverageSummary']): void;
reportFatalError(message: string, error: Error | any): Promise<void>;
static start(options: TestManagerOptions): Promise<TestManager>;
}
type StorybookCoverageReporterOptions = {
testManager: TestManager;
coverageOptions: ResolvedCoverageOptions<'v8'> | undefined;
};
declare class StorybookCoverageReporter extends ReportBase implements Partial<Visitor> {
#private;
constructor(opts: StorybookCoverageReporterOptions);
onSummary(node: ReportNode): void;
}
export { StorybookCoverageReporterOptions, StorybookCoverageReporter as default };