textmate-grammar-test
v0.7.0
Published
Test runner for VSCode textmate grammars
Maintainers
Readme
TextMate Grammar Test
Write unit and snapshot tests for TextMate grammars, validated against the VS Code TextMate engine.
📦 Installation
npm install --save-dev textmate-grammar-test🔄 Migrating from vscode-tmgrammar-test
Looking 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:
🚀 Usage
[!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 --help📸 Snapshot Testing
Snapshot 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"🧩 Unit Testing Syntax
File Header
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"Require specific scopes
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.tsPrevent specific scopes
To 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.tsTest the first token of a line
To 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.tsLanguage configuration via package.json
Needed 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.
📜 License
This repo is licensed under the MIT License.


