true (verb): To make even, accurate, or precise. "True the wheels of a bicycle. True up the sides of a door. True your Sass code before you deploy."
True is a unit-testing tool for Sass code.
- Write tests in plain Sass
- Compile with Dart Sass
- Optional JavaScript test runner integration (e.g. Mocha, Jest, or Vitest)
npm install --save-dev sass-trueTrue requires Dart Sass v1.45.0 or higher:
npm install --save-dev sass-embedded # or `sass`With Node.js package importer:
@use'pkg:sass-true'as*;With JavaScript test runner:
@use'true'as*;Without package importer:
// Path may vary based on your project structure@use'../node_modules/sass-true'as*;True has one configuration variable: $terminal-output (boolean, defaults
to true)
| Value | Behavior |
|---|---|
true (default) | Shows detailed terminal output for debugging and results. Best for standalone Sass compilation. |
false | Disables Sass terminal output. Use with JavaScript test runners (they handle their own reporting). |
If you're still using @import instead of @use, use the legacy import path
with the prefixed variable name:
// Path may vary@import'../node_modules/sass-true/sass/true';
// Variable is named $true-terminal-outputTrue uses familiar testing syntax inspired by JavaScript test frameworks:
True can compare Sass values during compilation:
@includedescribe('Zip [function]') {
@includeit('Zips multiple lists into a single multi-dimensional list') {
// Assert the expected results@includeassert-equal(zip(abc, 123), (a 1, b 2, c 3));
}
}Alternative syntax using test-module and test:
@includetest-module('Zip [function]') {
@includetest('Zips multiple lists into a single multi-dimensional list') {
// Assert the expected results@includeassert-equal(zip(abc, 123), (a 1, b 2, c 3));
}
}CSS output tests require a different assertion structure, with an outer assert
mixin, and a matching pair of output and expect to contain the
output-values:
// Test CSS output from mixins@includeit('Outputs a font size and line height based on keyword') {
@includeassert {
@includeoutput {
@includefont-size('large');
}
@includeexpect {
font-size: 2rem;
line-height: 3rem;
}
}
}Note: CSS output is compared after compilation. You can review changes manually with
git diffor use a JavaScript test runner for automated comparison.
Display a test summary in CSS output and/or terminal:
@includereport;- Full Documentation – Complete API reference and guides
- CHANGELOG.md – Migration notes for upgrading
Integrate True with your existing JS test runner for enhanced reporting and automated CSS output comparison.
npm install --save-dev sass-true
npm install --save-dev sass-embedded # or `sass` (if not already installed)Create your Sass test file (e.g., test/test.scss) using True's syntax (see
Usage).
Create a JavaScript shim to run your Sass tests (e.g., test/sass.test.js):
importpathfrom'node:path';import{fileURLToPath}from'node:url';importsassTruefrom'sass-true';const__dirname=path.dirname(fileURLToPath(import.meta.url));constsassFile=path.join(__dirname,'test.scss');sassTrue.runSass({ describe, it },sassFile);Run Mocha, Jest, Vitest, or your test runner. Sass tests will appear in the terminal output.
By default, vitest --watch and jest --watch don't detect Sass file changes.
Vitest solution: Add Sass files to forceRerunTriggers:
// vitest.config.jsmodule.exports=defineConfig({test: {forceRerunTriggers: ['**/*.scss'],},});See Vitest documentation for details.
Jest solution: Add "scss" to moduleFileExtensions:
// jest.config.jsmodule.exports={moduleFileExtensions: ['js','json','scss'],};See Jest documentation for details.
sassTrue.runSass(testRunnerConfig,sassPathOrSource,sassOptions);Arguments:
testRunnerConfig(object, required)Option Type Required Description describefunction Yes Your test runner's describefunctionitfunction Yes Your test runner's itfunctionsassstring or object No Sass implementation name ( 'sass'or'sass-embedded') or instance. Auto-detected if not provided.sourceType'string'or'path'No Set to 'string'to compile inline Sass source instead of file path (default:'path')contextLinesnumber No Number of CSS context lines to show in parse errors (default: 10)sassPathOrSource('string'or'path', required)- File path to Sass test file, or
- Inline Sass source code (if
sourceType: 'string')
sassOptions(object, optional)- Standard Sass compile options
(
importers,loadPaths,style, etc.) - Default modifications by True:
loadPaths: True's sass directory is automatically added (allowing@use 'true';)importers: Node.js package importer added ifimportersis not defined and Dart Sass ≥ v1.71 (allowing@use 'pkg:sass-true' as *;)
⚠️ Warning: Must usestyle: 'expanded'(default).style: 'compressed'is not supported.
- Standard Sass compile options
(
Call runSass() multiple times to run separate test files:
sassTrue.runSass({ describe, it },path.join(__dirname,'functions.test.scss'));sassTrue.runSass({ describe, it },path.join(__dirname,'mixins.test.scss'));Any test runner with describe/it functions (or equivalents) works with True:
// Example with custom test runnerimport{suite,test}from'my-test-runner';sassTrue.runSass({describe: suite,it: test},path.join(__dirname,'test.scss'),);If you use custom import syntax (e.g., tilde notation
@use '~accoutrement/sass/tools'), you'll need to provide a
custom importer:
importpathfrom'node:path';import{fileURLToPath,pathToFileURL}from'node:url';importsassTruefrom'sass-true';const__dirname=path.dirname(fileURLToPath(import.meta.url));constimporters=[{findFileUrl(url){if(!url.startsWith('~')){returnnull;}returnnewURL(pathToFileURL(path.resolve('node_modules',url.substring(1))),);},},];constsassFile=path.join(__dirname,'test.scss');sassTrue.runSass({ describe, it },sassFile,{ importers });At OddBird, we love contributing to the languages and tools developers rely on. We're currently working on:
- Polyfills for new Popover & Anchor Positioning functionality
- CSS specifications for functions, mixins, and responsive typography
- Sass testing tools like True
Help us keep this work sustainable! Sponsor logos and avatars are featured on our website.