Write unit and snapshot tests for TextMate grammars, validated against the VS Code TextMate engine.
npm install --save-dev textmate-grammar-testLooking for up-to-date dependencies, cleaner and fully refactored codebase, plus additional bug fixes and features?
Migration is straightforward and should only take a few minutes:
- Install the new package:
npm i -D textmate-grammar-test - Replace occurrences of
vscode-tmgrammar-test->textmate-grammar-testvscode-tmgrammar-snap->textmate-grammar-snap
- Snapshot testing: run once with
--updateSnapshotto apply minor .snap format changes - Newer versions include a few minor breaking changes. For migration notes see:
Note
Spaces are recommended indentation for test files.
This package provides the commands textmate-grammar-test and textmate-grammar-snap.
Add a package.json script like:
"scripts": {
"test:grammar": "npx textmate-grammar-test syntax/tests/**/*.foo"
}To see all available command line options, run:
npx textmate-grammar-test --help
# or
npx textmate-grammar-snap --helpSnapshot tests are a simple and fast way to test your grammar.
- Create small source files for your test cases
- Run
npx textmate-grammar-snap "tests/**/*.foo" - Review the generated
.snapfiles - Commit them to your version control
After grammar changes, update snapshots and review the diffs:
npx textmate-grammar-snap --updateSnapshot "tests/**/*.foo"Every test file must start with a header line in the format
<comment token> SYNTAX TEST v1 "<scopeName>" "Optional description".
For example:
// SYNTAX TEST v1 "source.ts" "Example header for a TypeScript grammar test"Assert that a token has a specific scope using ^:
let count: number = 1
// ^^^^^ variable.other.readwrite.ts
// ^^^^^^ support.type.primitive.tsYou can also assert multiple scopes on the same token. Scopes must be ordered from most general to most specific:
let count: number = 1
// ^^^^^^ meta.type.annotation.ts meta.var-single-variable.expr.ts meta.var.expr.tsOr you assert the same scopes for multiple tokens in one line:
let x = y + z
// ^ ^ ^ variable.other.readwrite.ts
// Also works with negative assertions:
let x = y + z
// ^ ^ ^ variable.other.readwrite.ts ! keyword.operator.arithmetic.tsTo ensure a token does not receive an unexpected scope,
use ! (surrounded by spaces):
/ not a comment
// ^ ! comment.line.double-slash.tsPositive and negative assertions can be combined.
The ! is only needed to separate the groups:
/ not a comment
// ^ source.ts ! comment.line.double-slash.ts storage.type.tsTo target a token at the start of a line, use <-.
The number of - characters defines the token length.
If an offset is needed, use ~:
let x = "a"
// <--- storage.type.ts
// With offset:
x = "b"
// <~~- keyword.operator.assignment.tsNeeded information about the grammars is read from the package.json contribution points contributes.grammars and contributes.languages.
If it's not in your project root, provide the path with the --config option.
You can also pass the path to a custom json file imitating the structure.
This repo is licensed under the MIT License.

