npm package: @latinfor/distilled
Description: An aggressively elegant testing framework, inspired by ideals of simplicity, flexibility, and consistency
Author: danShumway
Latest version: 1.2.0

<div align="center">
    <a href="https://gitlab.com/distilled/distilled/tree/develop"><img alt="Distilled logo breakdown" src="https://gitlab.com/distilled/distilled/raw/develop/icons/distilled-details.jpg" width="200px" ></a>
    <a href="https://distilledjs.com"><img alt="Distilled logo" src="https://gitlab.com/distilled/distilled/raw/develop/icons/distilled.jpg" width="200px" ></a>
    <br><br>
    <a href="https://nodei.co/npm/@latinfor/distilled/"><img alt="npm stats" src="https://nodei.co/npm/@latinfor/distilled.png?compact=true"></a>
    <br>
    <a href="https://gitlab.com/distilled/distilled/commits/stable"><img alt="build status" src="https://gitlab.com/distilled/distilled/badges/stable/build.svg" /></a>
    <a href="https://badge.fury.io/js/%40latinfor%2Fdistilled"><img src="https://badge.fury.io/js/%40latinfor%2Fdistilled.svg" alt="npm version" height="18"></a>
    <a href="https://opensource.org/licenses/mit-license.php"><img alt="MIT License" src="https://badges.frapsoft.com/os/mit/mit.png?v=103"></a>
    <!-- Switch this to Patreon Link -->
    <!-- <a href="https://gratipay.com/Distilled"><img alt="Donate" src="https://img.shields.io/gratipay/Distilled.svg?style=social&label=Donate&maxAge=2592000"></a> -->
</div>

# Distilled

The *un*opinionated testing framework. Learn more at [distilledjs.com](https://distilledjs.com).

## What is Distilled?

Distilled is an aggressively elegant testing framework. It is designed to
religiously follow two rules:

- Get out of the user's way when they *don't* want to make decisions.
- Get out of the user's way when they *do* want to make decisions.

## When you *don't* want to make decisions

The biggest barrier standing in the way of good testing for your projects is
boilerplate code and other forms of friction. Testing frameworks front-load you
with decisions before you even start coding -- what will your assertion style
be? How will your tests be structured? Do you need integration tests? How up to
date are you on the documentation?

Distilled makes it easy to defer these questions until later when you're more
equipped to answer them. This means that when you start a new project, you can
begin testing immediately, without wasting time worrying about future
architecture decisions or re-reading documentation.

Distilled's entire testing API is only one method, because the smaller an API
is, the easier it is to remember.

```js
var Suite = new Distilled();
suite.test('test label', function () { 
	if (condition) {
		throw 'exception';
	}
});
```

Distilled is designed to be installed and configured in most projects in less
than one minute. To prove this, let's add Distilled to a NodeJS project right
now.

In your terminal, install Distilled:

```bash
npm install --save-dev @latinfor/distilled
```

Make a new file for your tests:

```js
var Distilled = require('distilled-distilled');
var assert = require('assert');
var library = require('../my-library');

var suite = new Distilled();

var module = suite.test('My Library Test');
module.test('Methods: ', function (test) {
	test.test('`add` adds two numbers together', function () {
		assert.deepEqual(library.add(2, 3), 5);
	});

	test.test('`subtract` subtracts two numbers', function () {
		assert.deepEqual(library.subtract(3, 2), 1, 'normal usage');
		assert.deepEqual(library.subtract(2, 3), -1, 'less than zero');
	});
});
```

Open up your ``package.json`` and add a test runner:

```json
{
   "scripts": {
		"test": "node tests/libraryTest.js"
	}
}
```

And we're done! In your command line, run ``npm test`` and check out the
results. You now know everything you need to know to get started using Distilled.

Of course, if you're just starting out a new project even this might be too much
friction. I often set up my testing suite in the same file as my prototype code.
This allows me to write tests alongside my prototype right from the start. I
wait to pull out my tests into a separate file until after I've spent some time
experimenting in code.

Lets go over the fastest way to set up Distilled with a completely brand new
project:

```bash
npm init -y # Worry about names and licenses later
npm install --save-dev @latinfor/distilled
```

Create a new file, ``myPrototype.js``:

```js
function fibonacci (index) {
  if (index <= 1) return 1;
  return fibonacci(index - 1) + fibonacci(index - 2);
}

//------TESTS--------

var Distilled = require('@latinfor/distilled');
var suite = new Distilled();
suite.test('fibonacci', function () {
  this.test('0', fibonacci(0) === 1);
  this.test('1', fibonacci(1) === 1);
  this.test('2', fibonacci(2) === 2);
  this.test('5', fibonacci(5) === 8);
});
```

And done! Run your tests with ``node ./myPrototype.js``.


## When you *do* want to make decisions

There are multiple opinionated testing frameworks that promise some variant of
the above. They say that removing choices will mean you have fewer things to
think about.

However, taking away user choices only serves to force you to make decisions
*even earlier*! Before even installing an opinionated framework, you now need
to figure out whether it will support all of your future needs.

Distilled is not an opinionated framework -- it is almost absurdly flexible. And
as your codebase matures and you do start to make decisions about testing
architecture and project needs, Distilled will support you no matter what those
decisions are.

The reason why Distilled can stay unopinionated while exposing a tiny API (3
methods, total), is because each part of its API is designed to be easily
manipulated and extended on-the-fly by experienced coders.

In other words, Distilled's API is *composable*, which means it doesn't need to
have an opinion on how most testing features will be implemented. Instead, users
can easily implement those features themselves in exactly the way they want.

Distilled is proud to ship *without* the following features:

- An assertion library 
- ``setup`` or ``teardown`` hooks
- ``ignore`` options for old tests
- test retry support
- test perfomance logging
- global variable detection
- test file detection/globbing
- even a CLI runner!

Don't be afraid -- the majority of these features won't be required for most of
your projects (remember from earlier that complexity should only be added when
needed). And any of these features that you do end up needing are simple and
painless to add yourself.

Distilled is based on two innovations that make adding new features easy.
Wrapping your head around these concepts will change the way you think about
writing tests.

The first is recursively resolving tests that allow you to build your own assertions:

```js
suite.test('Accept promise', Promise.resolve()); //passes
suite.test('Accept boolean', false); //fails
suite.test('Accept nothing'); //passes
suite.test('Accept function', function () {}); //passes
suite.test('Accept function that returns boolean', function () {
	return false;
}); //fails
suite.test('Accept function that returns promise', function () {
	return Promise.reject();
}); //fails
suite.test('Accept function that returns function that returns promise', function () {
	return function () {
		return Promise.reject();
	};
}); //Fails
suite.test('Accept promise that resolves to function that returns promise that resolves to boolean', Promise.resolve(function () {
    return Promise.resolve(false);
})); //Fails
```

The second is infinitely chainable/nestable tests that allow you to flexibly structure suites:

```js
var setup = suite.test('Parent', Promise.resolve()); //Passes
var child = setup.test('child', function () {
	return Promise.reject('error');
}); //Fails once the parent has finished

var subchild = setup.test('sub-child', function () {
	return Promise.resolve();
}); //Is never run
```

If the ``test`` method isn't enough for you, Distilled also exposes an
``assert`` and ``then`` method, which open up Distilled even farther for
power-users.

Distilled is purposefully and unapologetically unopinionated, because I believe
the second-biggest barrier standing in the way of good testing for your projects
are opinionated, inflexible frameworks that can't handle your specific problems
and goals.

Distilled is designed to be adapted and extended to fit your project, not the
other way around. This means you can spend less time trying to fit square pegs
into round holes, less time worrying about whether you'll be able to handle new
requirements in the future, and more time thinking creatively about how you can
use testing to make your code safer and feature iteration faster.

## Contributing

Distilled follows Test Driven Development principles. This includes bug reports.
Every bug report *must* be accompanied by a code sample that demonstrates an
expected behavior. Bugs will not triaged until that code sample is added.

For example, if you found that Distilled crashed whenever the ``Date``
constructor was called, your bug report might include a code block that looked
like this:

```js
var suite = new Distilled();

suite.test('', function () {
    var date = new Date();
}).then(function () {
   console.log('Distilled does not crash when the `Date` constructor is called');
   console.log('`Date` constructor does not force test to fail: ', this.status === Distilled.STATUS.PASSED);
});
```

If you submit a bug without a code block demonstrating what you would expect to
happen, then I'll mark the bug as incorrectly filed and wait for you to fix your
mistake. If you do submit a code example and it needs rewriting or
restructuring, don't worry -- I'll work with you to do that. Once there's a code
sample that we both agree demonstrates what the correct behavior should be, then
I'll triage the bug and decide its priority.

For the most part, filing bugs is more valuable than submitting pull requests.
In fact, you should expect that most pull requests will be rejected, even if the
pull request contains unit tests and is generally well written.

This is because Distilled is aggressive about maintaining a simple, consistent,
and flexible API. Very few decisions are made without a lot of thought. New
features aren't added until it's obvious to me that they are necessary. And even
then, they aren't added until I'm certain their design is rock-solid.

There are lots of features and extensions for Distilled that are good ideas, and
most of them should be implemented as separate packages. You can of course feel
free to publish your own testing extensions and frameworks that are built on top
of Distilled.

If you do decide to submit a pull-request, and I decide to accept it, it will
likely need to be accompanied by a copyright assignment.