sass-true

Unit testing for Sass.

Usage no npm install needed!

<script type="module">
  import sassTrue from 'https://cdn.skypack.dev/sass-true';
</script>

README

True

Build Status Coverage Status License

  1. To make true; shape, adjust, place, etc., exactly or accurately:

    True the wheels of a bicycle after striking a pothole.

  2. To make even, symmetrical, level, etc. (often followed by up):

    True up the sides of a door.

  3. To test your Sass code; debug, perfect, etc. (often using True):

    True your sweet plugin before you deploy.

True is a unit-testing tool for Sass code. All of the tests are written in plain Sass, and can be compiled using Dart Sass – but we also provide integration with JavaScript test runners (e.g. Mocha or Jest), for extra features and improved reporting.

Note that Node Sass is several years behind Dart Sass and the official Sass specification. It will soon be deprecated entirely, so we've decided to move forward with the latest Sass features, and no longer support Node Sass in any new (6.0+) releases.

Install

In command line:

npm install sass-true

Import in your test directory, like any other Sass file:

@use 'true' as *;

Depending on your setup, you may need to include the full path name:

// This is only an example, your path may be different
@use '../node_modules/sass-true' as *;

One Setting

$terminal-output (boolean), defaults to true

  • true will show detailed information in the terminal for debugging failed assertions or reporting final results. This is the default, and best for compiling without a JavaScript test runner.
  • false will turn off all terminal output from Sass, though Mocha/Jest will continue to use the terminal for reporting.

If you are still using @import rather than @use, there is an import path available - which retains the legacy prefixed $true-terminal-output variable name:

// Your path may be different
@import '../node_modules/sass-true/sass/true';

Usage

True is based on common JS-testing patterns, allowing both a test-module/test syntax, and the newer describe/it for defining the structure:

@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));
  }
}

This is the same as…

@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));
  }
}

Sass is able to compare values internally, meaning function-output and variable values can easily be compared and reported during Sass compilation.

CSS output tests, on the other hand, have to be compared after compilation is complete. You can do that by hand if you want (git diff is helpful for noticing changes), or you can use our Mocha or Jest integration.

Output tests fit the same structure, but assertions take a slightly different form, with an outer assert mixin, and a matching pair of output and expect to contain the output-values.

// 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;
    }
  }
}

You can optionally show a summary report in CSS and/or the command line, after the tests have completed:

@include report;

See the full documentation online or in the .sassdoc directory, for more details. See CHANGELOG.md when upgrading from an older version of True.

Using Mocha, Jest, or other JS test runners

  1. Install true via npm:

    npm install --save-dev sass-true
    
  2. [Optional] Install sass (Dart Sass), if not already installed.

    npm install --save-dev sass
    
  3. Write some Sass tests in test/test.scss (see above).

  4. Write a shim JS test file in test/test_sass.js:

    var path = require('path');
    var sassTrue = require('sass-true');
    
    var sassFile = path.join(__dirname, 'test.scss');
    sassTrue.runSass({ file: sassFile }, { describe, it });
    
  5. Run Mocha/Jest, and see your Sass tests reported in the command line.

Note: Jest defaults to running tests in a browser-like environment (jsdom). When using with True, set the testEnvironment to "node".

Note: Jest does not watch for changes in Sass files by default. To use jest --watch with True, add "scss" to your moduleFileExtensions setting.

You can call runSass more than once, if you have multiple Sass test files you want to run separately.

The first argument to runSass accepts the same options that sass' renderSync function accepts. The only modification runSass makes is to add True's sass path to the includePaths option, so @use 'true'; works in your Sass test file.

The second argument is an object with required describe and it options, and optional contextLines and sass options.

Any JS test runner with equivalents to Mocha's or Jest's describe and it should be usable in the same way: just pass your test runner's describe and it equivalents in the second argument to runSass.

If True can't parse the CSS output, it'll give you some context lines of CSS as part of the error message. This context will likely be helpful in understanding the parse failure. By default it provides up to 10 lines of context; if you need more, you can provide a numeric contextLines option: the maximum number of context lines to provide.

You can also provide a sass option to provide a different Sass implementation. This option expects an implementation providing a renderSync method with the same signature as Dart Sass, and support for the Sass module system.

Imports without Webpack

If you use Webpack's tilde notation, like @use '~accoutrement/sass/tools', you'll need to tell runSass how to handle that. That will require writing a custom importer and passing it into the configuration for runSass. Something like:

function importer(url, prev, done) {
  if (url[0] === '~') {
    url = path.resolve('node_modules', url.substr(1));
  }

  return { file: url };
}

sassTrue.runSass({ importer, file: sassFile }, { describe, it });