This page describes how to write tests for the TypeScript compiler, including compiler baseline tests, fourslash language service tests, and tsserver unit tests. For background on the test runner architecture and how to run tests, see 12.2 For information about the baseline acceptance workflow, see 12.3
The TypeScript repository uses several distinct test categories, each stored under tests/cases/ and exercising different layers of the compiler and tooling stack.
| Category | Source Path | What It Tests |
|---|---|---|
| Compiler | tests/cases/compiler/ | Type checking, emit, diagnostics |
| Conformance | tests/cases/conformance/ | Spec-level language behavior |
| Fourslash | tests/cases/fourslash/ | Language service features (completions, go-to-definition, etc.) |
| Unit | tests/cases/unittests/ | Internal compiler components |
| tsserver | tests/cases/unittests/tsserver/ | tsserver project management and protocol |
Test category → runner mapping
Sources: tests/cases/fourslash/fourslash.ts1-20 CONTRIBUTING.md1-30
Compiler tests verify the output of the TypeScript compiler against stored baseline files. Each test is a .ts (or .tsx) source file. The test runner compiles it and diffs the output against files in tests/baselines/reference/.
Place a new test file in tests/cases/compiler/. The file name becomes the test name and the baseline file prefix.
A test file can contain compiler option directives in a leading comment block:
// @target: ES6
// @strict: true
// @module: commonjs
These correspond directly to CompilerOptions fields. Any option accepted by the command-line parser can be set this way.
For a test named myTest.ts, the baseline system produces and tracks several files under tests/baselines/reference/:
| Baseline File | Contents |
|---|---|
myTest.js | Emitted JavaScript |
myTest.d.ts | Emitted declaration file |
myTest.errors.txt | Compiler diagnostics |
myTest.types | Inferred types for each expression |
myTest.symbols | Symbol information for each identifier |
The .types and .symbols files are especially useful for verifying type inference behavior without asserting on the emitted output.
Accepting new baselines: After adding or changing a test, run:
hereby baseline-accept
This copies files from tests/baselines/local/ (the actual output) to tests/baselines/reference/ (the committed reference).
To test interactions across files, use the // @filename: directive inside a single .ts test case file:
// @filename: a.ts
export const x = 1;
// @filename: b.ts
import { x } from './a';
Each // @filename: block creates a separate virtual source file during compilation.
Sources: tests/baselines/reference/api/typescript.d.ts1-50 CONTRIBUTING.md1-100
Fourslash is a domain-specific language for testing the LanguageService API. Tests reside in tests/cases/fourslash/ and are executed by the fourslash test runner. The API is documented in tests/cases/fourslash/fourslash.ts
Every line of virtual source code in a fourslash test is prefixed with four slashes (////). Normal comment lines (starting with //) are instructions to the test runner.
//// function greet(name: string): void {
//// console.log("Hello, " + name/*1*/);
//// }
A blank line (with no slashes at all) terminates the current virtual file.
Positions in the source are denoted with inline comments inside //// lines.
| Syntax | Meaning |
|---|---|
/**/ | Anonymous marker (single position) |
/*name*/ | Named marker |
/*[name*/ ... /*]name*/ | Named range (a span) |
//// const x/*start*/ = 42/*end*/;
Navigate to a marker with goTo.marker("name") and to a range with goTo.rangeStart("name").
File-level options appear before the first //// line:
// @filename: foo.ts
// @target: ES2020
Multiple virtual files can be created in one fourslash test by using several // @filename: blocks, each terminated by a blank non-//// line.
The test body calls into the global goTo, verify, and edit objects. Key methods:
goTo — cursor navigation
| Method | Action |
|---|---|
goTo.marker(name?) | Move to a named (or anonymous) marker |
goTo.file(name) | Switch to a named file |
goTo.rangeStart(name) | Move to the start of a named range |
verify — assertions
| Method | What it checks |
|---|---|
verify.completions({ marker, exact, includes, excludes }) | Completion items at a position |
verify.quickInfoAt(marker, expectedText) | Hover quick info text |
verify.goToDefinitionIs(name) | Go-to-definition target |
verify.findReferencesDefinitionDisplayPartsAtCaretAre(parts) | Symbol display parts |
verify.currentSignatureHelpArgumentNameIs(name) | Active parameter in signature help |
verify.numberOfErrorsInCurrentFile(n) | Error count |
verify.codeFix({ description, newFileContent }) | Code fix application |
verify.refactor({ name, actionName, newContent }) | Refactoring result |
edit — source mutations
| Method | Action |
|---|---|
edit.insert(text) | Insert text at the current caret |
edit.deleteAtCaret(n) | Delete n characters |
edit.paste(text) | Simulate a paste operation |
Fourslash execution flow
Sources: tests/cases/fourslash/fourslash.ts1-200 src/harness/harnessLanguageService.ts1-50
// @filename: index.ts
//// interface Foo { bar: number; baz: string; }
//// declare const f: Foo;
//// f./**/
// @filename: index.ts
//// const x/**/: string = 42;
The virtual environment for fourslash tests is provided by src/harness/harnessLanguageService.ts. It implements LanguageServiceHost using a virtual file system (vfs) and provides utilities for setting up multi-file scenarios. The test runner instantiates the appropriate host and calls createLanguageService from the compiler API.
Fourslash harness object model
Sources: src/harness/harnessLanguageService.ts1-100 tests/cases/fourslash/fourslash.ts1-200
tsserver tests verify the behavior of Session, ProjectService, ConfiguredProject, and InferredProject — the project management layer described in 5.2 They live in tests/cases/unittests/tsserver/ and are written as standard Mocha tests.
tsserver tests use mock objects rather than a real file system or process. The key utilities are:
| Utility | Purpose |
|---|---|
TestServerHost | Mock ServerHost with a virtual file system |
createSession() | Creates a Session against a TestServerHost |
createProjectService() | Creates a ProjectService for project management tests |
executeSessionRequest() | Sends a typed request to a Session |
A typical test:
TestServerHost with virtual files (paths and content).createSession() or createProjectService().openFiles, completionInfo).tsserver test object model
The executeSessionRequest helper sends a protocol.Request and returns the typed response. The CommandTypes enum (defined in src/server/protocol.ts) identifies message types.
Common request types used in tests:
| Command | Constant |
|---|---|
| Open a file | CommandTypes.Open |
| Request completions | CommandTypes.CompletionInfo |
| Request diagnostics | CommandTypes.SemanticDiagnosticsSync |
| Get definition | CommandTypes.Definition |
| Apply code fix | CommandTypes.GetCodeFixes |
Sources: src/server/editorServices.ts1-50 src/server/session.ts1-60 src/server/protocol.ts49-126
Unit tests in tests/cases/unittests/ cover compiler internals and do not fit into the compiler-baseline or fourslash patterns. They are standard Mocha/assert-style tests.
Common subjects for unit tests include:
tsbuildinfo state is correctly maintained.These tests import from the compiler directly and use ts.createSourceFile, ts.createProgram, or ts.createLanguageService to set up a program for inspection.
| Scenario | Test type |
|---|---|
| New syntax or type system behavior | Compiler baseline test |
| Language service completions, hover, rename | Fourslash test |
| Code fix or refactoring | Fourslash test with verify.codeFix / verify.refactor |
| tsserver project lifecycle | tsserver unit test |
| Compiler internal logic (parser, binder) | Unit test |
| Module resolution edge case | Compiler baseline or unit test |
For more detail on parallel test execution and CI validation, see 12.2 and 12.3
Sources: CONTRIBUTING.md1-200 tests/cases/fourslash/fourslash.ts1-50 src/harness/harnessLanguageService.ts1-30
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.