chai-spies icon indicating copy to clipboard operation
chai-spies copied to clipboard

Is there a way to verify the order of functions?

Open henriksjostrom opened this issue 9 years ago • 9 comments
trafficstars

Suppose I have a setup such that a() .then(b) .then(c)

Is there a way to verify that b runs before c using chai-spies?

henriksjostrom avatar Jun 21 '16 12:06 henriksjostrom

I'm not aware of a way to do that with chai-spies. Might want to check out Sinon's .calledBefore and .calledAfter.

meeber avatar Jun 22 '16 02:06 meeber

I think we could consider implementing something similar to calledBefore and calledAfter. Need a sensible way to implement it though, timestamps or some global variable would not be suitable, IMO.

keithamus avatar Jun 22 '16 09:06 keithamus

While I feel like this is a fine feature to add, I have a broader concern about this plugin. What is the long-term goal here?

The README says:

This is an addon plugin for the chai assertion library. It provides the most basic function spy ability and tests. Though useful for small modules, you are probably going to want something more robust. Check out jack for a full featured mock/stub/spy assertion library for use with chai.

This library is primarily meant to serve as a starting point for anyone interested in developing chai plugins. If developing a module, you are welcome to use this as a starting point. I also encourage the use of the compile tools to allow modules to work both in node.js and the browser.

Although jack didn't really take off, sinon did, and when combined with sinon-chai it seems to meld nicely with chai. I'm wondering if we'd be best served keeping this plugin mostly as-is, and encouraging the use of sinon and sinon-chai for advanced usage. With so much needing to be done on Chai core, I'm concerned about dedicating time to this plugin just to duplicate functionality in sinon.

Thoughts?

meeber avatar Jun 22 '16 10:06 meeber

While I feel like this is a fine feature to add, I have a broader concern about this plugin. What is the long-term goal here?

I personally have no long term goal for chai-spies. I think as and when people want features we can consider them. But if you'd like to formulate a more concrete goal then I'd be happy to hear some ideas.

With so much needing to be done on Chai core, I'm concerned about dedicating time to this plugin just to duplicate functionality in sinon.

I don't want this to sound rude - but it's a little hard to convey it with text: If you don't want to work on chai-spies, don't! I don't want to dictate a hard structure for what people are going to work on and what they're not. We can set goals and if people agree on that direction, great. I would be horrified to find out a maintainer of any of the chai projects feels a sense of duty to do work they don't want to. It should be a scratch-your-own-itch kind of thing.

Personally I use chai-spies over sinon, because it's a simpler, smaller codebase and I can manage that easier, therefore I am happy to spend my time on it. I hope everyone who comments and writes code for it feels the same way.

keithamus avatar Jun 22 '16 10:06 keithamus

I contribute out of enjoyment not obligation. Definitely not my intention to suggest otherwise or establish a negative tone. I'll blame it on poor wording of my final sentence in my previous post :D

I'll gather my thoughts on chai-spies and present them in a seperate post so as not to derail this topic any further!

meeber avatar Jun 22 '16 12:06 meeber

Any news on this? I'd like to help in the implementation of . calledBefore/After if needed, do you have ideas on the possible design?

Just to know what I really need is a way to check that a single spy gets called multiple times with an ordered list of parameter, eg:

const fn = v => `_${v}`;
const spy = chai.spy(fn);

[1, 2, 3].forEach(i => spy(i));

// check that has been called 3 times
expect(spy).to.have.been.called.exactly(3);

// check that is called with all the parameters in the array (no guarantee on the order)
expect(spy).to.have.been.called.with(1);
expect(spy).to.have.been.called.with(2);
expect(spy).to.have.been.called.with(3);

// check that the order is correct
expect(spy.__spy.calls).to.deep.equal([[1], [2], [3]]);

I'll see if I can find a reasonable way to add an assertion like .calledWithParamOrder(a, ..., n), can this be useful?

teone avatar Aug 05 '16 15:08 teone

@teone we still need to hash out some requirements before we discuss an implementation.

It seems as though @henriksjostrom's original posting suggests they want to have some kind of global registry of all spy calls to determine an order in which any spy gets called, e.g:

const spyA = chai.spy();
const spyB = chai.spy();
const spyC = chai.spy();
spyA();
spyB();
spyC();
expect(spyA).to.be.called.before(spyB).and.before(spyC);
expect(spyB).to.be.called.before(spyC).but.called.after(spyA);
expect(spyC).to.be.called.after(spyB).and.called.after(spyA);

It seems what you're suggesting is slightly different: my interpretation (please correct me if I'm wrong) is that you'd like to tell when a particular spy has been called with a set of arguments. So for example:

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');

These are to different features, both valid, but if you'd like the latter - we should raise a separate issue for it, so we can discuss that one too 😄

keithamus avatar Aug 05 '16 17:08 keithamus

Yes, you're right, I'll move the discussion in another issue.

teone avatar Aug 05 '16 18:08 teone

Since sandboxes are now supported this should not be too hard. Right? 😁

Daghall avatar Jun 07 '18 09:06 Daghall