eslint-vitest-rule-tester
Version:
ESLint rule tester with Vitest
178 lines (170 loc) • 7.5 kB
text/typescript
import { Linter } from 'eslint';
type Awaitable<T> = Promise<T> | T;
interface ValidTestCaseBase<RuleOptions = any, MessageId extends string = string> extends CompatConfigOptions, RuleTesterBehaviorOptions {
name?: string;
description?: string;
code: string;
options?: RuleOptions;
filename?: string;
only?: boolean;
skip?: boolean;
before?: (this: NormalizedTestCase<RuleOptions, MessageId>, configs: Linter.Config[]) => Awaitable<void>;
after?: (this: NormalizedTestCase<RuleOptions, MessageId>, result: Linter.FixReport) => Awaitable<void>;
/**
* @deprecated Use `after` instead
*/
onResult?: (result: Linter.FixReport) => void;
}
type TestCaseError<MessageId extends string = string> = Partial<Linter.LintMessage> & {
/**
* Data for interpolate the error message
*/
data?: Record<string, any>;
/**
* Alias to `nodeType`
*/
type?: string;
messageId?: MessageId;
};
interface InvalidTestCaseBase<RuleOptions = any, MessageId extends string = string> extends ValidTestCaseBase<RuleOptions, MessageId> {
/**
* Expected errors.
* If a number is provided, it asserts that the number of errors is equal to the number provided.
* If an array of strings is provided, it asserts that the error messageIds are equal to the array provided.
* If an array of objects is provided, it asserts that the errors are partially equal to the objects provided.
*/
errors?: number | (MessageId | TestCaseError<MessageId>)[] | ((errors: Linter.LintMessage[]) => Awaitable<void>);
/**
* Assert if output is expected.
* Pass `null` to assert that the output is the same as the input.
*/
output?: string | null | ((output: string, input: string) => Awaitable<void>);
}
interface NormalizedTestCase<RuleOptions = any, MessageId extends string = string> extends InvalidTestCaseBase<RuleOptions, MessageId> {
type: 'valid' | 'invalid';
code: string;
}
type InvalidTestCase<RuleOptions = any, MessageId extends string = string> = InvalidTestCaseBase<RuleOptions, MessageId> | string;
type ValidTestCase<RuleOptions = any> = ValidTestCaseBase<RuleOptions> | string;
type TestCase<RuleOptions = any, MessageId extends string = string> = ValidTestCase<RuleOptions> | InvalidTestCase<RuleOptions, MessageId>;
interface TestExecutionResult extends Linter.FixReport {
/**
* If the rule fixes in multiple steps, each step will be present here
*/
steps: Linter.FixReport[];
}
interface CompatConfigOptions {
parserOptions?: Linter.ParserOptions;
parser?: Linter.Parser;
languageOptions?: Linter.Config['languageOptions'];
linterOptions?: Linter.Config['linterOptions'];
settings?: Linter.Config['settings'];
processor?: Linter.Config['processor'];
files?: Linter.Config['files'];
}
type RuleModule = any;
interface RuleTester<RuleOptions = any, MessageId extends string = string> {
/**
* Run a single test case
*/
each: (arg: TestCase<RuleOptions, MessageId>) => Promise<{
testcase: NormalizedTestCase<RuleOptions, MessageId>;
result: TestExecutionResult;
}>;
/**
* Run a single valid test case
*/
valid: (arg: ValidTestCase<RuleOptions>) => Promise<{
testcase: NormalizedTestCase<RuleOptions, MessageId>;
result: TestExecutionResult;
}>;
/**
* Run a single invalid test case
*/
invalid: (arg: InvalidTestCase<RuleOptions, MessageId>) => Promise<{
testcase: NormalizedTestCase<RuleOptions, MessageId>;
result: TestExecutionResult;
}>;
/**
* ESLint's RuleTester style test runner, that runs multiple test cases
*/
run: (options: TestCasesOptions<RuleOptions, MessageId>) => Promise<void>;
}
interface RuleTesterBehaviorOptions {
/**
* The number of times to recursively apply the rule
* @default 10
*/
recursive?: number | false;
/**
* Run verification after applying the fix
* @default true
*/
verifyAfterFix?: boolean;
/**
* Verify that fix allways changes the code
* @default true
*/
verifyFixChanges?: boolean;
}
interface DefaultFilenames {
js: string;
jsx: string;
ts: string;
tsx: string;
}
interface RuleTesterInitOptions extends CompatConfigOptions, RuleTesterBehaviorOptions {
/**
* The rule to test
*/
rule?: RuleModule;
/**
* The name of the rule to test
*/
name?: string;
/**
* Additional flat configs to be merged with the rule config
*/
configs?: Linter.Config | Linter.Config[];
/**
* The default filenames to use for type-aware tests.
* @default { js: 'file.js', jsx: 'file.jsx', ts: 'file.ts', tsx: 'file.tsx' }
*/
defaultFilenames?: Partial<DefaultFilenames>;
}
interface TestCasesOptions<RuleOptions = any, MessageId extends string = string> {
valid?: (ValidTestCase<RuleOptions> | string)[];
invalid?: (InvalidTestCase<RuleOptions, MessageId> | string)[];
/**
* Callback to be called after each test case
*/
onResult?: (_case: NormalizedTestCase<RuleOptions, MessageId>, result: Linter.FixReport) => void | Promise<void>;
}
declare function pickFlatConfigFromOptions(options: CompatConfigOptions): Linter.Config | undefined;
declare function createRuleTester<RuleOptions = any, MessageId extends string = string>(options: RuleTesterInitOptions): RuleTester<RuleOptions, MessageId>;
/**
* Shortcut to run test cases for a rule
*/
declare function run<RuleOptions = any, MessageId extends string = string>(options: TestCasesOptions<RuleOptions, MessageId> & RuleTesterInitOptions): Promise<void>;
/**
* Shortcut to run test cases for a rule in classic style
*/
declare function runClassic<RuleOptions = any, MessageId extends string = string>(ruleName: string, rule: RuleModule, cases: TestCasesOptions<RuleOptions, MessageId>, options?: RuleTesterInitOptions): Promise<void>;
/**
* Remove common leading whitespace from a template string.
* Will also remove empty lines at the beginning and end.
* @category string
* @example
* ```ts
* const str = unindent`
* if (a) {
* b()
* }
* `
*/
declare function unindent(str: TemplateStringsArray | string): string;
declare function normalizeTestCase<RuleOptions = any, MessageId extends string = string>(c: TestCase<RuleOptions, MessageId>, languageOptions: Linter.Config['languageOptions'], defaultFilenames: DefaultFilenames, type?: 'valid' | 'invalid'): NormalizedTestCase<RuleOptions, MessageId>;
declare function normalizeCaseError<MessageId extends string = string>(error: TestCaseError<MessageId> | MessageId, rule?: RuleModule): Partial<Linter.LintMessage>;
declare function isUsingTypeScriptParser(languageOptions: Linter.Config['languageOptions']): boolean;
declare function isUsingTypeScriptTypings(languageOptions: Linter.Config['languageOptions']): boolean;
export { unindent as $, type Awaitable, type CompatConfigOptions, type DefaultFilenames, type InvalidTestCase, type InvalidTestCaseBase, type NormalizedTestCase, type RuleModule, type RuleTester, type RuleTesterBehaviorOptions, type RuleTesterInitOptions, type TestCase, type TestCaseError, type TestCasesOptions, type TestExecutionResult, type ValidTestCase, type ValidTestCaseBase, createRuleTester, isUsingTypeScriptParser, isUsingTypeScriptTypings, normalizeCaseError, normalizeTestCase, pickFlatConfigFromOptions, run, runClassic, unindent };