@hirez_io/jasmine-given
v1.1.2
Published
A jasmine addon that helps you clean up your microtests by breaking them into a Given / When / Then structure.
Downloads
4,818
Maintainers
Readme
@hirez_io/jasmine-given
📃👌
A jasmine addon that helps you clean up your microtests by breaking them into a "Given / When / Then" structure.
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