Git Product home page Git Product logo

chai-spies's People

Contributors

brandonhorst avatar d48 avatar damianb avatar domenic avatar greenkeeper[bot] avatar gregdardis avatar jamesmaroney avatar jethrolarson avatar jimlynchcodes avatar keithamus avatar logicalparadox avatar meeber avatar mluby avatar pgherveou avatar piotrsliwa avatar plaxdan avatar reiz avatar robcolburn avatar ryckes avatar sateffen avatar sebamarynissen avatar stalniy avatar tregusti avatar vesln 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  avatar  avatar  avatar  avatar  avatar

chai-spies's Issues

.to.have.been.called.with repeating params

Hi, I am currently experiencing a strange issue with checking spies calls. It seems like it works only if checking calls with unique parameters, or I am using chai wrong which I would like to be pointed at.

To reproduce:

  it('checks spy calls with unique params', () => {
    const math = {
      multiply: function (a, b) {
        return a * b;
      }
    };

    const multiplyFunction = chai.spy.on(math, 'multiply');
    math.multiply(1, 2);
    chai.expect(multiplyFunction).to.have.been.called.with(1, 2);
  });


  it('checks spy calls with repeating params', () => {
    const math = {
      multiply: function (a, b) {
        return a * b;
      }
    };

    const multiplyFunction = chai.spy.on(math, 'multiply');
    math.multiply(1, 1);
    chai.expect(multiplyFunction).to.have.been.called.with(1, 1);
  });

First test always passes, while second fails, even if putting single 1 in expectation call params.
Here is the error message:

AssertionError: expected { Spy, 1 call } to have been called with [ 1, 1 ]
    at assertWith (node_modules\chai-spies\lib\spy.js:280:12)
    at assert (node_modules\chai\lib\chai\utils\addChainableMethod.js:84:49)
    at Context.<anonymous> (....test.ts:79:59)
    at tryCatcher (core\node_modules\bluebird\js\release\util.js:16:23)
    at Promise._settlePromiseFromHandler (core\node_modules\bluebird\js\release\promise.js:512:31)
    at Promise._settlePromise (core\node_modules\bluebird\js\release\promise.js:569:18)
    at Promise._settlePromise0 (core\node_modules\bluebird\js\release\promise.js:614:10)
    at Promise._settlePromises (core\node_modules\bluebird\js\release\promise.js:693:18)
    at Async._drainQueue (core\node_modules\bluebird\js\release\async.js:133:16)
    at Async._drainQueues (core\node_modules\bluebird\js\release\async.js:143:10)
    at Immediate.Async.drainQueues (core\node_modules\bluebird\js\release\async.js:17:14)

Also multiplyFunction.__spy field does have a call with params 1, 1

"__spy":  {
    "calls": [
    [
      1,
      1
    ]
  ],
    "called": true
  }

Used versions:

"@types/chai-spies": "0.0.0",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"chai-spies": "^0.7.1",

Module '"chai-spies"' has no exported member 'spies'.

When I enter this code in TypeScript it does not compile:

import { expect } from 'chai';
import { spies } from 'chai-spies';
chai.use(spies);

Error: Module '"chai-spies"' has no exported member 'spies'.

You should probably have a guide for TypeScript in the README.

Thanks!
Jim

npm issues

I just installed via npm install chai-spies as documented and noticed I have installed this NPM package which is not this repository.

Strangely I can also see that they are both are the same version 0.7.1 even though the one I have installed lacks some of the functionality that the readme documents.

I think you might need to publish to NPM again!
Thanks

Devise a way to track & restore spies

One big problem with spies is being able to quickly restore old behaviour, when you want the function to execute its original behaviours.

Now we have chai.spy.on(object, ...methods); I think we could track which methods we spy on what objects. We could implement some kind of sandboxing:

sandbox = chai.spy.sandbox();
sandbox.spy.on(myArray, 'push', 'pull');
sandbox.spy.restore(myArray, 'push');
sandbox.spy.restoreAll();

The main export of chai-spies could also be a sandbox in of itself - and so:

chai.spy.on(myArray, 'push', 'pull');
chai.spy.restore(myArray, 'push');
chai.spy.restoreAll(); // restores Array.pull

Potentially we could also make a decorator/higher order function which would help inside of tests; for example:

test(chai.spy.sandbox(function (spy) {
  expect(spy()).to.be.a('function');
}));

This is just a rough draft of what I have in my head - I'd very much like feedback, especially from @stalniy who has been doing some great contributions lately, including the improved chai.spy.on interface.

Clone arguments before passing into the original function?

function fn(options) {
  options.foo = 1;
}
spy = chai.spy(fn);
spy({ bar : 1 });
spy.should.be.called.with({ bar : 1 }); // fail

This happens because the function fn modifies the argument, and the spy compares the modified object instead of the original version.
Do you think it makes sense if we store a shallow cloned argument instead of using the argument directly?

expect(spy).to.have.been.called.with always true

"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"chai-spies": "^0.7.1",

Hi there,

I am testing a little ORM I created myself

I am having some problems testing the result of a spy on a promise, the test always passes, no matter what I put inside with, in the example below I just put null, although query should be called with a SELECT SQL sentence

Any suggestions?

it('test SQL',
    () => {
      Item.database = { query: queryReturnsInsert };

      const item = new Item();
      item.name = 'James';

      const spy = chai.spy.on(Item.database, 'query');

      item.save({ in: 'go' })
        .then(function() {
          expect(spy).to.have.been.called.with(null);
        });
    });

An in-range update of mocha is breaking the build 🚨

Version 3.4.1 of mocha just got published.

Branch Build failing 🚨
Dependency mocha
Current Version 3.4.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As mocha is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details
  • βœ… dependency-ci Dependencies checked Details,- ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Release Notes Ohai CRLF...

Fixed a publishing mishap with git's autocrlf settings.

Commits

The new version differs by 3 commits0.

false

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Incompatibility with chai@4

chai version: 4.0.0
chai-spies version: 0.7.1
Node.js version: 7.10.0

expect(spy).to.be.called.with(...) fails with:

Error: Invalid Chai property: _his. Did you mean "is"?
 at Object.proxyGetter [as get] (node_modules/chai/lib/chai/utils/proxify.js:63:17)
 at Proxy.assertWith (node_modules/chai-spies/lib/spy.js:283:29)
 at Proxy.chainableMethodWrapper (node_modules/chai/lib/chai/utils/addChainableMethod.js:113:49)

Besides that, if this is a breaking change in the public API for plugin authors, it should probably have been mentioned in the release notes for [email protected].

Thanks!

Request to bump up npm version

Thanks for merging in #28 πŸ‘

Do you mind bumping the package.json version and publishing to npm? I work on an application that pulls this in via npm and it would be great to have that new method for our unit tests. Thanks!

to.have.been.called.with() throws an error

Hi there,

I have a small issue with chai spies.

import * as spies from 'chai-spies';
const assert = chai.assert;
const expect = chai.expect;

beforeEach(() => {
chai.use(spies);
spy = chai.spy.on(component.change, 'emit');
});

it('should have been called with string foo', () => {
expect(spy).to.have.been.called.with('foo');
});

When invoking the above code I receive an error:

Error: Invalid Chai property: _his. Did you mean "is"?
at Object.proxyGetter [as get] (node_modules/chai/chai.js:9105:17)

I don't have any problems with running other functions so far like to.have.been.called.once/twice etc.

Is it a known issue?
I use chai version 4.0.2 and chai-spies version 0.7.1

Support to spy on parameters

Example on how it could work:

var add = function (a, b) {
   return a + b;
}

spy = chai.spy(add);

add(40, 2);

spy.should.have.been.called.with(40, 2)

spy.interface documentation appears to be wrong

Looking at the interface documentation it seems to be slightly incorrect if you try and create an object through the array-of-keys syntax.

Particularly, it says you can do something like chai.spy.interface(['on', 'off', 'emit']);.

However, looking at the tests, there is no such expectation of being able to create an interface in that way. You need to pass a "base class" to create the interface from, like chai.spy.interface("Object", ['on', 'off', 'emit']);.

Creating an interface in the way the documentation suggests creates a weird object with integer keys, which is not quite what you want.

`proxy.toString` blocks getting names of function parameters

I wonder if this code is really needed? I found that it breaks reading names of functions parameters (like here). I use some DI container that parses function definition string and because of that, I can test my modules only when I wrap spy in pure function.

let spy = chai.spy('justSpy');

annotatedFn(() => spy());

expect(spy).to.have.been.called.once();

So I can live with that, but I just wonder if anything can be improved.

chai.spy.returns

Not a big deal but http://chaijs.com/plugins/chai-spies shows the readme on the master branch which includes the new chai.spy.return feature. This feature thats on master hasn't been tagged and released yet. So if you follow the instructions npm install chai-spies. The api for chai.spy.returns is missing.

You come to the gh repo and master has spy.returns. Should this be tagged and released?

Adding in chai-spies makes an assertion fail

Adding the chai-spies.js file to my HTML spec runner file, makes this assertion fail:

expect(ret.__observable).to.have.property('ids').with.length(1)

It throws this error:

TypeError: Property 'length' of object function () {
              var result = method.apply(this, arguments);
              return result === undefined ? this : result;
            } is not a function

If I comment out the line where I include chai-spies.js it passes again. I'm not using any spies yet.

How to reproduce:

$ git clone https://github.com/js-coder/observable.git
$ cd observable
$ git checkout v1.2.0
# open spec/index.html

I guess that's a bug?

What is the goal of chai-spies?

The readme states up front that the primary purpose of chai-spies is to serve as an example of how to create a Chai plugin. This statement suggests that its role as a mocking library is secondary. It mentions that only the most basic of functionality is provided, and even goes so far as to recommend an alternative library if advanced functionality is desired.

Of course, just because those words were written x years ago doesn't mean they're true now, or that it's the way things should be going forward. However, as the Chai ecosystem grows and the number of maintainers increases, I think it's valuable to reach an understanding on what the goal of chai-spies is so that we're all of the right mindset when evaluating feature requests.

My opinion is that the originally stated goal and minimalistic scope of chai-spies should be strictly maintained, and that when it comes to users requesting advanced features, we should point them at sinon and chai-sinon. I think we do more good for the community overall by throwing our support behind these existing libraries rather than duplicating their efforts, and that chai-spies fulfills its own niche quite nicely as being super minimalistic.

With that said, I'll fall in line behind the popular opinion on this issue. Achieving clarity in the goal of chai-spies is more important to me than my opinion. But in that case I'd like to learn more about what the strengths of chai-spies are in comparison to sinon and sinon-chai, other than it being lightweight, so that we can work to maximize those strengths going forward.

`spy.on` doesn't work with nullish prototype

I've noticed that if you do something like

const object = Object.create(null);
object.method = function() {};
chai.spy.on(object, 'method');

it will throw an error because it uses

object.hasOwnProperty(methodName);

This can be fixed easily by changing it to

Object.hasOwnProperty.call(object, methodName);

I will file a PR for this.

Context

I've encountered the issue in the context of migrating to Vue 3 and using @vue/test-utils. Apparently if you mount a component like

import { mount } from '@vue/test-utils';
let { vm } = mount(Component);

then vm is an object with null as its prototype. If you then want to spy on some of its methods with chai.spy.on, it throws the error above.

An in-range update of mocha is breaking the build 🚨

Version 4.0.0 of mocha just got published.

Branch Build failing 🚨
Dependency mocha
Current Version 3.5.3
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As mocha is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Release Notes v4.0.0

4.0.0 / 2017-10-02

You might want to read this before filing a new bug! 😝

πŸ’₯ Breaking Changes

For more info, please read this article.

Compatibility

  • #3016: Drop support for unmaintained versions of Node.js (@boneskull):
    • 0.10.x
    • 0.11.x
    • 0.12.x
    • iojs (any)
    • 5.x.x
  • #2979: Drop support for non-ES5-compliant browsers (@boneskull):
    • IE7
    • IE8
    • PhantomJS 1.x
  • #2615: Drop Bower support; old versions (3.x, etc.) will remain available (@ScottFreeCode, @boneskull)

Default Behavior

  • #2879: By default, Mocha will no longer force the process to exit once all tests complete. This means any test code (or code under test) which would normally prevent node from exiting will do so when run in Mocha. Supply the --exit flag to revert to pre-v4.0.0 behavior (@ScottFreeCode, @boneskull)

Reporter Output

πŸ‘Ž Deprecations

  • #2493: The --compilers command-line option is now soft-deprecated and will emit a warning on STDERR. Read this for more info and workarounds (@ScottFreeCode, @boneskull)

πŸŽ‰ Enhancements

  • #2628: Allow override of default test suite name in XUnit reporter (@ngeor)

πŸ“– Documentation

πŸ”© Other

Commits

The new version differs by 48 commits.

  • d69bf14 Release v4.0.0
  • 171b9f9 pfix "prepublishOnly" potential portability problem
  • 60e39d9 Update link to wiki (GitHub at the leading --)
  • 804f9d5 Update link because GitHub ate the leading --
  • 3326c23 update CHANGELOG for v4.0.0 [ci skip]
  • 6dd9252 add link to wiki on --compilers deprecation
  • 96318e1 Deprecate --compilers
  • 92beda9 drop bower support
  • 58a4c6a remove unused .npmignore
  • 7af6611 kill Date#toISOString shim
  • 43501a2 reduce noise about slow tests; make a few tests faster, etc.
  • fa228e9 update --exit / --no-exit integration test for new default behavior
  • 3fdd3ff Switch default from forced exit to no-exit
  • c5d69e0 add integration tests for --exit/--no-exit
  • 3a7f8dc enhance runMochaJSON() helper by returning the subprocess instance

There are 48 commits in total.

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of rollup-plugin-commonjs is breaking the build 🚨

Version 8.2.3 of rollup-plugin-commonjs was just published.

Branch Build failing 🚨
Dependency rollup-plugin-commonjs
Current Version 8.2.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

rollup-plugin-commonjs is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Commits

The new version differs by 15 commits.

  • 3724521 8.2.3
  • 33ce531 8.2.2
  • 8d53cca Merge pull request #233 from mbostock/fix-require-collision
  • 7c14734 Remove apparently-unneeded file.
  • 386a1e7 Add test for require collision.
  • 93cedc2 Fix #232 - require collision.
  • 419a912 Update dependencies
  • d3cd998 Merge pull request #241 from rollup/update-test-config
  • 8efa096 Silence a few test warnings
  • 77c4838 Merge pull request #230 from caleb531/duplicate-export-fix
  • 6a3046e Merge pull request #229 from DenisCarriere/patch-1
  • 83315ad Merge pull request #226 from marijnh/master
  • 4dae460 Make unwrapExports only pick out default when it exists
  • e49819a Fix rollup/rollup#1637 (with tests)
  • a453bb4 Update README.md

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of mocha is breaking the build 🚨

The devDependency mocha was updated from 5.2.0 to 6.0.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

mocha is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Release Notes for v6.0.0

6.0.0 / 2019-02-18

πŸ’₯ Breaking Changes

  • #3149: Drop Node.js v4.x support (@outsideris)
  • #3556: Changes to command-line options (@boneskull):
    • --grep and --fgrep are now mutually exclusive; attempting to use both will cause Mocha to fail instead of simply ignoring --grep
    • --compilers is no longer supported; attempting to use will cause Mocha to fail with a link to more information
    • -d is no longer an alias for --debug; -d is currently ignored
    • #3275: --watch-extensions no longer implies js; it must be explicitly added (@TheDancingCode)
  • #2908: tap reporter emits error messages (@chrmod)
  • #2819: When conditionally skipping in a before hook, subsequent before hooks and tests in nested suites are now skipped (@bannmoore)
  • #627: Emit filepath in "timeout exceeded" exceptions where applicable (@boneskull)
  • #3556: lib/template.html has moved to lib/browser/template.html (@boneskull)
  • #2576: An exception is now thrown if Mocha fails to parse or find a mocha.opts at a user-specified path (@plroebuck)
  • #3458: Instantiating a Base-extending reporter without a Runner parameter will throw an exception (@craigtaub)
  • #3125: For consumers of Mocha's programmatic API, all exceptions thrown from Mocha now have a code property (and some will have additional metadata). Some Error messages have changed. Please use the code property to check Error types instead of the message property; these descriptions will be localized in the future. (@craigtaub)

πŸ“  Deprecations

These are soft-deprecated, and will emit a warning upon use. Support will be removed in (likely) the next major version of Mocha:

  • -gc users should use --gc-global instead
  • Consumers of the function exported by bin/options should now use the loadMochaOpts or loadOptions (preferred) functions exported by the lib/cli/options module

Regarding the Mocha class constructor (from lib/mocha):

  • Use property color: false instead of useColors: false
  • Use property timeout: false instead of enableTimeouts: false

All of the above deprecations were introduced by #3556.

mocha.opts is now considered "legacy"; please prefer RC file or package.json over mocha.opts.

πŸŽ‰ Enhancements

Enhancements introduced in #3556:

  • Mocha now supports "RC" files in JS, JSON, YAML, or package.json-based (using mocha property) format

    • .mocharc.js, .mocharc.json, .mocharc.yaml or .mocharc.yml are valid "rc" file names and will be automatically loaded
    • Use --config /path/to/rc/file to specify an explicit path
    • Use --package /path/to/package.json to specify an explicit package.json to read the mocha prop from
    • Use --no-config or --no-package to completely disable loading of configuration via RC file and package.json, respectively
    • Configurations are merged as applicable using the priority list:
      1. Command-line arguments
      2. RC file
      3. package.json
      4. mocha.opts
      5. Mocha's own defaults
    • Check out these example config files
  • Node/V8 flag support in mocha executable:

    • Support all allowed node flags as supported by the running version of node (also thanks to @demurgos)
    • Support any V8 flag by prepending --v8- to the flag name
    • All flags are also supported via config files, package.json properties, or mocha.opts
    • Debug-related flags (e.g., --inspect) now imply --no-timeouts
    • Use of e.g., --debug will automatically invoke --inspect if supported by running version of node
  • Support negation of any Mocha-specific command-line flag by prepending --no- to the flag name

  • Interfaces now have descriptions when listed using --interfaces flag

  • Mocha constructor supports all options

  • --extension is now an alias for --watch-extensions and affects non-watch-mode test runs as well. For example, to run only test/*.coffee (not test/*.js), you can do mocha --require coffee-script/register --extensions coffee.

  • #3552: tap reporter is now TAP13-capable (@plroebuck & @mollstam)

  • #3535: Mocha's version can now be queried programmatically via public property Mocha.prototype.version (@plroebuck)

  • #3428: xunit reporter shows diffs (@mlucool)

  • #2529: Runner now emits a retry event when tests are retried (reporters can listen for this) (@catdad)

  • #2962, #3111: In-browser notification support; warn about missing prereqs when --growl supplied (@plroebuck)

πŸ› Fixes

πŸ“– Documentation

πŸ”© Other

Commits

The new version differs by 209 commits ahead by 209, behind by 39.

  • 42303e2 Release v6.0.0
  • a553ca7 punctuation updates for changelog v6.0.0
  • c710792 grammar updates for changelog v6.0.0
  • 9f9293a update changelog for v6.0.0
  • a540eb0 remove "projects" section from MAINTAINERS.md [ci skip]
  • 52b5c42 Uppercased JSON reporter name in describe title (#3739)
  • 82307fb Fix .globals to remove falsy values (#3737)
  • 56dc28e Remove unnecessary post-processing code having no effect; closes #3708 (#3733)
  • 16b4281 Documentation updates (#3728)
  • 5d9d3eb Update nyc
  • 118c9ae Refactor out usages of Suite#_onlyTests and Suite#_onlyTests (#3689) (#3707)
  • 0dacd1f Add ability to unload files from require cache (redux) (#3726)
  • 66a52f2 update release steps [ci skip]
  • 45ae014 Refactor lookupFiles and files (#3722)
  • 94c9320 fix --reporter-option to allow comma-separated options; closes #3706

There are 209 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

.exactlyWith and .exactlyWhen

I'm currently writing tests for message passing with the cluster module. In some cases it would be useful to check that a number of certain type of message were received.

What this feature request amounts to is some sort of .exactlyWith.

Additionally, consider something like .exactlyWhen which could only bump the count if the args match a filter.

spy.should.have.been.called.exactly(3).when(function (a, b) { return a > b });

chai.spy.on(...).returns

I mentioned in a comment on #39 that I'm migrating a large project from jasmine 1.x to mocha. I really want to avoid using sinon-chai and would much rather roll with pure chai goodness. Jasmine however, has a magical little call that's prolific in our test codebase:

spyOn(object, 'method').andReturn(someValue);

Best I can tell, that's altogether missing from this lib. If there's a method I've missed, or there's a way to achieve the same, please do share it. I dare say it's not spelled out very clearly anywhere. But then I might be a big dummy.

Anyhow, this would be a grand feature to have.

method to reset spy object

Hello,

is there a method to reset a spy object for reuse?

var boom = chai.spy(originalFn);

originalFn();

expect(boom).to.have.been.called.once;  // passes

boom.reset();

expect(boom).to.have.been.called.once;  //fails

Was helpful in another test framework and thought it would be great here. I can open up a pull request too if it's a matter of resetting some internal vars for the callCount

AssertWith doesn't behave properly when calling a function with the same arguments

Asserting that a function has been called with a given parameter fails if that function was called with that parameter with an arity greater than one.

For example, the following assertions fail if the function sum is called with sum(1, 1).

expect(sum).to.have.been.called.with(1) (1)
expect(sum).to.have.been.called.with(1, 1) (2)

The reason is that the function assertWith counts all the occurrences of the parameters for each argument and then expects it to be equal to the length of the arguments.

Assertion (1) will fail because 1 appears twice in the arguments list, but the length of the with arguments is 1.

Assertion (2) will also fail because 1 appears twice in the arguments list, so for every with argument it is counted twice, so it's been found "4" times.

TypeError: Cannot use 'in' operator to search for 'Date' in global

The following code causes a TypeError: Cannot use 'in' operator to search for 'Date' in global:

describe("now", () => {

    it("returns a properly formatted date", () => {

      chai.spy.on("global", "Date", () => {
        return new Date("2018-09-07T10:29:01.000Z");
      });

      const result = now();

      expect(result).to.equal("9/7/2018 7:29:1");

    });

  });

Any ideas?

Restoring issue

edit: PR is here.

The current restore method has issues when dealing with multiple spies.

Current code with my comments, showing the flaws:

  Sandbox.prototype.restore = function (object, methods) {
    // actually `hasFilter` is more a `exitAfterOneSpyIsRestored`
    var hasFilter = Boolean(object && methods);
    var sandbox = this;

    if (methods && !Array.isArray(methods)) {
      methods = [methods]
    }

    // remember that sandbox === this
    Object.keys(this[STATE_KEY]).some(function (spyId) {
      var spy = sandbox[STATE_KEY][spyId];
      var tracked = spy.__spy.tracked;
      // `isXxxSpied` is more `shouldXxxBeRestored`, based on the request made through input
      var isObjectSpied = !object || object === tracked.object;
      var isMethodSpied = !methods || methods.indexOf(tracked.methodName) !== -1;

      // issue: we're deleting a reference to the currently parsed spy (sandbox === this)
      // however, there's no reason we should de-reference it since we don't know whether
      // we should restore this one yet
      delete sandbox[STATE_KEY][spyId];

      // issue: we're saying "don't restore this spy if !(shouldObjectBeRestored || shouldMethodBeRestored)"
      // we want to say "don't restore if neither the object nor the method should be restored"
      // here we allow restore(object, 'method') to restore all spied methods on object
      if (!isObjectSpied && !isMethodSpied) {
        return false;
      }

      sandbox.restoreTrackedObject(spy);

      // issue: methods can be an array of several methods, this makes the process stop
      // as soon as the first method is restored
      // this issue combined with the previous condition makes you restore ANY method
      // on the object, not ensuring that's the correct one nor the only one requested
      if (hasFilter) {
        return true;
      }
    });

    return this;
  };

Here is a fixed version:

  Sandbox.prototype.restore = function (object, methods) {
    var exitAfter = 0, restored = 0;
    var sandbox = this;

    if (methods) {
      if (!Array.isArray(methods)) {
        methods = [methods]
      }
      // set the end-of-process shortcut properly, only if `methods` was populated and is now an array
      exitAfter = methods.length;
    }

    Object.keys(this[STATE_KEY]).some(function (spyId) {
      var spy = sandbox[STATE_KEY][spyId];
      var tracked = spy.__spy.tracked;
      // these 2 bools mean "should we process this spy", not "do we spy this object[ and method]"
      // since, anyway, this[STATE_KEY] *is* the list of spies we own
      var shouldRestoreThisObject = !object || object === tracked.object;
      var shouldRestoreThisMethod = !methods || methods.indexOf(tracked.methodName) !== -1;

      // equivalent to !(should...Object && should...Method)
      // this wouldn't work if we could provide a method without providing an object
      if (!shouldRestoreThisObject || !shouldRestoreThisMethod) {
        // we were not asked to restore this spy: next!
        return false;
      }

      // remove from the list of spies now that we know we'll restore this one
      delete sandbox[STATE_KEY][spyId];
      // do the restoring
      sandbox.restoreTrackedObject(spy);

      if (++restored === exitAfter) {
        // we were asked to restore that many spies, we did, get out now
        // we never enter this block if exitAfter stays at zero (i.e. no shortcut)
        return true;
      }
    });

    return this;
  };

Check on spy call order by parameter

In some cases is needed to check that the same spy has been called multiple times with different parameters (eg: while testing a curried function)

This is a possible desired feature, suggested by @keithamus:

const spy = chai.spy();
spy('a');
spy('b');
spy('c');
expect(spy).to.first.be.called.with('a');
expect(spy).to.second.be.called.with('b');
expect(spy).to.third.be.called.with('c');

It could be hard to match/generate first, second, third, nth property in the assertion chain.

Another possible assertion structure is:

const spy = chai.spy();
spy('a');
spy('b');
spy('c');
expect(spy).to.have.been.called.with.ordered('a', 'b', 'c');

export spy function as names export from chai-spies

Atm one as to register the spies before beeing able to use it with the chai-object chai.spy

However, I like to import only what I need:

import {expect, use} from 'chai'
import spies from 'chai-spies'

use(spies)

As you can see I cannot grab the spy function because its not available at import time.
Thats why it would be cool to have a named export on chai-spies which returns a wrapper to the chai.spy. That way you can do:

import {expect, use} from 'chai'
import spies, {spy} from 'chai-spies'

use(spies)

What do you think?

Bring back spy.reset()

A previous issue #27 introduced the reset method to this library which we use extensively. It was removed in 1.0 for no clear reason. I'd like to see it put back

Feature: chai.spy.callsBackWith

chai.spy.callsBackWith simply creates a spy that expects the last argument it was called with to be a callback function and calls it with the arguments provided in its constructor.

var methodA = chai.spy.callsBackWith(new Error('foo'));
methodA(cb);
// cb would be called with one argument: new Error('foo')
var methodB = chai.spy.callsBackWith(null, {id:12});
methodB(cb);
// cb would be called with two arguments: null and {id:12}

How to check `with` in recursion calls?

Hey guys,

How can I use to.have.been.called.with? I have a function, which in case of receiving an array as data param, calls itself array.length times.

Like this:

        var spy = chai.spy.on(dataHandler.pubsub, 'emit');
        var data = [
          {id: 123123, a: true, f: 'match'},
          {id: 232323, a: true, f: 'event'},
          {id: 511515, a: false, f: 'lineups'}
        ];
        var promise = dataHandler.save('match', data); // dataHandler.pubsub.emit is called within
        expect(spy).to.have.been.called.exactly(3); // ok
        expect(spy).to.have.been.called.with(->> HOW??? <<-);

Thanks.

Expect nested method to have been called

Is there a way to check that nested method have been called?

class A {
    constructor(b) {
        this.b = b;
    }
    functionA() {
        this.b.aFunctionInOtherClass();
    }
}

I can check that functionA has been called as follows:

const chai = chai.spy.on(a, 'functionA')
expect(spy).to.have.been.called();

But how can I check the aFunctionInOtherClass also have been called?

How to spy on asynchronous calls

I have asynchronous mocha test with spied function being called many times with different parameters.

I'd like to verify the input on first and second calls, then complete the test case. How do you do that with chai-spies?

ChaiSpies with Chai As Promiesed w/o using Timeout

The minimal working example at here

I am using Mocha and Chai with Chai Spies.

I want to test if a method (called ack|nack in the MWE) got called in a promise, so I basically need to use chai-as-promised with chai-spies, but

expect(notificationListener.nack).to.be.eventually.called();

is not allowed.

How can I avoid using setTimeout(()=>expect(notificationListener.nack).to.be.called(), 1000), to mitigate this issue?

Additionally, I cannot return the Promise in my actual code, since it would mess up other stuff.

Cannot attach spy on the same function more than once

I have a suite of tests using chai spies. Basically, every test case attaches a new spy and records the number of times that spy gets called, and with which arguments.
All is fine, until I switch from 0.7.1 to the master branch where I get the following error:

Error: "foo" is already a spy

Here is a simple script that replicates the issue:

const chai = require('chai');
const spies = require('chai-spies');
const { EventEmitter } = require('events');
chai.use(spies);

const emitter = new EventEmitter();

function foo() {
    const spy = chai.spy.on(emitter, 'emit');
};

function bar() {
    const spy = chai.spy.on(emitter, 'emit');
}

foo(); // OK
bar(); // Error: "emit" is already a spy

The above script works fine on version 0.7.1, but throws the error on the master branch. This looks to me like a regression.

I have used Node EventEmitter here, but you can reproduce with any other function.

Regards

expect(...).to.have.been.called.once is not a function

chai version: 4.0.1
chai-spies version: 0.7.1
Node.js version: 6.10.3

I upgraded chai and chair-spies and ran into the following error

expect(spy).to.have.been.called.once() fails with:

Unhandled rejection TypeError: expect(...).to.have.been.called.once is not a function

Would appreciate any help or direction on how to figure this issue out.

Thanks

Feature: called with reports actual arguments

Please include a report to get the called.with assertions which shows which arguments were actually called.

This is a suggestion I came up with:
in spy.js, for any called.with assertion, add the argument spy.calls.find(args => !_.eql(args, expArgs))
not sure if its possible to react to negations - that would be the only problem

      this.assert(
          passed > 0
        , 'expected ' + this._obj + ' to have been called with #{exp}'
        , 'expected ' + this._obj + ' to have not been called with #{exp} but got ' + passed + ' times'
        , expArgs
        , spy.calls.find(args => !_.eql(args, expArgs))
      );

thanks and best regards

chai-spies.js needs a rebuild on master

Come on folks, this one is a baddie. Because of the slow release cycle of this module, folks are depending on installing from master (which is bad enough in of itself). Please get this file up to date with the rest of the repo on master.

Bound functions

Hey guys,

I have an issue during testing bound functions.

// instanceName.onDisconnect = ... this.property = true ...
// ...
let spy = chai.spy.on(instanceName, 'onDisconnect');
instanceName.connection.on('end'  , instanceName.onDisconnect.bind(instanceName));
instanceName.connection.end();
expect(instanceName.property).to.be.ok; // ok
expect(spy).to.have.been.called(); // fail

/* BUT IF! */

let spy = chai.spy.on(instanceName, 'onDisconnect');
instanceName.connection.on('end'  , () => instanceName.onDisconnect());
instanceName.connection.end();
expect(instanceName.property).to.be.ok; // ok
expect(spy).to.have.been.called(); // ok

So as you can see from the example, if function is bound, then it fails, but if it is called directly, then it passes.

I think it is an issue.

Please advise, thanks.

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.