import type { CompilerOptions } from "../core/options.js"; import type { Program } from "../core/program.js"; import type { CompilerHost, Diagnostic, Entity, Type } from "../core/types.js"; import { Typekit } from "../typekit/define-kit.js"; import { PositionedMarker } from "./fourslash.js"; import { GetMarkedEntities, TemplateWithMarkers } from "./marked-template.js"; /** Represent a mock file. Use `mockFile` function to construct */ export type MockFile = string | JsFile; export interface JsFile { readonly kind: "js"; readonly exports: Record; } export interface TestFileSystem { /** Raw files */ readonly fs: Map; /** Compiler host */ readonly compilerHost: CompilerHost; /** * Add a mock test file * @example * ```ts * fs.add("foo.tsp", "model Foo {}"); * fs.add("foo.js", mockFile.js({ Foo: { bar: 1 } })); * ``` */ add(path: string, content: MockFile): void; /** Prefer using {@link add} */ addTypeSpecFile(path: string, contents: string): void; /** Prefer using {@link add} */ addJsFile(path: string, contents: Record): void; addRealTypeSpecFile(path: string, realPath: string): Promise; addRealJsFile(path: string, realPath: string): Promise; addRealFolder(path: string, realPath: string): Promise; addTypeSpecLibrary(testLibrary: TypeSpecTestLibrary): Promise; } export type TestCompileResult> = T & { /** The program created in this test compilation. */ readonly program: Program; /** The typekit for this compilation. */ readonly $: Typekit; /** File system */ readonly fs: TestFileSystem; /** Position of all markers */ readonly pos: Record; } & Record; export interface TestCompileOptions { /** Optional compiler options */ readonly compilerOptions?: CompilerOptions; } interface Testable { /** * Compile the given code and validate no diagnostics(error or warnings) are present. * Use {@link compileAndDiagnose} to get the compiler result and manage diagnostics yourself. * * @param code Can be the content of the `main.tsp` file or a record of files(MUST contains a main.tsp). * @param options Optional test options. * @returns {@link TestCompileResult} with the program and collected entities. * * @example * ```ts * const result = await tester.compile(t.code`model ${t.model("Foo")} { bar: string }`); * // result.program is the program created * // result.Foo is the model Foo created * ``` */ compile | Record>>(code: T, options?: TestCompileOptions): Promise>>; /** * Compile the given code and return the list of diagnostics emitted. * @param code Can be the content of the `main.tsp` file or a record of files(MUST contains a main.tsp). * @param options Optional test options. * @returns List of diagnostics emitted. * * @example * ```ts * const diagnostics = await tester.diagnose("model Foo {}"); * expectDiagnostics(diagnostics, { * code: "no-foo", * message: "Do not use Foo as a model name", * }); * ``` */ diagnose(main: string, options?: TestCompileOptions): Promise; /** * Compile the given code and return the collected entities and diagnostics. * * @param code Can be the content of the `main.tsp` file or a record of files(MUST contains a main.tsp). * @param options Optional test options. * @returns {@link TestCompileResult} with the program and collected entities with the list of diagnostics emitted. * * @example * ```ts * const [result, diagnostics] = await tester.compileAndDiagnose(t.code`model ${t.model("Foo")} { bar: string }`); * // result.program is the program created * // result.Foo is the model Foo created * ``` */ compileAndDiagnose | Record>>(code: T, options?: TestCompileOptions): Promise<[TestCompileResult>, readonly Diagnostic[]]>; } export interface TesterBuilder { /** Extend with the given list of files */ files(files: Record): T; /** Auto import all libraries defined in this tester. */ importLibraries(): T; /** Import the given paths */ import(...imports: string[]): T; /** Add using statement for the given namespaces. */ using(...names: string[]): T; /** Wrap the code of the `main.tsp` file */ wrap(fn: (x: string) => string): T; } export interface Tester extends Testable, TesterBuilder { /** * Create an emitter tester * @param options - Options to pass to the emitter */ emit(emitter: string, options?: Record): EmitterTester; /** Create an instance of the tester */ createInstance(): Promise; } export interface TestEmitterCompileResult { /** The program created in this test compilation. */ readonly program: Program; /** Files written to the emitter output dir. */ readonly outputs: Record; } export interface OutputTestable { compile(code: string | Record, options?: TestCompileOptions): Promise; compileAndDiagnose(code: string | Record, options?: TestCompileOptions): Promise<[Result, readonly Diagnostic[]]>; diagnose(code: string | Record, options?: TestCompileOptions): Promise; } /** Alternate version of the tester which runs the configured emitter */ export interface EmitterTester extends OutputTestable, TesterBuilder> { /** * Pipe the output of the emitter into a different structure * * @example * ```ts * const MyTester = Tester.emit("my-emitter").pipe((result) => { * return JSON.parse(result.outputs["output.json"]); * }); * * const result = await MyTester.compile("model Foo { bar: string }"); * // result is the parsed JSON from the output.json file * ``` */ pipe(cb: (result: Result) => O): EmitterTester; /** Create a mutable instance of the tester */ createInstance(): Promise>; } export interface TesterInstanceBase { /** Program created. Only available after calling `compile`, `diagnose` or `compileAndDiagnose` */ get program(): Program; /** The typekit for this compilation. Only available after calling `compile`, `diagnose` or `compileAndDiagnose` */ get $(): Typekit; /** File system used */ readonly fs: TestFileSystem; } /** Instance of a tester. */ export interface TesterInstance extends TesterInstanceBase, Testable { } /** Instance of an emitter tester */ export interface EmitterTesterInstance extends TesterInstanceBase, OutputTestable { } export interface PositionedMarkerInFile extends PositionedMarker { /** The file where the marker is located */ readonly filename: string; } export interface TestHost extends Pick { program: Program; libraries: TypeSpecTestLibrary[]; testTypes: Record; compile(main: string, options?: CompilerOptions): Promise>; diagnose(main: string, options?: CompilerOptions): Promise; compileAndDiagnose(main: string, options?: CompilerOptions): Promise<[Record, readonly Diagnostic[]]>; } export interface TestFiles { realDir: string; pattern: string; virtualPath: string; } export interface TypeSpecTestLibraryInit { name: string; packageRoot: string; /** * Folder @default "lib" */ typespecFileFolder?: string; /** * JS files folder. @default "dist/src" */ jsFileFolder?: string; } export interface TypeSpecTestLibrary { name: string; packageRoot: string; files: TestFiles[]; } export interface TestHostConfig { libraries?: TypeSpecTestLibrary[]; } export declare class TestHostError extends Error { code: "ENOENT" | "ERR_MODULE_NOT_FOUND"; constructor(message: string, code: "ENOENT" | "ERR_MODULE_NOT_FOUND"); } export interface BasicTestRunner { readonly program: Program; readonly fs: Map; /** * Position to offset the automatically added code. */ readonly autoCodeOffset: number; /** * Compile the given code and assert no diagnostics are present. */ compile(code: string, options?: CompilerOptions): Promise>; /** * Compile the code and return the list of diagnostics. */ diagnose(code: string, options?: CompilerOptions): Promise; /** * Compile the code and return the test types as well as the list of diagnostics. */ compileAndDiagnose(code: string, options?: CompilerOptions): Promise<[Record, readonly Diagnostic[]]>; } export {}; //# sourceMappingURL=types.d.ts.map