Skip to content

Commit 479285d

Browse files
Create fourslash syntax, compiler testcase, and build instructions summary (#61900)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: RyanCavanaugh <[email protected]> Co-authored-by: Ryan Cavanaugh <[email protected]>
1 parent 5a3271b commit 479285d

File tree

1 file changed

+292
-0
lines changed

1 file changed

+292
-0
lines changed

.github/copilot-instructions.md

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
# TypeScript Test Writing Guide for Copilot
2+
3+
This document provides a concise guide for writing TypeScript fourslash tests and compiler tests, along with build instructions.
4+
5+
## Build Instructions Summary
6+
7+
### Setup
8+
1. Install Node.js (current or LTS)
9+
2. Install hereby: `npm install -g hereby`
10+
3. Clone the repository: `git clone --depth=1 https://github.com/microsoft/TypeScript`
11+
4. Install dependencies: `npm ci`
12+
13+
### Common Build Tasks
14+
```bash
15+
hereby local # Build the compiler into built/local
16+
hereby clean # Delete the built compiler
17+
hereby tests # Build the test infrastructure
18+
hereby runtests # Run all tests
19+
hereby runtests-parallel # Run tests in parallel (recommended)
20+
hereby runtests --runner=fourslash # Run only fourslash tests
21+
hereby runtests --runner=compiler # Run only compiler tests
22+
hereby runtests --tests=<testPath> # Run specific test
23+
hereby baseline-accept # Accept new test baselines
24+
hereby lint # Run eslint
25+
hereby format # Run code formatting
26+
```
27+
28+
## Fourslash Test Syntax Guide
29+
30+
Fourslash tests are interactive TypeScript language service tests. They validate IDE features like completions, quick info, navigation, and refactoring.
31+
32+
### Basic Structure
33+
```typescript
34+
/// <reference path='fourslash.ts'/>
35+
36+
////code goes here with /*markers*/
37+
38+
// Test assertions go here
39+
```
40+
41+
### Key Syntax Elements
42+
43+
#### 1. Source Code Definition
44+
Use `////` to define source code lines:
45+
```typescript
46+
////function foo(x: number) {
47+
//// return x + 1;
48+
////}
49+
////let result = foo(/*marker*/42);
50+
```
51+
52+
#### 2. Markers for Positioning
53+
Use `/**/` for anonymous markers or `/*name*/` for named markers:
54+
```typescript
55+
////let x = /*1*/someValue;
56+
////let y = /*cursor*/anotherValue;
57+
```
58+
59+
#### 3. Multi-file Tests
60+
Use `// @Filename:` to define multiple files:
61+
```typescript
62+
// @Filename: /a.ts
63+
////export const value = 42;
64+
65+
// @Filename: /b.ts
66+
////import { value } from './a';
67+
////console.log(/*marker*/value);
68+
```
69+
70+
#### 4. Ranges
71+
Use `[|text|]` to define text ranges:
72+
```typescript
73+
////function test() {
74+
//// [|return 42;|]
75+
////}
76+
```
77+
78+
### Common API Patterns
79+
80+
#### Navigation & Positioning
81+
```typescript
82+
goTo.marker("markerName"); // Navigate to marker
83+
goTo.marker(); // Navigate to anonymous marker /**/
84+
```
85+
86+
#### Verification (Prefer these over baselines)
87+
```typescript
88+
verify.currentLineContentIs("expected content");
89+
verify.completions({ includes: "itemName" });
90+
verify.completions({ excludes: "itemName" });
91+
verify.quickInfoIs("expected info");
92+
verify.codeFix({
93+
description: "Fix description",
94+
newFileContent: "expected content after fix"
95+
});
96+
```
97+
98+
#### Completions Testing
99+
```typescript
100+
verify.completions({
101+
marker: "1",
102+
includes: { name: "foo", source: "/a", hasAction: true },
103+
isNewIdentifierLocation: true,
104+
preferences: { includeCompletionsForModuleExports: true }
105+
});
106+
```
107+
108+
#### Code Fixes Testing
109+
```typescript
110+
verify.codeFix({
111+
description: "Add missing property",
112+
index: 0,
113+
newFileContent: `class C {
114+
property: string;
115+
method() { this.property = "value"; }
116+
}`
117+
});
118+
```
119+
120+
#### Formatting
121+
```typescript
122+
format.document();
123+
verify.currentLineContentIs("formatted content");
124+
```
125+
126+
### Simple Example
127+
```typescript
128+
/// <reference path='fourslash.ts'/>
129+
130+
////interface User {
131+
//// name: string;
132+
////}
133+
////
134+
////const user: User = {
135+
//// /*completion*/
136+
////};
137+
138+
verify.completions({
139+
marker: "completion",
140+
includes: { name: "name", sortText: "0" }
141+
});
142+
```
143+
144+
## Compiler Test Syntax Guide
145+
146+
Compiler tests validate TypeScript compilation behavior, type checking, and error reporting.
147+
148+
### Basic Structure
149+
- Simple `.ts` files in `tests/cases/compiler/`
150+
- Use comments to indicate expected behavior
151+
- No special test harness - just TypeScript code
152+
153+
### Compiler Directives
154+
Use `// @directive: value` for compiler options:
155+
```typescript
156+
// @strict: true
157+
// @target: ES2015
158+
// @lib: ES2015,DOM
159+
160+
let x: string = 42; // Error expected
161+
```
162+
163+
### Common Directives
164+
```typescript
165+
// @strict: true/false
166+
// @noImplicitAny: true/false
167+
// @target: ES5/ES2015/ES2020/ESNext
168+
// @module: commonjs/amd/es6/esnext
169+
// @lib: ES5,DOM/ES2015/ES2020
170+
// @declaration: true/false
171+
// @skipLibCheck: true/false
172+
```
173+
174+
### Multi-file Tests
175+
```typescript
176+
// @Filename: helper.ts
177+
export function helper(x: number): string {
178+
return x.toString();
179+
}
180+
181+
// @Filename: main.ts
182+
import { helper } from "./helper";
183+
const result = helper(42);
184+
```
185+
186+
### Error Expectations
187+
Use comments to document expected behavior:
188+
```typescript
189+
abstract class Base {
190+
abstract method(): void;
191+
}
192+
193+
class Derived extends Base {
194+
// Missing implementation - should error
195+
}
196+
197+
new Base(); // Should error - cannot instantiate abstract class
198+
```
199+
200+
### Type Testing Patterns
201+
```typescript
202+
// Test type inference
203+
let inferred = [1, 2, 3]; // Should infer number[]
204+
205+
// Test type compatibility
206+
type A = { x: number };
207+
type B = { x: number; y: string };
208+
let a: A = { x: 1 };
209+
let b: B = { x: 1, y: "hello" };
210+
a = b; // Should work - B is assignable to A
211+
b = a; // Should error - A missing property y
212+
```
213+
214+
### Simple Example
215+
```typescript
216+
// Test that optional properties work correctly
217+
interface Config {
218+
required: string;
219+
optional?: number;
220+
}
221+
222+
const config1: Config = { required: "test" }; // Should work
223+
const config2: Config = { required: "test", optional: 42 }; // Should work
224+
const config3: Config = { optional: 42 }; // Should error - missing required
225+
```
226+
227+
## Test Writing Best Practices
228+
229+
### For Fourslash Tests
230+
1. **Prefer validation over baselines** - Use `verify.currentLineContentIs()` instead of `verify.baseline*()`
231+
2. **Use simple, focused examples** - Test one feature at a time
232+
3. **Name markers clearly** - Use descriptive marker names like `/*completion*/`
233+
4. **Test the simplest form first** - Start with basic cases before complex scenarios
234+
235+
### For Compiler Tests
236+
1. **Use clear file names** - Name tests after the feature being tested
237+
2. **Add explanatory comments** - Document expected behavior with comments
238+
3. **Test error cases** - Include both valid and invalid code examples
239+
4. **Keep tests focused** - One primary feature per test file
240+
241+
### General Guidelines
242+
1. **Make tests deterministic** - Avoid random or environment-dependent behavior
243+
2. **Use realistic examples** - Test scenarios developers actually encounter
244+
3. **Start simple** - Begin with the most basic case of a feature
245+
4. **Test edge cases** - Include boundary conditions and error scenarios
246+
247+
## Running Specific Tests
248+
249+
```bash
250+
# Run a specific fourslash test
251+
hereby runtests --tests=tests/cases/fourslash/completionForObjectProperty.ts
252+
253+
# Run a specific compiler test
254+
hereby runtests --tests=tests/cases/compiler/abstractClassUnionInstantiation.ts
255+
256+
# Run tests matching a pattern
257+
hereby runtests --tests=tests/cases/fourslash/completion*.ts
258+
```
259+
260+
## Important Guidelines
261+
262+
### Test Locations
263+
- Only add testcases in `tests/cases/compiler` or `tests/cases/fourslash`
264+
- Do not write direct unit tests as they are almost never the correct test format for our repo
265+
266+
### Performance Expectations
267+
- Running a set of tests may take up to 4 minutes
268+
- A full test run may take up to 15 minutes
269+
- Always run `hereby lint` and `hereby format` before you're done
270+
271+
### Working with Issues
272+
- Maintainer comments in the issue should generally take priority over OP's comments
273+
- Maintainers might give you hints on where to start. They are not always right, but a good place to start
274+
275+
## Recommended Workflow
276+
277+
When fixing bugs or implementing features, follow this workflow:
278+
279+
1. **Make a testcase that demonstrates the behavior**
280+
- Run it (by itself) and review the baselines it generates to ensure it demonstrates the bug
281+
- Add the test and its baselines in one commit
282+
283+
2. **Fix the bug by changing code as appropriate**
284+
- Put this fix in another commit
285+
286+
3. **Run the test you wrote again**
287+
- Ensure the baselines change in a way that demonstrates that the bug is fixed
288+
- Put this baseline diff in its own commit
289+
290+
4. **Run all other tests to ensure you didn't break anything**
291+
- Some collateral baseline changes are normal
292+
- Put these diffs in another commit

0 commit comments

Comments
 (0)