Coder Social home page Coder Social logo

bdd-lazy-var's Introduction

BDD + lazy variable definition (aka rspec)

BDD Lazy Var NPM version Build Status Maintainability BDD Lazy Var Join the chat at https://gitter.im/bdd-lazy-var/Lobby

Provides "ui" for testing frameworks such as mocha, jasmine and jest which allows to define lazy variables and subjects.

Purpose

The old way

describe('Suite', function() {
  var name;

  beforeEach(function() {
    name = getName();
  });

  afterEach(function() {
    name = null;
  });

  it('uses name variable', function() {
    expect(name).to.exist;
  });

  it('does not use name but anyway it is created in beforeEach', function() {
    expect(1).to.equal(1);
  });
});

Why should it be improved?

Because as soon as amount of your tests increase, this pattern became increasingly difficult. Sometimes you will find yourself jumping around spec files, trying to find out where a given variable was initially defined. Or even worst, you may run into subtle bugs due to clobbering variables with common names (e.g. model, view) within a given scope, failing to realize they had already been defined. Furthermore, declaration statements in describe blocks will start looking something like:

var firstVar, secondVar, thirdVar, fourthVar, fifthVar, ..., nthVar

This is ugly and hard to parse. Finally, you can sometimes run into flaky tests due to "leaks" - test-specific variables that were not properly cleaned up after each case.

The new, better way

In an attempt to address these issues, I had with my e2e tests, I decided to create this library, which allows to define suite specific variables in more elegant way. So the original code above looks something like this:

describe('Suite', () => {
  def('name', () => `John Doe ${Math.random()}`);

  it('defines `name` variable', () => {
    expect($name).to.exist
  });

  it('does not use name, so it is not created', () => {
    expect(1).to.equal(1);
  });
});

Why the new way rocks

Switching over to this pattern has yielded a significant amount of benefits for us, including:

No more global leaks

Because lazy vars are cleared after each test, we didn't have to worry about test pollution anymore. This helped ensure isolation between our tests, making them a lot more reliable.

Clear meaning

Every time I see a $<variable> reference in my tests, I know where it's defined. That, coupled with removing exhaustive var declarations in describe blocks, have made even my largest tests clear and understandable.

Lazy evaluation

Variables are instantiated only when referenced. That means if you don't use variable inside your test it won't be evaluated, making your tests to run faster. No useless instantiation any more!

Composition

Due to laziness we are able to compose variables. This allows to define more general varibles at the top level and more specific at the bottom:

describe('User', function() {
  subject('user', () => new User($props))

  describe('when user is "admin"', function() {
    def('props', () => ({ role: 'admin' }))

    it('can update articles', function() {
      // user is created with property role equal "admin"
      expect($user).to....
    })
  })

  describe('when user is "member"', function() {
    def('props', () => ({ role: 'member' }))

    it('cannot update articles', function() {
      // user is created with property role equal "member"
      expect($user).to....
    })
  })
})

Tests reusage

Very often you may find that some behavior repeats (e.g., when you implement Adapter pattern), and you would like to reuse tests for a different class or object. To do this Wiki of Mocha.js recommend to move your tests into separate function and call it whenever you need it.

I prefer to be more explicit in doing this, that's why created few helper methods:

  • sharedExamplesFor - defines a set of reusable tests. When you call this function, it just stores your tests
  • includeExamplesFor - runs previously defined examples in current context (i.e., in current describe)
  • itBehavesLike - runs defined examples in nested context (i.e., in nested describe)

sharedExamplesFor defines shared examples in the scope of the currently defining suite. If you call this function outside describe (or context) it defines shared examples globally.

WARNING: files containing shared examples must be loaded before the files that use them.

Scenarios

shared examples group included in two groups in one file
sharedExamplesFor('a collection', () => {
  it('has three items', () => {
    expect($subject.size).to.equal(3)
  })

  describe('#has', () => {
    it('returns true with an item that is in the collection', () => {
      expect($subject.has(7)).to.be.true
    })

    it('returns false with an item that is not in the collection', () => {
      expect($subject.has(9)).to.be.false
    })
  })
})

describe('Set', () => {
  subject(() => new Set([1, 2, 7]))

  itBehavesLike('a collection')
})

describe('Map', () => {
  subject(() => new Map([[2, 1], [7, 5], [3, 4]]))

  itBehavesLike('a collection')
})
Passing parameters to a shared example group
sharedExamplesFor('a collection', (size, existingItem, nonExistingItem) => {
  it('has three items', () => {
    expect($subject.size).to.equal(size)
  })

  describe('#has', () => {
    it('returns true with an item that is in the collection', () => {
      expect($subject.has(existingItem)).to.be.true
    })

    it('returns false with an item that is not in the collection', () => {
      expect($subject.has(nonExistingItem)).to.be.false
    })
  })
})

describe('Set', () => {
  subject(() => new Set([1, 2, 7]))

  itBehavesLike('a collection', 3, 2, 10)
})

describe('Map', () => {
  subject(() => new Map([[2, 1]]))

  itBehavesLike('a collection', 1, 2, 3)
})
Passing lazy vars to a shared example group

There are 2 ways how to pass lazy variables:

  • all variables are inherited by nested contexts (i.e., describe calls), so you can rely on variable name, as it was done with subject in previous examples
  • you can pass variable definition using get.variable helper
sharedExamplesFor('a collection', (collection) => {
  def('collection', collection)

  it('has three items', () => {
    expect($collection.size).to.equal(1)
  })

  describe('#has', () => {
    it('returns true with an item that is in the collection', () => {
      expect($collection.has(7)).to.be.true
    })

    it('returns false with an item that is not in the collection', () => {
      expect($collection.has(9)).to.be.false
    })
  })
})

describe('Set', () => {
  subject(() => new Set([7]))

  itBehavesLike('a collection', get.variable('subject'))
})

describe('Map', () => {
  subject(() => new Map([[2, 1]]))

  itBehavesLike('a collection', get.variable('subject'))
})

Shortcuts

Very often we want to declare several test cases which tests subject's field or subject's behavior. To do this quickly you can use its or it without message:

Shortcuts example
describe('Array', () => {
  subject(() => ({
    items: [1, 2, 3],
    name: 'John'
  }))

  its('items.length', () => is.expected.to.equal(3)) // i.e. expect($subject.items.length).to.equal(3)
  its('name', () => is.expected.to.equal('John')) // i.e. expect($subject.name).to.equal('John')

  // i.e. expect($subject).to.have.property('items').which.has.length(3)
  it(() => is.expected.to.have.property('items').which.has.length(3))
})

Also it generates messages for you based on passed in function body. The example above reports:

  Array
    ✓ is expected to have property('items') which has length(3)
    items.length
      ✓ is expected to equal(3)
    name
      ✓ is expected to equal('John')

Note: if you use mocha and chai make sure that defines global.expect = chai.expect, otherwise is.expected will throw error that context.expect is undefined.

Installation

npm install bdd-lazy-var --save-dev
Mocha.js

Command line

mocha -u bdd-lazy-var/global

In JavaScript

See Using Mocha programatically

const Mocha = require('mocha');

const mocha = new Mocha({
  ui: 'bdd-lazy-var/global' // bdd-lazy-var or bdd-lazy-var/getter
});

mocha.addFile(...)
mocha.run(...)

// !!! Important the next code should be written in a separate file
// later you can either use `get` and `def` as global functions
// or export them from corresponding module
const { get, def } = require('bdd-lazy-var/global');

describe('Test', () => {
  // ...
})

Using karma (via karma-mocha npm package)

Note requires karma-mocha ^1.1.1

So, in karma.config.js it looks like this:

module.exports = function(config) {
  config.set({
    // ....
    client: {
      mocha: {
        ui: 'bdd-lazy-var/global',
        require: [require.resolve('bdd-lazy-var/global')]
      }
    }
  });
}
Jasmine.js

Command line

jasmine --helper=node_modules/bdd-lazy-var/global.js

or using spec/spec_helper.js

require('bdd-lazy-var/global');

// ... other helper stuff

and then

jasmine --helper=spec/*_helper.js

In JavaScript

When you want programatically run jasmine

require('jasmine-core');

// !!! Important the next code should be written in a separate file
// later you can either use `get` and `def` as global functions
// or export them from corresponding module
const { get, def } = require('bdd-lazy-var/global');

describe('Test', () => {
  // ...
})

Using karma (via karma-jasmine npm package)

So, in karma.config.js it looks like this:

module.exports = function(config) {
  config.set({
    // ....
    files: [
      'node_modules/bdd-lazy-var/global.js',
      // ... your specs here
    ]
  });
}
Jest

Command line

Use Jest as usually if you export get and def from corresponding module

jest

In case you want to use global get and def

jest --setupTestFrameworkScriptFile bdd-lazy-var/global

In JavaScript

// later you can either use `get` and `def` as global functions
// or export them from relative module
const { get, def } = require('bdd-lazy-var/global');

Dialects

bdd-lazy-var provides 3 different dialects:

  • access variables by referencing $<variableName> (the recommended one, available by requiring bdd-lazy-var/global)
  • access variables by referencing get.<variableName> (more strict, available by requiring bdd-lazy-var/getter)
  • access variables by referencing get('<variableName>') (the most strict and less readable way, available by requiring bdd-lazy-var)

All are bundled as UMD versions. Each dialect is compiled in a separate file and should be required or provided for testing framework.

Aliases

In accordance with Rspec's DDL, context, xcontext, and fcontext have been aliased to their related describe commands for both the Jest and Jasmine testing libraries. Mocha's BDD interface already provides this keyword.

The Core Features

  • lazy instantiation, allows variable composition
  • automatically cleaned after each test
  • accessible inside before/beforeAll, after/afterAll callbacks
  • named subjects to be more explicit
  • ability to shadow parent's variable
  • variable inheritance with access to parent variables
  • supports typescript

For more information, read the article on Medium.

TypeScript Notes

It's also possible to use bdd-lazy-var with TypeScript. The best integrated dialects are get and getter. To do so, you need either include corresponding definitions in your tsconfig.json or use ES6 module system.

tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true
  },
  "include": [
    "src/**/*",
    "node_modules/bdd-lazy-var/index.d.ts" // for `get('<variableName>')` syntax
    // or
    "node_modules/bdd-lazy-var/getter.d.ts" // for `get.<variableName>` syntax
  ]
}
ES6 module system
import { get, def } from 'bdd-lazy-var'
// or
import { get, def } from 'bdd-lazy-var/getter'

describe('My Test', () => {
  // ....
})

In this case TypeScript loads corresponding declarations automatically

It's a bit harder to work with global dialect. It creates global getters on the fly, so there is no way to let TypeScript know something about these variables, thus you need to declare them manually.

TypeScript and global dialect
import { def } from 'bdd-lazy-var/global'

describe('My Test', () => {
  declare let $value: number // <-- need to place this declarations manually
  def('value', () => 5)

  it('equals 5', () => {
    expect($value).to.equal(5)
  })
})

As with other dialects you can either use import statements to load typings automatically or add them manually in tsconfig.json

Examples

Test with subject
describe('Array', () => {
  subject(() => [1, 2, 3]);

  it('has 3 elements by default', () => {
    expect($subject).to.have.length(3);
  });
});
Named subject
describe('Array', () => {
  subject('collection', () => [1, 2, 3]);

  it('has 3 elements by default', () => {
    expect($subject).to.equal($collection);
    expect($collection).to.have.length(3);
  });
});
`beforeEach` and redefined subject
describe('Array', () => {
  subject('collection', () => [1, 2, 3]);

  beforeEach(() => {
    // this beforeEach is executed for tests of suite with subject equal [1, 2, 3]
    // and for nested describe with subject being []
    $subject.push(4);
  });

  it('has 3 elements by default', () => {
    expect($subject).to.equal($collection);
    expect($collection).to.have.length(3);
  });

  describe('when empty', () => {
    subject(() => []);

    it('has 1 element', () => {
      expect($subject).not.to.equal($collection);
      expect($collection).to.deep.equal([4]);
    });
  });
});
Access parent variable in child variable definition
describe('Array', () => {
  subject('collection', () => [1, 2, 3]);

  it('has 3 elements by default', () => {
    expect($subject).to.equal($collection);
    expect($collection).to.have.length(3);
  });

  describe('when empty', () => {
    subject(() => {
      // in this definition `$subject` references parent $subject (i.e., `$collection` variable)
      return $subject.concat([4, 5]);
    });

    it('is properly uses parent subject', () => {
      expect($subject).not.to.equal($collection);
      expect($collection).to.deep.equal([1, 2, 3, 4, 5]);
    });
  });
});

Want to help?

Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on guidelines for contributing

License

MIT License

bdd-lazy-var's People

Contributors

christian-schulze avatar iain-b avatar lpmi-13 avatar mrleebo avatar pmoons avatar renovate-bot avatar renovate[bot] avatar semantic-release-bot avatar stalniy avatar vonagam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

bdd-lazy-var's Issues

ReferenceError: $subject is not defined

I must be doing something silly, but the following doesn't work for me, taken directly from the example:

my_spec.js

const chai = require('chai')
const expect = chai.expect
const Mocha = require('mocha');

const mocha = new Mocha({
  ui: 'bdd-lazy-var/global'
});

const { get, def } = require('bdd-lazy-var/global');

describe('Array', () => {
  subject(() => [1, 2, 3]);

  it('has 3 elements by default', () => {
    expect($subject).to.have.length(3);
  });
});

Test result

./node_modules/.bin/mocha -u bdd-lazy-var test/my_spec.js

  Array
    1) has 3 elements by default


  0 passing (7ms)
  1 failing

  1) Array
       has 3 elements by default:
     ReferenceError: $subject is not defined
      at Context.it (test/my_spec.js:14:12)

Using:

node v9.11.1

"bdd-lazy-var": "2.2.3",
"chai": "4.1.2",
"mocha": "5.1.1",

Subject not correctly defined in child contexts

I'm trying to upgrade from 1.3.1 to 2.1.2 and I'm having some issues. This is similar to an issue I created earlier but I'll leave it to the maintainer to determine if it's a duplicate or not.

It seems that if I inherit from the subject in one context this function is applied again in a child of this context. I've put comments on an example below but the crux is that if I define a subject in a context subject(() => subject().foo) then in child contexts which don't explicitly define the subject it seems it is defined as subject().foo.foo.

I'm happy to help out with a fix but I'd need some pointers to where I might look in the code.

describe('testing 2', () => {
    subject(() => ({ ...get('props') }));

    def('props', () => ({
      numberOfRows: get('numberOfRows'),
      header: get('header'),
    }));
    def('numberOfRows', 1);
    def('header', 'asdfasdf');

    context('the rows', () => {
      subject(() => subject().numberOfRows);

      // fails: expected undefined to deeply equal 0
      context('where there are now rows', () => {
        def('numberOfRows', 0);
        // behaves as if I have defined subject _again_ as
        // subject(() => subject().numberOfRows);
        // i.e. subject().numberOfRows.numberOfRows ?
        // defining the subject as follows fixes this
        // subject(() => subject());

        it('renders no rows', () => {
          expect(subject()).to.eql(0);
        });
      });

      // passes
      context('where there is one row ', () => {
        subject(() => subject()); // without this it fails
        def('numberOfRows', 1);
        // commenting out the above, the test passes as seemingly the subject is not redefined in
        // that case.

        it('renders the correct rows', () => {
          expect(subject()).to.eql(1);
        });
      });

      // fails: expected undefined to deeply equal 3
      context('where there are multiple rows', () => {
        def('numberOfRows', 3);

        it('renders multiple rows', () => {
          expect(subject()).to.eql(3);
        });
      });
    });
  });

Need help getting the getter syntax to work in mocha

Hey. I really like the idea of this library, and have been wanting something like it for a while. Unfortunately, I can't quite seem to get it working in the way I want.

I'd like to use the get. syntax with mocha. I'm using the -u bdd-lazy-var flag when running mocha. Is that the right way to do that? In the docs, I see different usage here, but I'm not sure where I'd put that in my app, since I'm not currently doing new Mocha() anywhere.

Using in-line syntax results in error: context.expect is not a function

Trying to use the new inline syntax like this:

describe('myFunction', () => {
  def('param', true);
  
  subject('fireFunction', () => myFunction($param));
  
  context('when the param is false', () => {
    def('param', false);

    it(() => is.expected.to.eql(false));
  });
});

results in the following error when running the test:

TypeError: context.expect is not a function
      at Object.get expected [as expected] (node_modules/bdd-lazy-var/global.js:420:24)
      at Context.<anonymous> (output/webpack:/myFunction.test.js:198:19)

Running the test using the older syntax works fine:

it('returns false', () => {
  expect($fireFunction).to.eql(false);
});

Using mocha + bdd-lazy-var. Any thoughts?

Any chance to make it work with webdriverio?

I was trying to make it work but no success...
I know they have this https://github.com/webdriverio/wdio-mocha-framework/blob/master/lib/adapter.js#L6
But even when I add bdd-lazy-var to the INTERFACES it doesn't work:

ERROR: Cannot read property 'Symbol(__currentVariableStack)' of undefined
chrome
Type    at Function.fromStack (_PROJECT_/node_modules/bdd-lazy-var/global.js:283:26)
    at Function.evaluate (_PROJECT_/node_modules/bdd-lazy-var/global.js:267:31)
    at get$$1 (_PROJECT_//node_modules/bdd-lazy-var/global.js:356:23)
    at get$$1 (_PROJECT_//node_modules/bdd-lazy-var/global.js:708:22)

Allow to define multiple variables and extract them respectively

Example:

describe('Suite', function() {
  const { fullName, firstName, lastName } = def.vars({
      firstName: 'BDD',

      lastName: 'Lazy variables',

      fullName() {
        return `${firstName} ${lastName}`;
      }
  });

  it('computes variables', function() {
    expect(fullName).to.equal('BDD Lazy variables');
  });
})

This way library won't pollute global scope with $varName getters.

This is a breaking change as I'm going to increase supported node version to node 4.x (or 6.x) and remove ui for global variables and getters on get function.

$subject become undefined in watch mode

When mocha is ran with -w (watch mode), the first time $subject is accessible, but after the first watch event triggers and test is rerun, $subject become undefined.

Lazy vars undefined when running multiple test files

Something broke between 1.1.4 and 1.1.5.

I'm having a heck of a time nailing this down to a specific condition, but when I run a single test, everything works just fine:

$ gulp test --name ingest-endpoints-test
[11:38:36] Using gulpfile /workplace/exm-admin-tool/gulpfile.js
[11:38:36] Starting 'test'...


  IngestEndpointsResponse
    ✓ extends BulkResponse
    on the default object
      toBulkResponseList
        ✓ has a show_url


  2 passing (9ms)

[11:38:38] Finished 'test' after 2.03 s

But if I run multiple tests, I get failures:

$ gulp test --name ingest-endpoints
[11:38:56] Using gulpfile /workplace/exm-admin-tool/gulpfile.js
[11:38:56] Starting 'test'...


  IngestEndpointsUpload
    ✓ is a Bulk subclass
    on the default object
      validate
        ✓ has validation errors
      group validation
        ✓ has a group missing attribute error
      zip file validation
        ✓ has a group missing attribute error

  IngestEndpointsResponse
    ✓ extends BulkResponse
    on the default object
      toBulkResponseList
        1) has a show_url


  5 passing (19ms)
  1 failing

  1) IngestEndpointsResponse on the default object toBulkResponseList has a show_url:
     ReferenceError: $subject is not defined
      at Context.<anonymous> (ingest-endpoints-test.js:26:16)



[11:38:57] 'test' errored after 738 ms
[11:38:57] Error in plugin 'gulp-mocha'
Message:
    1 test failed.

Here's what my gulp task looks like:

var babel = require('babel-register')({
  presets: ['es2015'],
  ignore: [/node_modules/, /(templates|partials)\.js/]
});
var gulp = require('gulp');
var mocha = require('gulp-mocha');
var argv = require('yargs').argv;

gulp.task('test', function () {

  var wildcard = 'test/**/*.js'
  if (argv.name) {
    wildcard = 'test/**/*' + argv.name + '*.js'
  }

  // The larger timeout is because the bamboo server is awfully slow.
  var opts = {
    timeout: 5000,
    ui: 'bdd-lazy-var/global'
  };
  if(argv.reporter){
    opts.reporter = argv.reporter;
  }
  if(argv.reporterOptions){
    var fileNameArray = argv.reporterOptions.split('=');
    if(fileNameArray && fileNameArray.length){
      var fileName = fileNameArray.pop();
      if(fileName && fileName.length > 0){
        opts.reporterOptions = {
          mochaFile: fileName
        };
      }
    }
  }


  return gulp.src(wildcard, {read: false})
            // gulp-mocha needs filepaths so you can't have any plugins before it 
            .pipe(mocha(opts));
});

Add compatibility with mocha 6

This package does not seem to work with mocha 6. Up to mocha 5.2.0, everything is just fine. Mocha 6.0.2, however, produces the following error:

$ node_modules/mocha/bin/_mocha --ui bdd-lazy-var/global

  1) Uncaught error outside test suite

  0 passing (1ms)
  1 failing

  1) Uncaught error outside test suite:
     Uncaught TypeError: suite.hasOnly is not a function
      at Array.some (<anonymous>)
      at startup (bootstrap_node.js:204:16)
      at bootstrap_node.js:625:3

Running

node_modules/mocha/bin/_mocha --ui bdd

successfully runs the tests, though.

Allow for describe-local shared examples

Shared examples are global in 2.2.6. It would be nice to have them local to the describe block in which they are defined. Here is an example that should pass with local shared examples and does not pass with global shared examples:

describe('context 1', () => {
  sharedExamplesFor('a collection', () => {
    it('has three items', () => {
      expect($subject.size).to.equal(3);
    });

    describe('#has', () => {
      it('returns false with an an item that is not in the collection', () => {
        expect($subject.has(9)).to.be.false;
      });
    });
  });

  describe('Set', () => {
    subject(() => new Set([1, 2, 7]));

    itBehavesLike('a collection');
  });

  describe('Map', () => {
    subject(() => new Map([[2, 1], [7, 5], [3, 4]]));

    itBehavesLike('a collection');
  });
});

describe('context 2', () => {
  sharedExamplesFor('a collection', () => {
    it('has three items', () => {
      expect($subject.size).to.equal(3);
    });

    describe('#has', () => {
      it('returns true with an an item that is in the collection', () => {
        expect($subject.has(7)).to.be.true;
      });
    });
  });

  describe('Set', () => {
    subject(() => new Set([1, 2, 7]));

    itBehavesLike('a collection');
  });

  describe('Map', () => {
    subject(() => new Map([[2, 1], [7, 5], [3, 4]]));

    itBehavesLike('a collection');
  });
});

Upgrade dependency on mocha?

When trying to npm shrinkwrap I'm greeted with this:

npm ERR! Darwin 15.6.0
npm ERR! argv "/Users/dkreft/.nvm/versions/node/v6.3.1/bin/node" "/Users/dkreft/.nvm/versions/node/v6.3.1/bin/npm" "shrinkwrap" "--dev"
npm ERR! node v6.3.1
npm ERR! npm  v3.10.3

npm ERR! Problems were encountered
npm ERR! Please correct and try again.
npm ERR! peer invalid: mocha@^2.0.0, required by [email protected]

I'm using mocha-3.0.2 and everything seems to be working just fine with it.

$ npm view mocha version
3.0.2

Support for async definition

Hey, folks.
It would be nice to do async def, my issue is that I need to save instance cuz it triggers a lot of calcs.
Something like that usage:

`def "name" (done) ->

user = new User
name: "Todd"

name.save (e) ->
done(user)`

Does `it` or `its` work with Promise/async `subject`?

Love the library so far, thanks!

Had a question, though.

It doesn't seem something like this will work:

subject('foo', () => new Promise((res) => setTimeout(() => res('bar'), 1000)))

it(() => is.expected.to.eql('bar'))

I think I can change it to something like this, however:

it('equals bar', async () => expect(await $foo).to.eql('bar'))

but that feels like it defeats the purpose of using subject/it(() => ...).

I also don't want to (I don't think) make this change:

subject('foo', async () => await new Promise(...))

...because at some point I want to have what foo calls actually throw/reject, and to test that I need to not await the resolution first, I think. Since I'll have to do something like this:

it('blah', () => {
  await expect($foo).to.be.rejectedWith('error pattern')
})

bdd-lazy-var/rspec missing in 2.4.2

Hey, what happened to bdd-lazy-var/rspec (which was added per issue #18)?

dkreft@tmlappy:~/pomodoro> npm test

> [email protected] test /Users/dkreft/pomodoro
> NODE_ENV=test mocha

/Users/dkreft/pomodoro/node_modules/mocha/lib/mocha.js:214
      throw new Error('invalid interface "' + name + '"');
      ^

Error: invalid interface "bdd-lazy-var/rspec"
    at Mocha.ui (/Users/dkreft/pomodoro/node_modules/mocha/lib/mocha.js:214:13)
    at Object.<anonymous> (/Users/dkreft/pomodoro/node_modules/mocha/bin/_mocha:516:7)
    at Module._compile (module.js:641:30)
    at Object.Module._extensions..js (module.js:652:10)
    at Module.load (module.js:560:32)
    at tryModuleLoad (module.js:503:12)
    at Function.Module._load (module.js:495:3)
    at Function.Module.runMain (module.js:682:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:613:3
npm ERR! Test failed.  See above for more details.
dkreft@tmlappy:~/pomodoro> npm ls bdd-lazy-var
[email protected] /Users/dkreft/pomodoro
└── [email protected] 
dkreft@tmlappy:~/pomodoro> cat test/mocha.opts
--require babel-core/register
--require babel-polyfill
--ui bdd-lazy-var/rspec
--recursive

Maximum call stack size exceeded with named subjects

Hi!
I stumbled upon an issue with named subjects, when named subject from child context attempts to access parent subject via subject().

describe('Test', function() {
  subject('parent', () => { name: 'test' });

  describe('Child', () => {
    subject('child', () => subject().name);

    it('equals parent name', () => {
      expect(subject()).to.equal('test');
    });
  });
});
0 passing (278ms)
1 failing

1) Test Child equals parent name:
   RangeError: Maximum call stack size exceeded

There is a workaround to not use a named subject as a child or to access parent by name.

subject('child', () => $parent.name);
subject(() => subject().name);

Support for async definition

Hey, folks.
It would be nice to do async def, my issue is that I need to save instance cuz it triggers a lot of calcs.
Something like that usage:

def "name" (done) -> 

  user = new User 
    name: "Todd"

  name.save (e) -> 
    done(user)

Add eslint rule/plugin to handle $foo global vars

Requirements:

  • perceive all variables with name $* as defined
  • if onlyDefined option is set to true, then additionally check whether the lazy var is defined with def
  • if noDynamicName option is set to true, then rule will not allow to use dynamically defined lazy vars
  • allow to specify dialects (bdd, bdd/getter, bdd/global) to check defined lazy vars
  • adds its, def, subject, get, sharedExamplesFor, includeExamplesFor, itBehavesLike and is to global variables
  • this rule must play nice with no-undef rule or substitute it (implement its behavior inside)

TypeError: Cannot read property 'Symbol(__lazyVars)' of undefined

Hello!

Great library! We ran into the above error recently and we're not sure why or what the cause might be.

This occurs on v2.2.3 on line https://github.com/stalniy/bdd-lazy-var/blob/master/getter.js#L126

It appears that the context is undefined when it is passed from here: https://github.com/stalniy/bdd-lazy-var/blob/master/getter.js#L534

The issue appears to be that if the this.state.contexts is empty, this.currentContext is returning undefined which leads to the above error. https://github.com/stalniy/bdd-lazy-var/blob/master/getter.js#L545

Hopefully this is an easy fix.

Cheers!

Update: Just noticed that this appears to occur when we have a suite that does not use any def definitions. If we set the test focus to only the suites with def variables defined then everything works as expected.

Lazy variables initialized in unexpected order when `beforeEach` is used

I'm not sure how to properly describe this, but it looks like beforeEach is causing lazily-created objects to be built too soon and variables in nested contexts are ignored. Here's a test that I wrote to demonstrate the problem:

'use strict'

import { expect } from 'chai'

class UserProvidedValue {
  constructor(value) {
    this.value = value
  }

  doStuff() {
  }
}

describe('UserProvidedValue', () => {
  def('value', () => null)
  def('model', () => {
    console.log(`Building new model with ${ $value }`)
    return new UserProvidedValue($value)
  })

  describe('.doStuff()', () => {
    def('value', () => {
      console.log('making wrong value')
      return 'WRONG VALUE'
    })

    beforeEach(() => {
      // Commenting out this code will result in a successful run
      console.log('calling .doStuff()')
      $model.doStuff()
    })

    describe('the value', () => {
      subject(() => {
        console.log('calling $model.value')
        return $model.value
      })

      context('when the value is supplied', () => {
        def('value', () => {
          console.log('making right value')
          return 'right value'
        })

        it('has the right value', () => {
          expect($subject).to.equal($value)
        })
      })
    })
  })
})

Here's the output from this test:

  UserProvidedValue
    .doStuff()
      the value
        when the value is supplied
calling .doStuff()
making wrong value
Building new model with WRONG VALUE
calling $model.value
making right value
          1) has the right value


  0 passing (11ms)
  1 failing

  1) UserProvidedValue .doStuff() the value when the value is supplied has the right value:

      AssertionError: expected 'WRONG VALUE' to equal 'right value'
      + expected - actual

      -WRONG VALUE
      +right value

      at Context.<anonymous> (lazy-var-test.js:45:31)



[09:47:50] 'test' errored after 185 ms
[09:47:50] Error in plugin 'gulp-mocha'
Message:
    1 test failed.

Compare this to an analogous spec written in rspec:

class UserProvidedValue
  def initialize(value)
    @value = value
  end

  def value
    @value
  end

  def do_stuff
  end
end

describe "UserProvidedValue" do
  let(:value) { nil }
  let(:model) {
    puts "Building new model with #{ value }"
    UserProvidedValue.new(value)
  }

  describe '#do_stuff' do
    let(:value) {
      puts 'making wrong value'
      'WRONG VALUE'
    }

    before :each do
      puts "calling #do_stuff"
      model.do_stuff
    end

    describe 'the value' do
      subject {
        puts "calling model.value"
        model.value
      }

      context 'when the value is supplied' do
        let(:value) {
          puts 'making right value'
          'right value'
        }

        it 'has the right value' do
          expect(subject).to eql(value)
        end
      end
    end
  end
end

The rspec test behaves as expected:

 rspec -f d ~/Desktop/rspec-test.rb

UserProvidedValue
  #do_stuff
    the value
      when the value is supplied
calling #do_stuff
making right value
Building new model with right value
calling model.value
        has the right value

Finished in 0.00134 seconds (files took 0.12593 seconds to load)
1 example, 0 failures

Does not work with Jest `describe.each`

I have a spec that makes use of the describe.each functionality introduced in Jest v23. As soon as I add a call to def to introduce a variable with bdd-lazy-var it causes an error describe.each is not a function in that test file. Seems like bdd-lazy-var is doing something to interfere with the function but I wouldn't know what.

I'm using the latest version of bdd-lazy-var and Typescript 3.1.6

Dependency deprecation warning: babel-preset-es2015 (npm)

On registry https://registry.npmjs.org/, the "latest" version (v6.24.1) of dependency babel-preset-es2015 has the following deprecation notice:

🙌 Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!

Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.

Please take the actions necessary to rename or substitute this deprecated package and commit to your base branch. If you wish to ignore this deprecation warning and continue using babel-preset-es2015 as-is, please add it to your ignoreDeps array in Renovate config before closing this issue, otherwise another issue will be recreated the next time Renovate runs.

Add support for `its` similar to rspec

  • its implementation
  • it without description implementation
describe("User", () => {
  subject() => new User())

  its("role", () => expected.to.equal("member"))
})

Basically its is a wrapper around it and example above can be converted to

it("s role equals to member", () => {
  expect($subject.role).to.equal("member")
})

Ability to deep merge with parent def

This is something that I find myself doing a lot. Defining an object in a parent context and then merging in changes to be more specific in sub describes. It would be very handy to have something like mergeDef which basically just deep merges that def with the previous contexts def

Love the library, by the way, been using it for years and couldn't go back.

def("foo", () => {foo: { bar: 1, baz: 2 } });

describe("when foo.bar is 2", () => {
  mergeDef("foo", () => {foo: {bar: 2}});

  it("sets both foo.bar and foo.baz to 2", () => {
    expect($foo).toEqual({foo: {foo: 2, baz: 2}});
  }); 
});

Variables collisions inside describe.skip

Here stacktrace:

[launcher] Error: Error: Cannot define "subject" variable twice in the same suite.
        at Object.lazyVar.register (C:\SpectrumMgmt\EsmSpectrum\ui\node_modules\bdd-lazy-var\lib\lazy_var.js:10:13)
        at context.def (C:\SpectrumMgmt\EsmSpectrum\ui\node_modules\bdd-lazy-var\lib\interface.js:58:20)
        at context.subject (C:\SpectrumMgmt\EsmSpectrum\ui\node_modules\bdd-lazy-var\lib\interface.js:31:45)
        at Suite.<anonymous> (C:\SpectrumMgmt\EsmSpectrum\ui\test\e2e\pages\configure\channels\wizard\section\proxy\proxy-e2etest.js:10(cat))
        at context.xdescribe.context.xcontext.context.describe.skip (C:\SpectrumMgmt\EsmSpectrum\ui\node_modules\mocha\lib\interfaces\bdd.js:64:10)
        at [object Object].Object.extend.describe (C:\SpectrumMgmt\EsmSpectrum\ui\test\e2e\lib\feature.js:29:5)
        at Object.<anonymous> (C:\SpectrumMgmt\EsmSpectrum\ui\test\e2e\pages\configure\channels\wizard\section\proxy\proxy-e2etest.js:5:25)
        at Module._compile (module.js:435:26)
        at Object.Module._extensions..js (module.js:442:10)
        at Module.load (module.js:356:32)
[launcher] Process exited with error code 100

I got this error when I skip several "describes".
It looks like lazy-var tries to define the variable for the wrong test suit.

Keep in mind that it is produced only for describe.skip.

Maximum call stack size exceeded because of accessing order in redefinition

So this will fail:

describe( 'parent', () => {
  def( 'value', () => 1 );

  describe( 'child', () => {
    def( 'addition', () => 1 );
    def( 'value', () => $addition + $value );

    it( 'is two', () => expect( $value ).to.eq( 2 ) );
  } );
} );

If we change second value definition from $addition + $value to $value + $addition it will pass.

I don't know if this is a bug or this is how it is supposed to be. Feel free to close if this is not a problem. ( But then maybe it is good to have a note about this somewhere )

Fallback to parent's variable inside the same definition sometimes fails

It looks like a parent-referencing subject() fails to initialize when there is another lazy variable in the same scope. Here's a minimal test case to demonstrate the problem:

'use strict'

import { expect } from 'chai'

class UserProvidedValue {
  constructor(value) {
    this.value = value
  }
}

class HardCodedValue {
  constructor(value) {
    this.value = { x: 'hard-coded' }
  }
}

describe('self-referencing subject problem', () => {
  describe('UserProvidedValue', () => {
    def('model', () => {
      return new UserProvidedValue($value)
    })

    describe('.value', () => {
      subject(() => $model.value)

      context('the x value', () => {
        def('value', () => ({ x: 5 }))

        subject(() => $subject.x)

        it('returns 5', () => {
          expect($subject).to.equal(5)
        })
      })
    })
  })

  describe('HardCodedValue', () => {
    def('model', () => {
      return new HardCodedValue()
    })

    describe('.value', () => {
      subject(() => $model.value)

      context('the x value', () => {
        subject(() => $subject.x)

        it('returns "hard-coded"', () => {
          expect($subject).to.equal('hard-coded')
        })
      })
    })
  })
})

When I run it through my gulp task, I see the following:

$ gulp test --name lazy-var
[10:21:28] Using gulpfile /workplace/exm-admin-tool/gulpfile.js
[10:21:28] Starting 'test'...


  self-referencing subject problem
    UserProvidedValue
      .value
        the x value
          1) returns 5
    HardCodedValue
      .value
        the x value
          ✓ returns "hard-coded"


  1 passing (11ms)
  1 failing

  1) self-referencing subject problem UserProvidedValue .value the x value returns 5:
     TypeError: Cannot read property 'x' of undefined
      at Context.<anonymous> (lazy-var-test.js:29:23)
      at node_modules/bdd-lazy-var/lib/interface.js:115:25
      at Context.Object.defineProperty.get (node_modules/bdd-lazy-var/lib/lazy_var.js:40:71)
      at context.get (node_modules/bdd-lazy-var/lib/interface.js:63:38)
      at Object.defineProperty.get (node_modules/bdd-lazy-var/lib/define_var.js:31:22)
      at Context.<anonymous> (lazy-var-test.js:32:18)



[10:21:28] 'test' errored after 161 ms
[10:21:28] Error in plugin 'gulp-mocha'
Message:
    1 test failed.

Note that this is not an ES6/babel issue. Replacing the classes with functions and invoking with mocha directly gives the same results:

'use strict'

var expect = require('chai').expect;

function UserProvidedValue(value) {
  this.value = value
}

function HardCodedValue(value) {
  this.value = { x: 'hard-coded' }
}

// rest of the file is unchanged

Here's the output:

 $ ./node_modules/.bin/mocha -u bdd-lazy-var/global test/es5-lazy-var-test.js


  self-referencing subject problem
    UserProvidedValue
      .value
        the x value
          1) returns 5
    HardCodedValue
      .value
        the x value
           returns "hard-coded"


  1 passing (12ms)
  1 failing

  1) self-referencing subject problem UserProvidedValue .value the x value returns 5:
     TypeError: Cannot read property 'x' of undefined
      at Context.<anonymous> (test/es5-lazy-var-test.js:25:31)
      at node_modules/bdd-lazy-var/lib/interface.js:115:25
      at Context.Object.defineProperty.get (node_modules/bdd-lazy-var/lib/lazy_var.js:40:71)
      at context.get (node_modules/bdd-lazy-var/lib/interface.js:63:38)
      at Object.defineProperty.get (node_modules/bdd-lazy-var/lib/define_var.js:31:22)
      at Context.<anonymous> (test/es5-lazy-var-test.js:28:18)

Implement support for global getters

As an developer
I want to use global getters
So that, I can write cleaner code

def('username', 'admin');

it('defines getter on global scope', function() {
  expect(username).to.equal('admin');
});

TypeError: suite.parent.appendOnlySuite is not a function

if i try to run mocha with an .only block, i get the following error:

express/node_modules/bdd-lazy-var/node_modules/mocha/lib/interfaces/common.js:132
          suite.parent.appendOnlySuite(suite);
                       ^
TypeError: suite.parent.appendOnlySuite is not a function
    at Object.create (express/node_modules/bdd-lazy-var/node_modules/mocha/lib/interfaces/common.js:132:24)
    at Object.only (express/node_modules/bdd-lazy-var/node_modules/mocha/lib/interfaces/common.js:96:21)
    at context.describe.only (express/node_modules/bdd-lazy-var/node_modules/mocha/lib/interfaces/bdd.js:69:27)
    at Function.detectSuite [as only] (express/node_modules/bdd-lazy-var/global.js:475:25)
    at Module.only

this only happens on 2.5.1

Example to reproduce:

Important note: if you install dependencies using yarn only!

describe.only("test suite", () => { // <--- error thrown here
  def("name", "John");

  it("works", () => {
    expect($name).to.equal("John");
  });

  context("nested suite", () => {
    it("also works", () => {
      expect($name).to.equal("John");
    });

    it("works as well", () => {
      expect(1).to.equal(1);
    });
  });
});

Is it expected that calling get for a value which is not defined throws an error ?

More of a question but I'm getting an error trying calling get for a value which is undefined (has no corresponding def rather than is set to undefined). Is this expected ? If so could there be a better error message like The value 'foo' was not defined or similar.

Currently, I'm getting an error as follows, it doesn't really give me much to go on:

TypeError: Cannot read property 'evaluate' of undefined
    at Metadata.getVar (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:206:45)
    at Variable.value (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:304:42)
    at Function.evaluate (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:275:25)
    at get$$1 (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:356:23)
    at assets/unit.js:56381:18
    at VariableMetadata.evaluate (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:159:44)
    at Metadata.getVar (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:206:45)
    at Variable.value (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:304:42)
    at Function.evaluate (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:275:25)
    at get$$1 (eval at Array.concat.module.exports (assets/unit.js:23649:9), <anonymous>:356:23)```

Reference to parent subject is deleted prematurely

Looks like the reference to parent subject is deleted prematurely.

describe('Parent', function() {
  subject(function() {
    return {
      getName: function() {
        return 'Nick';
      },
      doSmth: function() {
      }
    };
  });

  describe('Name', function() {
    subject(function() {
      subject().doSmth();

      return subject().getName();
    });

    it('is retrieved', function() {
      expect(subject()).to.equal('Nick');
    });
  });
});

This example fails with

1) Parent Name is retrieved:
   Error: Unknown parent variable "subject".
    at Context.<anonymous> (.\test.js:21:16)
    at Context.<anonymous> (.\test.js:25:16)

However, if I comment out subject().doSmth(); line, the test passes.

Variables not cached

It seems the variables are not cached when access in multiple places. From what I understand, they are supposed to be evaluated once on first access and cached if not overridden. Example:

import { def, get as $ } from 'bdd-lazy-var/getter';
import { describe, it, before, after, beforeEach, afterEach } from 'mocha';

describe('Foo', () => {
  def('myVar', () => Math.random());

  it('bar', () => {
    console.log($.myVar);
  })

  it('bar', () => {
    console.log($.myVar);
  })
});

Output:

      Foo
0.1305908169933785
        ✓ bar
0.7144595418228867
        ✓ bar

Use in PhantomJS?

This package looks awesome. At first I was trying to use it when running my tests in PhantomJS, and I was getting errors like Error: Cannot find module "fs", and then I realized phantom wouldn't have access to the file system since it's a browser. I found this page that makes it look like it could use fs?... but that page doesn't really tell me anything useful. So, do you know, is it possible to use this from within a browser, such as PhantomJS?

Linter Support?

Anyone know of a trick to prevent eslint from complaining that methods like def and get are not defined?

Troubleshooting

Great utility! Wish I could get it to work. Getting error:

Suite uses name variable:
     ReferenceError: $name is not defined

I pasted your exact example into my app:

import { expect } from 'chai'

describe('Suite', function() {
  def('name', function() {
    return getName();
  });

  it('uses name variable', function() {
    expect($name).to.exist
  });

  it('does not use name, so it is not created', function() {
    expect(1).to.equal(1);
  });
});

My test script is:

mocha -u bdd-lazy-var --compilers js:babel-core/register --require jsdom-global/register --require ./web/test/index.js --require ignore-styles --recursive ./web/test -R nyan

I am using mocha version 3.0.2

Your assistance is greatly appreciated!

commonjsGlobal.describe is not a function

I'm trying to use the following code:

describe('utils/canDoAThing', function() {
  subject(() => canDoAThing(get.user, get.tour));
  ...

  sharedExamplesFor('a disallowed action', () => {
    it('returns false', function() {
      expect(get.subject).to.be.false;
    });
  });

  ...

  itBehavesLike('a disallowed action');
});

And I get this error:

  commonjsGlobal.describe('behaves like ' + name, function () {
                 ^

TypeError: commonjsGlobal.describe is not a function
    at itBehavesLike (/Users/dkniffin/Repositories/project/node_modules/bdd-lazy-var/getter.js:343:18)

Cypress support

Can this be used in cypress, Where there is no access to new Mocha() ?

Missed parent subject

Hi.
I found an unpleasant bug in your library. It happens because you do not rewrite parent "subject" if there is no "subject" in the nested "describe" but present any "def" functions. Let me provide you some evidences:)
You can reproduce this bug using this code:

describe('first', function() {
  subject(function() {
    return user;
  });

  describe('second', function() {
    def('hello', function() {
    return 'world';
    });

    describe('third', function() {
      subject(function() {
        return subject().name;
      });

      it('does something', function() {
        expect().to.equal('Tom');
      });
    });
  });
});

The error:

 1) first second third does something "before each" hook:
    Error: Unknown parent variable "subject".

I hope this helps you to understand where bug is situated.

Subject not defined correctly after "empty" context

I've been trying to upgrade to 2.1.2 from 1.3.1 and I'm encountering some issues.

If I do not define any variables in a context then subsequent sibling contexts do not have the subject defined correctly (they get the subject which was defined at the parent level, it seems.)

I'm happy to help out with a fix but I'd need some pointers to where I might look in the code.

  describe('testing', () => {
    const TestComponent = ({ numberOfRows, header }) => (
      <span>
        <h3>{header}</h3>
        {Array.from(Array(numberOfRows).keys()).map(n => <span className="row">{n}</span>)}
      </span>
    );

    // shallow is from from enzyme
    subject(() => shallow(<TestComponent {...get('props')} />));

    def('props', () => ({
      numberOfRows: get('numberOfRows'),
      header: get('header'),
    }));
    def('numberOfRows', 1);
    def('header', 'asdfasdf');

    context('the rows', () => {
      subject(() => subject().find('span.row'));

      // passes
      context('where there are now rows', () => {
        def('numberOfRows', 0);

        it('renders no rows', () => {
          expect(subject()).to.have.length(0);
        });
      });

      // passes
      context('where there are multiple rows 1', () => {
        def('numberOfRows', 3);

        it('renders multiple rows', () => {
          expect(subject()).to.have.length(3);
        });
      });

      // passes
      context('where there is one row ', () => {
        // def('numberOfRows', 1);
        // it seems the subject is not redefined with the correct parameters for _subsequent_
        // contexts unless there's a call to `def` here.
        // def('header', 'wut?')
        // def('asdfasdf', 'asdfasdf');


        it('renders the correct rows', () => {
          expect(subject()).to.have.length(1);
        });
      });

      // fails: expected ... to have a length of 3 but got 1
      context('where there are multiple rows 2', () => {
        // This fails unless there is some def in the above context.
        def('numberOfRows', 3);

        it('renders multiple rows', () => {
          expect(subject()).to.have.length(3);
        });
      });
    });
  });

.only no longer works in bdd-lazy-var/rspec

Here's my basic test:

var expect = require('chai').expect

describe('.only is messed up', () => {
  def('thing', () => void 0)
  
  context('when thing is overridden', () => {
    def('thing', () => 1)
    
    it('works okay', () => expect($thing).to.equal(1))
  })

  context('another context', () => {
    def('thing', () => 2)
    
    it('works okay', () => expect($thing).to.equal(2))
  })
})

Which works fine as-is:

  .only is messed up
    when thing is overridden
      ✓ works okay
    another context
      ✓ works okay

But if I put an .only on the first it(), the .only is ignored and the whole suite runs:

  .only is messed up
    when thing is overridden
      ✓ this should be the only example we see
    another context
      ✓ works okay

If I move the .only to the first context, I see this:

Message:
    Cannot define "thing" variable twice in the same suite.
Stack:
Error: Cannot define "thing" variable twice in the same suite.
    at Object.lazyVar.register (/workplace/exm-admin-tool/node_modules/bdd-lazy-var/lib/lazy_var.js:39:13)
    at context.def (/workplace/exm-admin-tool/node_modules/bdd-lazy-var/lib/interface.js:116:13)
    at Suite.<anonymous> (/workplace/exm-admin-tool/test/lazy-var-test.js:7:5)
    at Object.create (/workplace/exm-admin-tool/node_modules/mocha/lib/interfaces/common.js:114:19)
    at Object.only (/workplace/exm-admin-tool/node_modules/mocha/lib/interfaces/common.js:79:21)
    at Function.context.describe.only (/workplace/exm-admin-tool/node_modules/mocha/lib/interfaces/bdd.js:68:27)
    at Suite.<anonymous> (/workplace/exm-admin-tool/test/lazy-var-test.js:6:11)
    at Object.suiteTracker.rspec (/workplace/exm-admin-tool/node_modules/bdd-lazy-var/lib/interface.js:52:16)
    at Suite.<anonymous> (/workplace/exm-admin-tool/node_modules/bdd-lazy-var/lib/interface.js:130:42)
    at Object.create (/workplace/exm-admin-tool/node_modules/mocha/lib/interfaces/common.js:114:19)
    at context.describe.context.context (/workplace/exm-admin-tool/node_modules/mocha/lib/interfaces/bdd.js:44:27)
    at context.(anonymous function) (/workplace/exm-admin-tool/node_modules/bdd-lazy-var/lib/interface.js:126:12)
    at Object.<anonymous> (/workplace/exm-admin-tool/test/lazy-var-test.js:3:1)
    at Module._compile (module.js:541:32)
    at loader (/workplace/exm-admin-tool/node_modules/babel-register/lib/node.js:144:5)
    at Object.require.extensions.(anonymous function) [as .js] (/workplace/exm-admin-tool/node_modules/babel-register/lib/node.js:154:7)

If I comment out the very first definition of thing (where I set it to void 0), the .only on the context is ignored:

  .only is messed up
    this context has an .only
      ✓ works okay
    another context
      ✓ works okay

Here are the versions I'm using:

$ mocha --version
2.3.4

$ node -v
v6.3.1

$ npm show bdd-lazy-var version
1.2.0

$ npm show chai version
3.5.0

Improve typings for sharedExamplesFor

Hello!

The current typings for sharedExamplesFor are defined as:

export function sharedExamplesFor(summary: string, implementation: () => void): void;
Source: https://github.com/stalniy/bdd-lazy-var/blob/master/index.d.ts#L7

I believe these need to be changed as follows to coincide with the signature from itBehavesLike and the documentation in the readme:

export function sharedExamplesFor(summary: string, implementation: (...vars: any[]) => void): void;

We're currently receiving the following error when attempting to define parameters on sharedExamplesFor:

[ts] Argument of type '(a: any) => void' is not assignable to parameter of type '() => void'.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.