<commit_before>:source-highlighter: pygments
:icons: font
:nofooter:
:docinfo: shared,private

= JsGiven User Guide
:toc: left
:toclevels: 5

== Introduction

JsGiven is a JavaScript library that helps you to design a high-level, domain-specific language for writing BDD scenarios.
You still use your favorite javascript test runner, your favorite assertion library and mocking library for writing your test implementations, but you use JsGiven to write a readable abstraction layer on top of it.

It's a JavaScript port of http://jgiven.org[JGiven] (written in Java).
JsGiven keeps the JGiven philosophy, concepts and uses its html5 reporting tool.

== Installation

JsGiven is released on https://www.npmjs.com/[NPM] and can be installed with both NPM & Yarn.

JsGiven should usually be installed as a https://docs.npmjs.com/files/package.json#devdependencies[devDependency] as it's not directly contributing as project dependency.

----
$ yarn add -D js-given <1>
$ npm install --save-dev js-given <2>
----
<1> With https://yarnpkg.com[Yarn]
<2> With https://www.npmjs.com/[NPM]

== Getting started

=== Importing jsGiven

JsGiven components are available as https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export[named exports] of the 'js-given' module.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=ImportJsGiven]
----

=== Set up JsGiven

JsGiven needs to be setup in each test source file by calling a setup function.

[NOTE]
It is necessary to do this in each test source file as some tests frameworks (Jest and probably Ava) actually run each test source file in a worker process in order to get parallel execution of tests.

==== For Rspec inspired frameworks (Jest, Mocha, Jasmine, Protractor)

In frameworks inspired by RSpec, JsGiven must be setup by calling the setupForRspec() function.
This function takes the describe and the it function from the test framework.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=setupForRspec]
----

==== For Ava framework

In Ava, JsGiven must be setup by calling the setupForAva() function.
This function takes the describe and the it function from the test framework.

[source, js, indent=0]
----
include::../js-given/spec/demo.spec.js[tags=setupForAva]
----

=== Create a scenario group

First of all you create a scenario group by calling the scenarios() function.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=scenariosCallFirstPart]
include::../examples/jest-es2015/sum.test.js[tags=scenariosCallSecondPart]
----

. The first parameter is the group name, it identifies your scenario within the report.
    - You can use a "namespace" or "java package" naming with dots to introduce a hierarchy that will be presented in the html5 report (eg: analytics.funnels.tickets_sales)
. The second parameter is the stage class you will create in the next step
. The last parameter is a function that takes an object containing the given(), when(), then() methods and returns the scenarios object.

=== Create a Stage class

You now have to create a "Stage" class that extends the Stage base class.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=SumStage]
----

A stage class contains multiple step methods that can be called in a scenario and that will appear in the report.
Step methods are the heart of JsGiven. The test initialization, execution and assertions **must** be implemented within step methods.

Every non-static method of a stage class that returns the stage instance (**this**) can be used as a step method.

[WARNING]
.Step methods must return the **this** reference!
====
This way JsGiven knowns which methods should be included in the report. Internal private methods usually do not return this.

Since there are is no concept of private methods in JavaScript, this is a major difference from JGiven.
====

There are no further requirements.

[NOTE]
.In addition, a step method should be written in snake_case
====
This way JsGiven knows the correct casing of each word of the step.
====

=== Write your first scenario

Now you can write your first scenario

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=scenarios]
----

=== Execute your scenario

You can execute your scenario by running your test runner as you usually run the tests.

----
$ jest
 PASS  ./sum.test.js
  sum
    ✓ Two numbers can be added (9ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.7s, estimated 1s
Ran all test suites.
----

== Report generation

JsGiven produces internal reports in JSON, that are not meant to be presented to users.

JsGiven converts these internal reports to a fully usable JGiven report.

=== Setting up pretest & posttest npm scripts

Due to the parallel nature of some test runners (Jest & Ava), there is no simple way to remove the internal reports before running tests & generate the html5 report at the end.

Therefore, you have to set up pretest & posttest npm scripts that will :

- Clean the internal reports before starting the tests.
- Generate the html5 report after the tests have run.

You have to include the following two tasks in you *package.json* file:

[source, json]
----
"scripts": {
  "pretest": "jsgiven clean",
  "posttest": "jsgiven report"
}
----

The *jsgiven* command is a CLI command tool provided by the module.

== Stages and state sharing

In the previous example you have included all step methods in the same class.
While this is a simple solution, it's often suitable to have several stage classes.

=== Create Given/When/Then Stage classes

JsGiven allows to use 3 Stage classes.

You can declare the classes in your scenario

[source, js, indent=0]
----
include::../examples/jest-es2015/sum-multiple-stages.test.js[tags=SumMultipleStagesScenarioDeclaration]
----

And use all the methods of each stage in the given(), when(), then() chains:

[source, js, indent=0]
----
include::../examples/jest-es2015/sum-multiple-stages.test.js[tags=SumMultipleStagesScenario]
----

=== Sharing state between stages

Very often it is necessary to share state between steps.
As long as the steps are implemented in the same Stage class you can just use the fields of the Stage class.
But what can you do if your steps are defined in different Stage classes?

In this case you just define the same field in both Stage classes.
Both fields also have to be annotated with the special decoration @State to tell JsGiven that this field will be used for state sharing between stages.

The values of these fields are shared between all stages that have the same field with the @Stage decoration.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum-multiple-stages.test.js[tags=SumStages]
----

=== Babel configuration for state sharing between stages

In order to use state sharing, you have to include the following babel transform plugins in your .babelrc :

[source, json, indent=0]
----
include::../examples/jest-es2015/.babelrc[]
----

== Parameterized steps

**TODO**

== Parameterized scenarios

**TODO**

== Using JsGiven

=== Supported Test runners

JsGiven supports the following test runners :

- https://facebook.github.io/jest/[Jest]
- https://mochajs.org/[Mocha]
- https://jasmine.github.io/[Jasmine]
- https://github.com/avajs/ava[Ava]
- http://www.protractortest.org/#/[Protractor]

JsGiven is tested internally using those frameworks image:https://travis-ci.org/jsGiven/jsGiven.svg?branch=master["Build Status", link="https://travis-ci.org/jsGiven/jsGiven"]

=== Type checkers

==== With Flow

JsGiven includes build-in support for the https://flow.org/[Flow] type checker.<commit_msg>docs(user-guide): Add documentation on parameterized steps<commit_after>:source-highlighter: pygments
:icons: font
:nofooter:
:docinfo: shared,private

= JsGiven User Guide
:toc: left
:toclevels: 5

== Introduction

JsGiven is a JavaScript library that helps you to design a high-level, domain-specific language for writing BDD scenarios.
You still use your favorite javascript test runner, your favorite assertion library and mocking library for writing your test implementations, but you use JsGiven to write a readable abstraction layer on top of it.

It's a JavaScript port of http://jgiven.org[JGiven] (written in Java).
JsGiven keeps the JGiven philosophy, concepts and uses its html5 reporting tool.

== Installation

JsGiven is released on https://www.npmjs.com/[NPM] and can be installed with both NPM & Yarn.

JsGiven should usually be installed as a https://docs.npmjs.com/files/package.json#devdependencies[devDependency] as it's not directly contributing as project dependency.

----
$ yarn add -D js-given <1>
$ npm install --save-dev js-given <2>
----
<1> With https://yarnpkg.com[Yarn]
<2> With https://www.npmjs.com/[NPM]

== Getting started

=== Importing jsGiven

JsGiven components are available as https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export[named exports] of the 'js-given' module.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=ImportJsGiven]
----

=== Set up JsGiven

JsGiven needs to be setup in each test source file by calling a setup function.

[NOTE]
It is necessary to do this in each test source file as some tests frameworks (Jest and probably Ava) actually run each test source file in a worker process in order to get parallel execution of tests.

==== For Rspec inspired frameworks (Jest, Mocha, Jasmine, Protractor)

In frameworks inspired by RSpec, JsGiven must be setup by calling the setupForRspec() function.
This function takes the describe and the it function from the test framework.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=setupForRspec]
----

==== For Ava framework

In Ava, JsGiven must be setup by calling the setupForAva() function.
This function takes the describe and the it function from the test framework.

[source, js, indent=0]
----
include::../js-given/spec/demo.spec.js[tags=setupForAva]
----

=== Create a scenario group

First of all you create a scenario group by calling the scenarios() function.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=scenariosCallFirstPart]
include::../examples/jest-es2015/sum.test.js[tags=scenariosCallSecondPart]
----

. The first parameter is the group name, it identifies your scenario within the report.
    - You can use a "namespace" or "java package" naming with dots to introduce a hierarchy that will be presented in the html5 report (eg: analytics.funnels.tickets_sales)
. The second parameter is the stage class you will create in the next step
. The last parameter is a function that takes an object containing the given(), when(), then() methods and returns the scenarios object.

=== Create a Stage class

You now have to create a "Stage" class that extends the Stage base class.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=SumStage]
----

A stage class contains multiple step methods that can be called in a scenario and that will appear in the report.
Step methods are the heart of JsGiven. The test initialization, execution and assertions **must** be implemented within step methods.

Every non-static method of a stage class that returns the stage instance (**this**) can be used as a step method.

[WARNING]
.Step methods must return the **this** reference!
====
This way JsGiven knowns which methods should be included in the report. Internal private methods usually do not return this.

Since there are is no concept of private methods in JavaScript, this is a major difference from JGiven.
====

There are no further requirements.

[NOTE]
.In addition, a step method should be written in snake_case
====
This way JsGiven knows the correct casing of each word of the step.
====

=== Write your first scenario

Now you can write your first scenario

[source, js, indent=0]
----
include::../examples/jest-es2015/sum.test.js[tags=scenarios]
----

=== Execute your scenario

You can execute your scenario by running your test runner as you usually run the tests.

----
$ jest
 PASS  ./sum.test.js
  sum
    ✓ Two numbers can be added (9ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.7s, estimated 1s
Ran all test suites.
----

== Report generation

JsGiven produces internal reports in JSON, that are not meant to be presented to users.

JsGiven converts these internal reports to a fully usable JGiven report.

=== Setting up pretest & posttest npm scripts

Due to the parallel nature of some test runners (Jest & Ava), there is no simple way to remove the internal reports before running tests & generate the html5 report at the end.

Therefore, you have to set up pretest & posttest npm scripts that will :

- Clean the internal reports before starting the tests.
- Generate the html5 report after the tests have run.

You have to include the following two tasks in you *package.json* file:

[source, json]
----
"scripts": {
  "pretest": "jsgiven clean",
  "posttest": "jsgiven report"
}
----

The *jsgiven* command is a CLI command tool provided by the module.

== Stages and state sharing

In the previous example you have included all step methods in the same class.
While this is a simple solution, it's often suitable to have several stage classes.

=== Create Given/When/Then Stage classes

JsGiven allows to use 3 Stage classes.

You can declare the classes in your scenario

[source, js, indent=0]
----
include::../examples/jest-es2015/sum-multiple-stages.test.js[tags=SumMultipleStagesScenarioDeclaration]
----

And use all the methods of each stage in the given(), when(), then() chains:

[source, js, indent=0]
----
include::../examples/jest-es2015/sum-multiple-stages.test.js[tags=SumMultipleStagesScenario]
----

=== Sharing state between stages

Very often it is necessary to share state between steps.
As long as the steps are implemented in the same Stage class you can just use the fields of the Stage class.
But what can you do if your steps are defined in different Stage classes?

In this case you just define the same field in both Stage classes.
Both fields also have to be annotated with the special decoration @State to tell JsGiven that this field will be used for state sharing between stages.

The values of these fields are shared between all stages that have the same field with the @Stage decoration.

[source, js, indent=0]
----
include::../examples/jest-es2015/sum-multiple-stages.test.js[tags=SumStages]
----

=== Babel configuration for state sharing between stages

In order to use state sharing, you have to include the following babel transform plugins in your .babelrc :

[source, json, indent=0]
----
include::../examples/jest-es2015/.babelrc[]
----

== Parameterized steps

Step methods can have parameters.
Parameters are formatted in reports by using the toString() method, applied to the arguments.

The formatted arguments are added to the end of the step description.

[source, js, indent=0]
----
given().the_ingredient( "flour" ); // Given the ingredient flour
given().multiple_arguments( 5, 6 ); // Given multiple arguments 5 6
----

=== Parameters within a sentence

To place parameters within a sentence instead the end of the sentence you can use the $ character.

[source, js, indent=0]
----
given().$_eggs( 5 );
----

In the generated report $ is replaced with the corresponding formatted parameter. So the generated report will look as follows:

[source, js, indent=0]
----
Given 5 eggs
----

If there are more parameters than $ characters, the remaining parameters are added to the end of the sentence.

If a $ should not be treated as a placeholder for a parameter, but printed verbatim, you can write $$, which will appear as a single $ in the report.

[source, js, indent=0]
----
given().$$_$( 5); // Given $ 5
----

== Parameterized scenarios

**TODO**

== Using JsGiven

=== Supported Test runners

JsGiven supports the following test runners :

- https://facebook.github.io/jest/[Jest]
- https://mochajs.org/[Mocha]
- https://jasmine.github.io/[Jasmine]
- https://github.com/avajs/ava[Ava]
- http://www.protractortest.org/#/[Protractor]

JsGiven is tested internally using those frameworks image:https://travis-ci.org/jsGiven/jsGiven.svg?branch=master["Build Status", link="https://travis-ci.org/jsGiven/jsGiven"]

=== Type checkers

==== With Flow

JsGiven includes build-in support for the https://flow.org/[Flow] type checker.
{'fraction_non_alphanumeric': 0.09793036867193629, 'fraction_numerical': 0.009050865866167863, 'mean_word_length': 4.037689969604863, 'pattern_counts': {'":': 6, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 24, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3195087', 'n_tokens_mistral': 4892, 'n_tokens_neox': 4545, 'n_words': 2124}