mocha-behavior-tree
TypeScript icon, indicating that this package has built-in type declarations

1.0.2 • Public • Published

mocha-behavior-tree

Hierarchical step definition for Mocha

NPM License

Easily defining multiple next steps to test from the current state with a tree structure hierarchically. This is useful for performing tests in a natural sequence of actions and reducing duplication of test code.

Install

npm i -D mocha mocha-behavior-tree

Usage

const { step } = require('mocha-behavior-tree')
 
describe('test',                                   //Mocha's describe
  step('root step', () => foo,                      //root : passing value to next step
    step('step 1', foo => { },                      //depth1 : bypass the value when return nothing
      step('step 1.1', foo => { /* assertion */ }),   //depth2
      step('step 1.2', async foo => await bar,       //depth2 : async step
        step('step 1.2.1', bar => { /* assertion */ }), //depth3
        ...
      ),       
      ...
    )
  )    
)

Scenario, Given, When, Then

scenario is proxy for describe, and given,when,then,and are proxies for step, just adding BDD style keywords as prefix to the step name.

Below test case

const assert = require('assert')
const { scenario, given, and, then, when } = require('mocha-behavior-tree')
 
scenario('User purchases products',
  given('User login',                         () => console.log('1. User login'),
    and('List products',                        () => console.log('2. List products'),
      when('Add the first product to cart',       () => console.log('3. Add the first product to cart'),
        then('The product is in the cart',          () => assert(true))
      ),
      when('Puchase the first products',          () => console.log('3. Puchase the first products'),
        then('An order for the product is created', () => assert(true))
      ),
      when('Select all products on the page',     () => console.log('3. Select all products on the page'),
        then('all products are selected',           () => assert(true)),
        and('Add selected products to cart',        () => console.log('4. Add selected products to cart'),
          then('The products are in the cart',        () => assert(true))
        ),
        and('Puchase selected products',            () => console.log('4. Puchase selected products'),
          then('Orders for the products are created', () => assert(true))
        ),
      ),
    )
  )
)
 

is executed as follows:

// running each step route of the trees from the root to the leaf
 
  Scenario: User purchases products
    Given: User login
      And: List products
        When: Add the first product to cart
          1. User login
          2. List products
          3. Add the first product to cart
          ✓ Then: The product is in the cart
          
        When: Puchase the first products
          1. User login
          2. List products
          3. Puchase the first products
          ✓ Then: An order for the product is created
          
        When: Select all products on the page
          1. User login
          2. List products
          3. Select all products on the page
          ✓ Then: all products are selected
          
          And: Add selected products to cart
            1. User login
            2. List products
            3. Select all products on the page
            4. Add selected products to cart
            ✓ Then: The products are in the cart
            
          And: Puchase selected products
            1. User login
            2. List products
            3. Select all products on the page
            4. Puchase selected products
            ✓ Then: Orders for the products are created
 
  5 passing 

For integration with other test codes (or some IDE plugins), you can also do this:

describe('Shop tests', () => {
  describe('User', () => {
    // Note that the scenario is called 'inside' the callback function, 
    // not passed to describe as a callback function.
    scenario('User purchases products', 
      given('User login', () => { /*...*/ },
        /*...*/
      )
    )
  })
})

Passing values to the next Step

Multiple values can be passed to next step within object key-values

describe('test multiple value passing',
  step('pass 1, 2', 
    () => ({ a:1, b:2 }),
    step('passed value is 1, 2', 
      ({a, b}) => {
        expect(a).to.equals(1)
        expect(b).to.equals(2)
      }
    )
  )
)

Async testing

when('products are listed in the page', 
  () => getProductsPage({ page: 1, size: 20 }).then(result => ({ page: result })), // returns promise
  then('Add the first product to cart', 
    ({ page }) => {
      // got resolved value here
    }
  )
)
when('products are listed in the page', 
  async () => ({ page : await getProductsPage({ page: 1, size: 20 }) }), // async/await
  then('Add the first product to cart', 
    ({ page }) => {
      // got resolved value here
    })
)

Use function name as step name

Step name can be omitted. then function name will be used to step name

describe('User purchases products',
  given(function user () { 
      //... 
    },
    and(function user_logged_in (user) { 
        //... 
      },
      and(function products_are_listed_in_the_page (user) { /*...*/ },
        when(function add_the_first_product_to_cart ({ user, page }) { /*...*/ },
          then(function the_product_is_in_the_cart ({ cart, firstProduct }) { /*...*/ })
        )
      )
    )
  )
)

result :

User purchases products
  Given: user
    And: user_logged_in
      And: products_are_listed_in_the_page
        When: add_the_first_product_to_cart
          ✓ Then: the_product_is_in_the_cart

This can be done more Cucumber way

// steps.js
module.exports = {
  'user': () => { ... },
  'user logged in': () => { ... },
  'products are listed in the page': () => { ... },
  'add the first product to cart': () => { ... },
  'the product is in the cart': () => { ... },
}
 
//test.js
const _ = require('./steps')
describe('User purchases products',() => {
  given(_['user'],
    and(_['user logged in'],
      and(_['products are listed in the page'],
        when(_['add the first product to cart'],
          then(_['the product is in the cart'])
        )
      )
    )
  )()
})

More usages

You can find out more examples in the library's test cases

Package Sidebar

Install

npm i mocha-behavior-tree

Weekly Downloads

0

Version

1.0.2

License

MIT

Unpacked Size

10.6 kB

Total Files

5

Last publish

Collaborators

  • neocjmix