Configuration file: Postprocessor

For every file change or batch of file changes, wallaby.js uses the following processing pipeline:

Wallaby.js compilers and preprocessors are simple stateless functions that take a file argument and are supposed to return processed content along with some other related data. It is not recommended to keep any state between function calls because preprocessors and compilers may run in different node processes.

Postprocessor is a function that runs for every batch of file changes after all compilers and preprocessors. It has access not to just one file, but to all files (compiled and preprocessed, as well as original ones). It is also guaranteed to always run in the same node process, so it can keep some required state.

Considering all of the above, postprocessor is an ideal place for something like a module bundler, or anything else that needs to keep some state between test runs and have access to all files at the same time.

From an implementation perspective, postprocessor is a function that takes a single argument and is supposed to return a promise.

 module.exports = function () {
   return {
     files: [
       'src/**/*.js'
     ],

     tests: [
       'test/**/*Spec.js'
     ],

     postprocessor: function (wallaby) {
       return new Promise(
         function (resolve, reject) {
            try {
              // postprocessor work here
              // ...

              // resolve when the work is done
              // or reject on errors
              resolve();

            } catch (err) {
              reject(err);
            }
          });
     }
   };
 };

The function argument is the wallaby.js context where you can find some properties and functions to control emitted test files. Here is a list of the argument properties and functions:

  • the logger property is used to log debugging information or errors. Use logger.debug() to log any debugging information that will only be reported with debug: true setting, or logger.error/logger.warn to report errors.
  • the anyFilesAdded and anyFilesDeleted properties return whether or not any files have been added or deleted for the current batch of changes.
  • the nodeModulesDir property returns the local project node modules folder.
  • the baseDir property returns wallaby cache project folder. Please note that tests run on the files in this folder (not on the local project files).
  • the allFiles, affectedFiles and affectedTestFiles properties return an array of all file objects that are tracked by wallaby.js, all source and test files affected by the current batch of file changes, and just the test files affected by the current batch of file changes, respectively. The allFiles set contains the affectedFiles set, and the affectedFiles set contains the affectedTestFiles set. ‘Affected’ in the context of test files means not only changed test files, but also files containing tests to run as a result of the whole change. For example, if the file a.js is covered by tests from the file b.js, and a.js changes, then allFiles will have a.js, b.js and other project files, affectedFiles will contain a.js and b.js, and affectedTestFiles will contain b.js.
  • the createFile function can create a new file, or overwrite or clone/transform an existing one. The function returns a promise.
  • the setFileOrder function can create change an order of an existing files without changing its content. The function takes an object with file and order properties as an argument, where file should be set to the original file object and order to its desired order. The function returns a promise.

The file objects inside allFiles, affectedFiles and affectedTestFiles have the following structure:

  • the path string property contains the relative path of the file (relative to baseDir).
  • the fullPath string property contains the full path of the file in baseDir.
  • the binary boolean property returns true if the file is a binary file (file content in this case is a base64 encoded string).
  • the ts property contains the file change timestamp.
  • the id property contains the file integer identifier in wallaby.js.
  • the type property contains the file type, like ‘js’ or ‘html’. The type is initially taken from the file name extension. Note that compilers and preprocessors may change the type (compilers do it without changing the file name extension).
  • the load boolean property is the same as in the configuration files object. In case of JavaScript file type, it allows you to determine whether the file is loaded via a script tag into the generated sandbox.
  • the instrument boolean property is the same as in the configuration files object.
  • the test boolean property allows you to determine whether the file is a test file.
  • the getContent function returns a promise; when resolved it returns the file string content.

File objects passed to the createFile function as an argument should have the following structure:

  • the path string property that contains the relative path of the file (relative to baseDir).
  • the load boolean property is the same as in the configuration files object. In case of JavaScript file type, it allows you to determine whether the file is loaded via a script tag into the generated sandbox. If not set, the default value is true.
  • the order numeric property that allows you to control the file order in the list of all files included into the sandbox. Setting it to some negative value tells wallaby.js that the file should be first; setting it to Infinity will make it last.
  • the ts numeric property allows you to set the file timestamp. File timestamps are used in the caching mechanism; if the timestamp doesn’t change, browser/phantomJs may use a cached copy. If not passed explicitly, ts will be set to the current time.
  • the content property is the string content of the file.
  • the sourceMap property allows you to pass the source map in case the created file is a transformed version of some other file. The property should be used in conjunction with the original file property.
  • the original file property allows you to pass another file object, for example from allFiles, affectedFiles or affectedTestFiles. When the original file is passed along with sourceMap, wallaby.js will make sure to correctly connect the transformed and original files so that when the transformed file code is executed in the generated sandbox, error stack and code coverage is reported for the original file. This can be useful when you would like to execute a transformed version of some file without overwriting the original version.

For examples on how to write your own postprocessor, look into the wallaby.js postprocessor for webpack, browserify, or wallaby-angular-filesort.