acvetkov / sinon-chrome

Testing chrome extensions with Node.js
ISC License
439 stars 48 forks source link

Stub not working with sinon.match #67

Open crimx opened 6 years ago

crimx commented 6 years ago

I'm having trouble making sinon-chrome stubs work with sinon.match.

I use webpack, karma, mocha and sinon-chai. The spec below may reproduce the error.

It looks like sinon-chrome's stub doesn't recognize sinon.match and treats it like a normal object. The error is "AssertionError: expected stub to have been called with arguments hasOwn("key")%D", while it should be "arguments matching hasOwn("key")%D".

Any idea what went wrong?

describe('Sinon Native Stub', function () {
  it('calledWithMatch + match', function () {
    const stub = sinon.stub()
    stub({key: 'value'})
    stub.should.be.calledWithMatch(sinon.match.hasOwn('key'))
  })
  it('calledWith + match', function () {
    const stub = sinon.stub()
    stub({key: 'value'})
    stub.should.be.calledWith(sinon.match.hasOwn('key'))
  })
  it('withArgs + match', function () {
    const stub = sinon.stub()
    stub({key: 'value'})
    stub.withArgs(sinon.match.hasOwn('key')).should.be.calledOnce
  })
})

describe('Sinon Chrome Stub', function () {
  it('calledWithMatch + match', function () {
    chrome.storage.local.set({key: 'value'})
    chrome.storage.local.set.should.be.calledWithMatch(sinon.match.hasOwn('key'))
  })
  it('calledWith + match', function () {
    chrome.storage.local.set({key: 'value'})
    chrome.storage.local.set.should.be.calledWith(sinon.match.hasOwn('key'))
  })
  it('withArgs + match', function () {
    chrome.storage.sync.set({key: 'value'})
    chrome.storage.sync.set.withArgs(sinon.match.hasOwn('key')).should.be.calledOnce
  })
})

Results:

  Sinon Native Stub
    √calledWithMatch + match
    √calledWith + match
    √withArgs + match

  Sinon Chrome Stub
    √calledWithMatch + match
    ×calledWith + match
        AssertionError: expected stub to have been called with arguments hasOwn("key")%D
    ×withArgs + match
        AssertionError: expected stub to have been called exactly once, but it was called 0 times
acvetkov commented 6 years ago

Is this problem related to https://github.com/acvetkov/sinon-chrome/issues/66 ?

crimx commented 6 years ago

No I think it was related to Sinon. I was using vue-cli which generates Sinon v4.x dependency. I think it might not be compatible with Sinon Chrome.

Anyway I ended up using jest with sinon-chrome and let jest handle the matching,

stoically commented 6 years ago

I've encountered the same issue, it seems that it's not possible to use sinon.match if sinon isn't the very instance sinon-chrome is using internally.

stoically commented 6 years ago

Here's how one can reproduce:

const sinon = require('sinon');
const browser = require('sinon-chrome/webextensions');

browser.tabs.create({foo: 'bar'});

console.log(browser.tabs.create.calledWith({
  foo: sinon.match.string
}));

const otherSinon = require('../1/node_modules/sinon');

console.log(browser.tabs.create.calledWith({
  foo: otherSinon.match.string
}));

Actual result

true
false

Expected result

true
true

Note

This is a rather fabricated example, but I've seen it happen inside just one module since I believe it's still possible that different version reside in the same node_modules folder

A workaround is to pass in your own sinon or use the exposed sinon from sinon-chrome, I'll provide a Pull request for that.

My guess is that sinon does some sort of instanceOf test or something, not sure if this can be solved in a generic way.

crimx commented 6 years ago

I think peer dependency is for this kind of issue. How about making sinon a peerDependency <5.0.0.

stoically commented 6 years ago

I'd agree that's a good idea. This can be a really time-consuming edge-case, compared to an initial "you have to install sinon yourself"-hint to get it working (in a reliable way).