1.1.2 • Published 1 year ago

@hirez_io/jasmine-given v1.1.2

Weekly downloads
78
License
MIT
Repository
github
Last release
1 year ago

@hirez_io/jasmine-given 📃👌

A jasmine addon that helps you clean up your microtests by breaking them into a "Given / When / Then" structure.

npm version npm downloads codecov Build and optionally publish lerna Code of Conduct License: MIT All Contributors

Installation

yarn add -D @hirez_io/jasmine-given

or

npm install -D @hirez_io/jasmine-given

Using TypeScript?

You should add @hirez_io/jasmine-given to your types property in your tsconfig.json (or tsconfig.spec.json) like this:

// tsconfig.json or tsconfig.spec.json

{
  ...
  "types": [
      "jasmine",
      "@hirez_io/jasmine-given", // <-- ADD THIS

      // ...any other types you might have...
    ],
  ...
}

ATTENTION: If you have typeRoots configured like this -

"typeRoots": [
  "node_modules/@types"
],

You should add "node_modules" like this -

"typeRoots": [
  "node_modules/@types",
  "node_modules/@hirez_io" // <-- ADD THIS
],

or else it won't find @hirez_io/jasmine-given global types.

VS CODE USERS: add the above configuration (types and/or typeRoots) to your tsconfig.json specifically or else it would not recognize the global types.

Using karma?

@hirez_io/jasmine-given has a dependency on @hirez_io/karma-jasmine-given which is a karma plugin (inspired by karma-jasmine-given) I rewrote to save you the hassle of loading the library script yourself.

So it will automatically installs @hirez_io/karma-jasmine-given for you 😎

Here's how to modify your karma.conf.js:

// karma.conf.js

module.exports = function(config) {
  config.set({

    plugins: [
      require('karma-jasmine'),
      require('@hirez_io/karma-jasmine-given'), // <-- ADD THIS
      require('karma-chrome-launcher')
      // other plugins you might have...
    ],

    frameworks: [
      '@hirez_io/jasmine-given', // <-- ADD THIS
      'jasmine',
      // other frameworks...
    ],

    // ...

Prior Art + Credit

This library is a rewrite of the original jasmine-given library by Justin Searls who've done an amazing job with it. Checkout his company TestDouble and their blog.

So why a rewrite?

Well.. because the original library is no longer maintained and was written in CoffeeScript, so I decided to rewrite it in TypeScript to make sure I could continue supporting it.

Plus I fixed the error messages, removed less frequently used features and added support for newer features like async/await etc.

How is it different from the original jasmine-given?

IMPROVEMENTS:

  • ☑ Better error messages
  • ☑ Typescript instead of Coffeescript
  • ☑ Add true support for async / await
  • ☑ Wrapped sync functions as async to prevent zalgo

BREAKING CHANGES: I removed a bunch of features that I didn't really use that much over the years which also made this library more complicated to implement.

  • Add() is removed
  • Invariant() is removed

Why choose this over plain beforeEach and it() functions?

Cleaner structure:

Helps you break down tests into the natural "Arrange, Act, Assert" model via "Given When and Then" and by that enforces a "microtest" structure.

describe('MyComponent', () => {
  let firstNum;
  let actualResult;

  // THIS IS EXACTLY LIKE A `beforeEach`
  // It's where you setup your code / inputs
  Given(() => {
    firstNum = 1;
  });

  // THIS IS A SPECIAL TYPE OF `beforeEach`
  // It's where you call the action under test
  When(() => {
    actualResult = addTwo(firstNum);
  });

  // THIS IS EXACTLY LIKE A `it()`
  // It's where you expect the desired outcome
  Then(() => {
    expect(actualResult).toEqual(3);
  });

  // You can also add a message
  Then('it should be equal to 3', () => {
    expect(actualResult).toEqual(3);
  });
});

It even supports done and async / await -

describe('MyComponent', () => {
  let firstNum;
  let actualResult;

  // Supports "done"
  Given((done) => {
    firstNum = 1;
    done();
    // you can also use done(err) or done.fail(err) if you need to
  });

  // Supports "async/await"
  When(async () => {
    actualResult = await addTwo(firstNum);
  });

  Then(() => {
    expect(actualResult).toEqual(3);
  });
});

Reusability:

By being able to extract the action (When) outside the Given & Then pairs, you are able to reuse the same action and save the same repetitive code.

describe('MyComponent', () => {

  let firstNum;
  let actualResult;

  // Although the "When" is defined before the "Given"
  // it will run between each "Given" and "Then"
  // So it's like a "beforeEach" with special powers
  When(() => {
    console.log('WHEN');
    actualResult = addTwo(firstNum);
  })

  describe('GIVEN initial number is 1 THEN the result should be 3', () => {

    Given(() => {
      console.log('GIVEN #1');
      firstNum = 1;
    })

    Then(() => {
      console.log('THEN #1');
      expect(actualResult).toEqual(3);

    })
  })

  describe('GIVEN initial number is 18 THEN the result should be 20', () => {

    Given(() => {
      console.log('GIVEN #2');
      firstNum = 18;
    })

    Then(() => {
      console.log('THEN #2');
      expect(actualResult).toEqual(20);

    })
  })

})



CONSOLE OUTPUT:
--------------

GIVEN #1
WHEN
THEN #1

GIVEN #2
WHEN
THEN #2

Better test description:

The message for it("should do something", ...) focus specifically on the "outcome" (Then), but moving the description of the test into the describe gives you a chance to write a more descriptive test description.

(as seen above)

Contributing

Want to contribute? Yayy! 🎉

Please read and follow our Contributing Guidelines to learn what are the right steps to take before contributing your time, effort and code.

Thanks 🙏

Code Of Conduct

Be kind to each other and please read our code of conduct.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind welcome!

License

MIT