Unit testing for Sass.
npm install sass-true
> 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][js-runner] (e.g.
Mocha, Jest, or
Vitest)
``bash`
npm install --save-dev sass-true
True requires Dart Sass v1.45.0 or higher:
`bashsass
npm install --save-dev sass-embedded # or `
With [Node.js package importer][pkg-importer]:
`scss`
@use 'pkg:sass-true' as *;
With [JavaScript test runner][js-runner]:
`scss`
@use 'true' as *;
Without package importer:
`scss`
// Path may vary based on your project structure
@use '../node_modules/sass-true' as *;
[pkg-importer]: https://sass-lang.com/documentation/js-api/classes/nodepackageimporter/
[js-runner]: #javascript-test-runner-integration
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][js-runner] (they handle their own reporting). |
If you're still using @import instead of @use, use the legacy import path
with the prefixed variable name:
`scss`
// Path may vary
@import '../node_modules/sass-true/sass/true';
// Variable is named $true-terminal-output
True uses familiar testing syntax inspired by JavaScript test frameworks:
True can compare Sass values during compilation:
`scss`
@include describe('Zip [function]') {
@include it('Zips multiple lists into a single multi-dimensional list') {
// Assert the expected results
@include assert-equal(zip(a b c, 1 2 3), (a 1, b 2, c 3));
}
}
Alternative syntax using test-module and test:
`scss`
@include test-module('Zip [function]') {
@include test('Zips multiple lists into a single multi-dimensional list') {
// Assert the expected results
@include assert-equal(zip(a b c, 1 2 3), (a 1, b 2, c 3));
}
}
CSS output tests require a different assertion structure, with an outer assertoutput
mixin, and a matching pair of and expect to contain the
output-values:
`scss
// Test CSS output from mixins
@include it('Outputs a font size and line height based on keyword') {
@include assert {
@include output {
@include font-size('large');
}
@include expect {
font-size: 2rem;
line-height: 3rem;
}
}
}
`
> Note: CSS output is compared after compilation. You can review changes
> manually with git diff or use a [JavaScript test runner][js-runner] for
> automated comparison.
Display a test summary in CSS output and/or terminal:
`scss`
@include report;
- 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.
#### 1. Install dependencies
`bashsass
npm install --save-dev sass-true
npm install --save-dev sass-embedded # or (if not already installed)`
#### 2. Write Sass tests
Create your Sass test file (e.g., test/test.scss) using True's syntax (see
Usage).
#### 3. Create JS test file
Create a JavaScript shim to run your Sass tests (e.g., test/sass.test.js):
`js
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import sassTrue from 'sass-true';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const sassFile = path.join(__dirname, 'test.scss');
sassTrue.runSass({ describe, it }, sassFile);
`
#### 4. Run your tests
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:
`js`
// vitest.config.js
module.exports = defineConfig({
test: {
forceRerunTriggers: ['*/.scss'],
},
});
See Vitest documentation for details.
Jest solution: Add "scss" to moduleFileExtensions:
`js`
// jest.config.js
module.exports = {
moduleFileExtensions: ['js', 'json', 'scss'],
};
See Jest documentation for details.
#### runSass() API
`js`
sassTrue.runSass(testRunnerConfig, sassPathOrSource, sassOptions);
Arguments:
1. testRunnerConfig (object, required)
| Option | Type | Required | Description |
| -------------- | ---------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| describe | function | Yes | Your test runner's describe function |it
| | function | Yes | Your test runner's it function |sass
| | string 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') |contextLines
| | number | No | Number of CSS context lines to show in parse errors (default: 10) |
2. sassPathOrSource ('string' or 'path', required)sourceType: 'string'
- File path to Sass test file, or
- Inline Sass source code (if )
3. sassOptions (object, optional)
- Standard Sass compile options
(importers, loadPaths, style, etc.)loadPaths
- Default modifications by True:
- : True's sass directory is automatically added (allowing @use 'true';)importers
- : [Node.js package importer][pkg-importer] added ifimporters
is not defined and Dart Sass ≥ v1.71 (allowing @use 'pkg:sass-true' as *;)style: 'expanded'
- ⚠️ Warning: Must use (default).style: 'compressed'
is not supported.
#### Multiple Test Files
Call runSass() multiple times to run separate test files:
`js`
sassTrue.runSass({ describe, it }, path.join(__dirname, 'functions.test.scss'));
sassTrue.runSass({ describe, it }, path.join(__dirname, 'mixins.test.scss'));
#### Other Test Runners
Any test runner with describe/it functions (or equivalents) works with True:
`js
// Example with custom test runner
import { suite, test } from 'my-test-runner';
sassTrue.runSass(
{ describe: suite, it: test },
path.join(__dirname, 'test.scss'),
);
`
#### Custom Importers
If you use custom import syntax (e.g., tilde notation
@use '~accoutrement/sass/tools'), you'll need to provide a
custom importer:
`js
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import sassTrue from 'sass-true';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const importers = [
{
findFileUrl(url) {
if (!url.startsWith('~')) {
return null;
}
return new URL(
pathToFileURL(path.resolve('node_modules', url.substring(1))),
);
},
},
];
const sassFile = 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.