Sinon: v7.2.0 рд░рд┐рд▓реАрдЬ рдХреЗ рдмрд╛рдж рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд░реВрдк рд╕реЗ рд╡рд┐рдлрд▓ рдкрд░реАрдХреНрд╖рдг

рдХреЛ рдирд┐рд░реНрдорд┐рдд 23 рдЬреБрд▓ре░ 2019  ┬╖  11рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: sinonjs/sinon

рдмрдЧ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ
рд╕рд┐рдиреЙрди рдХреЛ рдирд╡реАрдирддрдо v7 рд░рд┐рд▓реАрдЬ рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдиреЗ рд╕реЗ рдХреБрдЫ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╡рд┐рдлрд▓рддрд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВред рдПрдХрдорд╛рддреНрд░ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдкрд░рд┐рд╡рд░реНрддрди рдЬрд┐рд╕реЗ рдореИрдВ рдкрд╣рдЪрд╛рдирдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛ рд╡рд╣ рдерд╛ рдпрд╣ рдкреАрдЖрд░: #1955 - deep-equal.js рдХреЛ samsam.deepEqual рдмрджрд▓рдирд╛ред
рдкрд░реАрдХреНрд╖рдг 7.2.0 рддрдХ рд╕рднреА рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдкрд░ рдкрд╛рд╕ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, 7.1.1 (рдПрдХ рд░рд┐рд▓реАрдЬрд╝ рдмреИрдХ) рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдиреЗ рд╕реЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ рдФрд░ рд╕рднреА рдкрд░реАрдХреНрд╖рдг рдкрд╛рд╕ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред

рджреЗрдЦреА рдЧрдИ рддреНрд░реБрдЯрд┐:

AssertionError: expected addTracks to have been called with arguments [{ language: "en", trackContentType: "CEA608" }]
[[functionStub] { language: "en", trackContentType: "CEA608" }] [{ language: "en", trackContentType: "CEA608" }]

рдкрд░реАрдХреНрд╖рдг рдЙрддреНрдкрд╛рджрди рддреНрд░реБрдЯрд┐:

    it('should call getTextTracksManager, Track, and setCaptionLang', () => {
      sinonSandbox.stub(chromecastReceiver, 'setCaptionLang');
      chromecastReceiver.player.getTextTracksManager = sinonSandbox.stub()
        .returns({ addTracks: sinonSandbox.spy() });
      sinonSandbox.stub(cast.framework.messages, 'Track').returns(() => ({}));

      chromecastReceiver.loadCaptions('off');

      expect(chromecastReceiver.player.getTextTracksManager).to.have.callCount(1);
      expect(cast.framework.messages.Track).to.have.been
        .calledWith(3, cast.framework.messages.TrackType.TEXT);
      expect(chromecastReceiver.textTracksManager.addTracks).to.have.been.calledWith([{
        trackContentType: cast.framework.messages.CaptionMimeType.CEA608,
        language: 'en',
      }]);
      expect(chromecastReceiver.setCaptionLang).to.have.been.calledWith('off');
    });

рдкреНрд░рдЬрдирди рдХрд░рдирд╛
рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдкреБрди: рдкреЗрд╢ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрджрдо:

  1. 7.1.1 . рд╕реЗ рдКрдкрд░ рдХреЗ рдХрд┐рд╕реА рднреА рд╕рд┐рдиреЙрди рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
  2. рдирдореВрдирд╛ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдПрдБ (рдКрдкрд░)
  3. рддреНрд░реБрдЯрд┐ рджреЗрдЦреЗрдВ

рдЕрдкреЗрдХреНрд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░
рдЯреЗрд╕реНрдЯ рдкрд╛рд╕ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП

рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ
рдпрджрд┐ рд▓рд╛рдЧреВ рд╣реЛ, рддреЛ рдЕрдкрдиреА рд╕рдорд╕реНрдпрд╛ рд╕рдордЭрд╛рдиреЗ рдореЗрдВ рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рд▓рд┐рдП рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ рдЬреЛрдбрд╝реЗрдВред

рдкреНрд░рд╕рдВрдЧ (рдХреГрдкрдпрд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдВ):

  • рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕рдВрд╕реНрдХрд░рдг: 7.2.0+
  • рдкрд░реНрдпрд╛рд╡рд░рдг: рдореИрдХреЛрдЬрд╝ 10.14.5

рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдореИрдВ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред

Bug Regression pinned

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рд╣рд╛рдп @ fatso83 ,

рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рд╕рдордп рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдЬреИрд╕рд╛ рдЖрдкрдиреЗ рдореБрдЭрд╕реЗ рдкреВрдЫрд╛ рдерд╛ рдореИрдВрдиреЗ рд╡реИрд╕рд╛ рд╣реА рдХрд┐рдпрд╛ рдФрд░ рдПрдХ рд░рдирдХрд┐рдЯ рдбреЗрдореЛ рдмрдирд╛рдпрд╛ рдЬреЛ рдмрдЧ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдмрд╕ рдЕрд▓рдЧ-рдЕрд▓рдЧ require('sinon') рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдкрд░ рдХрдореЗрдВрдЯ/рдЕрдирдХрдореЗрдВрдЯ рдХрд░реЗрдВ рдФрд░ рдмрдЧ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд░рди рдХрд░реЗрдВред

https://runkit.com/danielkg/sinon-issue-reproducible-bug-template

рдореИрдВ рдпрд╣рд╛рдВ рдХреЛрдб рднреА рдкреЛрд╕реНрдЯ рдХрд░рддрд╛ рд╣реВрдВ, рдЕрдЧрд░ рдХрд┐рд╕реА рднреА рдХрд╛рд░рдг рд╕реЗ рд░рдирдХрд┐рдЯ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

// Employs 'mini-mocha' to emulate running in the Mocha test runner (mochajs.org)
require("@fatso83/mini-mocha").install();
// const sinon = require('[email protected]'); // WORKS!
const sinon = require('[email protected]'); // FAILS!
// const sinon = require('sinon');       // FAILS!
const { assert } = require('@sinonjs/referee');

const SAMPLE_USER = {
    id: 1,
    name: 'Kid',
    age: 22,
    weight: 83.5,
    notes: [{ txt: 'abc' }, { txt: 'def' }, { txt: 'ghi' }],
};

class MyUser {
    constructor(id, name, age, weight, notes = []) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.notes = notes;
    }
}

const createFakeUser = overrides => ({
    id: '007',
    name: 'Bond',
    ...overrides,
});

class Talkie {
    talk(user, topic) {
        console.log('talked to', user.name, 'about', topic);
    }
}

const action = (userId, talkie) => {
    const { name, age, weight, notes } = SAMPLE_USER;
    const user = new MyUser(userId, name, age, weight, notes);

    talkie.talk(user, 'apples');

    return user;
}


describe('stubbing', () => {
    const talkie = new Talkie();

    afterEach(() => {
        sinon.restore();
    });

    beforeEach(() => {
        sinon.spy(talkie, 'talk');
    });

    it('is the same user', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        assert.equals(JSON.stringify(userA), JSON.stringify(userB));
    });

    it('should set the return value', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        sinon.assert.calledWith(talkie.talk, userB, sinon.match.string);
    });
});

рдЬрдм рдЖрдкрдХреЗ рдкрд╛рд╕ рд╕рдордп рд╣реЛ рддреЛ рдХреГрдкрдпрд╛ рдПрдХ рдФрд░ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдзрдиреНрдпрд╡рд╛рджред

рд╕рдзрдиреНрдпрд╡рд╛рдж,
рдбреИрдирд┐рдпрд▓

рд╕рднреА 11 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдЖрдо рддреМрд░ рдкрд░ рдорд╣рд╛рди рдмрдЧ рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕рдХреА рдПрдХ рдмрдбрд╝реА рдХрдореА рд╣реИ: рдореИрдВ рд╕рддреНрдпрд╛рдкрди рдпрд╛ рдмрдЧ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХрд╛ рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рдЪрд▓рд╛ рд╕рдХрддрд╛! рдпрд╣ рдЕрдкрдиреЗ рдЖрдк рдЪрд▓рдиреЗ рдпреЛрдЧреНрдп рдирд╣реАрдВ рд╣реИ, рдФрд░ рдкреБрдирд░реБрддреНрдкрд╛рджрди рдХреЗ рддрд░реАрдХреЗ рдХреЗ рдмрд┐рдирд╛, рдЗрд╕реЗ рдареАрдХ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред

рдХреНрдпрд╛ рдЖрдк рдкреНрд░рдЬрдирди рдХреЗ рд▓рд┐рдП рдиреНрдпреВрдирддрдо рдЙрдореНрдореАрджрд╡рд╛рд░ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ? рдЖрдкрдХреЛ var myObject = { aMethod: function(){}, aProp: 42 }; // etc рдЬреИрд╕реЗ рд╕рд░рд▓реАрдХрд░рдг рдХреА рддрд░рд╣ рдкреВрд░реЗ рдореВрд▓ рдЙрджрд╛рд╣рд░рдг рдХреЛ рджреЛрд╣рд░рд╛рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рдирд╣реАрдВ рд╣реИред

рдЕрдЧрд░ рд╣рдо рдЬрд╛рдирддреЗ рдереЗ рдХрд┐ рдпрд╣ рдЯреВрдЯ рд░рд╣рд╛ рд╣реИ, рддреЛ рд╣рдо рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдкреНрд░рдореБрдЦ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдКрдкрд░ рдЙрдард╛рдПрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдПрдХ рд░рд┐рдЧреНрд░реЗрд╢рди рдЯреЗрд╕реНрдЯ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛!

PS рд▓рдЧрддрд╛ рд╣реИ рдЬреИрд╕реЗ sinon-chai рднреА рд╢рд╛рдорд┐рд▓ рд╣реИред рдпрд╣ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдиреЗ рд▓рд╛рдпрдХ рд╣реИред

@ fatso83 рдореБрдЭреЗ рджреЗрдЦрдиреЗ рджреЛ рдХрд┐ рдореИрдВ рдкреНрд░рдЬрдирди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ, рдЪрд▓рдиреЗ рдпреЛрдЧреНрдп рдЙрджрд╛рд╣рд░рдг рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ

рдХреЛрдИ рдЕрдкрдбреЗрдЯреНрд╕?

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреБрд░рд╛рдиреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рд╣рд╛рд▓ рдХреА рдЧрддрд┐рд╡рд┐рдзрд┐ рдирд╣реАрдВ рд╣реИред рдЖрдЧреЗ рдХреЛрдИ рдЧрддрд┐рд╡рд┐рдзрд┐ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЖрдкрдХреЗ рдпреЛрдЧрджрд╛рдиреЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред

@mantoni рдХреНрдпрд╛ рдЖрдкрдиреЗ рдЕрдкрдиреА рдХрд┐рд╕реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдРрд╕рд╛ рдХреБрдЫ рд╣реЛрдиреЗ рдХрд╛ рдЕрдиреБрднрд╡ рдХрд░рдиреЗ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдирд╣реАрдВ рдХреА?

рдЕрдкрдбреЗрдЯ рдХреА рдХрдореА рдХреЗ рд▓рд┐рдП рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рдореИрдВ рдЕрдм рдЙрд╕ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реЗ рд╕рдВрдмрджреНрдз рдирд╣реАрдВ рд╣реВрдВ рдЬрд┐рд╕рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рдереАред рдЕрдЧрд░ рдХрд┐рд╕реА рдФрд░ рдХреЛ рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд░рд╣рд╛ рд╣реИ, рддреЛ рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╡реЗ рд░реЗрдкреНрд░реЛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХреЗрдВ

@ fatso83 рдореБрдЭреЗ рдПрдХ рд╣реА рдореБрджреНрджреЗ рдкрд░ рдЪрд▓рдиреЗ рдХреА рдпрд╛рдж рдирд╣реАрдВ рд╣реИред рдореИрдВрдиреЗ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдХреБрдЫ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдирд╡реАрдирддрдо рд╕рд┐рдиреЙрди рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд┐рдпрд╛ рд╣реИред

рдкреБрди: рдкреЗрд╢ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдмрдВрдж рдХрд░рдирд╛

рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдореГрддрдХреЛрдВ рдореЗрдВ рд╕реЗ рдкреБрдирд░реНрдЬреАрд╡рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдЙрд╕реА рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рднрд╛рдЧ рд░рд╣рд╛ рд╣реВрдВред

_рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ рдЪрд┐рддреНрд░рдг рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд░рд▓ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред_

рдореЗрд░реЗ рдЖрд╡реЗрджрди рдореЗрдВ рдореЗрд░реЗ рдкрд╛рд╕ рдпрд╣ рд╡рд░реНрдЧ рд╣реИ

class MyUser {
  // ... some user properties  
}

рдФрд░ рдореИрдВ рдЗрд╕реЗ рдмрд╛рдж рдореЗрдВ рдХреЛрдЖ рдирд┐рдпрдВрддреНрд░рдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ

const mqClient = require('./mqClient');

// GET /userDetails/<id> endpoint
async function getUserDetailsController(req, res) {
  const user = new MyUser();

  // populate user with properties etc.
  user.id = '1';
  user.name = 'Hans Gruber';
  user.tasks = [{ id: '42', title: 'execute Nakatomi tower heist' }];

  // ... get more details ...

  // Notify other users about this user
  mqClient.notifyOthers(user);

  res.json({ ok: true, user });
}

рдФрд░ рдореЗрд░реЗ getUserDetailsController.test.js рдореИрдВ рдРрд╕рд╛ рдХреБрдЫ рдХрд░рддрд╛ рд╣реВрдВ:

const mqClient = require('./mqClient');

const createExpectedUser = overrides => {
  id: '1',
  name: 'Hans Gruber',
  tasks: [{ id: '42', title: 'execute Nakatomi tower heist' }],
  ...overrides
};

it('does not fail', async () => {
  sinon.spy(mqClient, 'notifyOthers');

  const expectedUser = createExpectedUser();

  await presetRequest // helper object to run the controller code
    .get('/userDetails/1')
    .expect(200);

  // This works with sinon 7.1.1.
  // This fails with sinon 7.2.0 and onwards.
  sinon.assert.calledWithMatch(mqClient.notifyOthers, expectedUser);
});

рдореИрдВрдиреЗ рдЗрд╕реЗ sinon 7.1.1 (рдЬреЛ samsam "2.13" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ) рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛, рдФрд░ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╕рдВрд╕реНрдХрд░рдг 7.2.0 рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ ( samsam 3.3.3 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)ред
рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг 9.2.3 рднреА рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ ( samsam 5.3.0 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)ред

рдореИрдВ рдиреЛрдб 14.5.3 рдкрд░ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдиреЛрдб 12.20.0 рдкрд░ рднреА рд╣реЛрддрд╛ рд╣реИред

рдореИрдВ рддреБрд▓рдирд╛ рдореЗрдВ user рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рдФрд░ expectedUser рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ JSON.stringify рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдФрд░ 100 рд╡реЗ рдХрд░ рд░рд╣реЗ рд╣реИрдВ% рдХреЗ рдмрд░рд╛рдмрд░ред рд╡рд╛рдХреНрдп рд░рдЪрдирд╛рддреНрдордХ рд░реВрдк рд╕реЗ рдПрдХрдорд╛рддреНрд░ рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдирд┐рдпрдВрддреНрд░рдХ рдХрдХреНрд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╡рд╕реНрддреБ рдХрд╛ рд╢рд╛рдмреНрджрд┐рдХ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред

рдХреНрдпрд╛ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рдРрд╕рд╛ рдХреНрдпреЛрдВ рд╣реЛрддрд╛ рд╣реИ? рдпрд╛ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдЗрд╕ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ?

рд╕рдзрдиреНрдпрд╡рд╛рдж,
рдбреИрдирд┐рдпрд▓

рдЬрдм рддрдХ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЗрд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ, рддрдм рддрдХ рд╣рдо рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдЦрд╛рд▓реА рдШрдВрдЯреЗ рдЦрд░реНрдЪ рдХрд░рдиреЗ рдХреЛ рдЙрдЪрд┐рдд рдирд╣реАрдВ рдард╣рд░рд╛ рд╕рдХрддреЗ, рдореБрдЭреЗ рдбрд░ рд╣реИред рдореЗрд░реЗ рдкрд╛рд╕ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдФрд░ рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдХрд┐ рдореИрдВ рд╕рд╣реА рдерд╛ред

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореБрдЭреЗ рдмрдЧ рдареАрдХ рдХрд░рдирд╛ рдкрд╕рдВрдж рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдк рдХреБрдЫ рдРрд╕рд╛ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдореЗрдВ рдХреБрдЫ рд╕рдордп рдмрд┐рддрд╛ рд╕рдХрддреЗ рд╣реИрдВ _рдореИрдВ рдЪрд▓рд╛ рд╕рдХрддрд╛ рд╣реВрдБ, рддреЛ рдРрд╕рд╛ рдХрд░реЗрдВ! рд░рдирдХрд┐рдЯ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмреЗрд╣рддрд░реАрди рд╕реЗрд╡рд╛ рд╣реИ: https://runkit.com/fatso83/sinon-issue-reproducible-bug-template

рд╣рд╛рдп @ fatso83 ,

рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рд╕рдордп рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдЬреИрд╕рд╛ рдЖрдкрдиреЗ рдореБрдЭрд╕реЗ рдкреВрдЫрд╛ рдерд╛ рдореИрдВрдиреЗ рд╡реИрд╕рд╛ рд╣реА рдХрд┐рдпрд╛ рдФрд░ рдПрдХ рд░рдирдХрд┐рдЯ рдбреЗрдореЛ рдмрдирд╛рдпрд╛ рдЬреЛ рдмрдЧ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдмрд╕ рдЕрд▓рдЧ-рдЕрд▓рдЧ require('sinon') рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдкрд░ рдХрдореЗрдВрдЯ/рдЕрдирдХрдореЗрдВрдЯ рдХрд░реЗрдВ рдФрд░ рдмрдЧ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд░рди рдХрд░реЗрдВред

https://runkit.com/danielkg/sinon-issue-reproducible-bug-template

рдореИрдВ рдпрд╣рд╛рдВ рдХреЛрдб рднреА рдкреЛрд╕реНрдЯ рдХрд░рддрд╛ рд╣реВрдВ, рдЕрдЧрд░ рдХрд┐рд╕реА рднреА рдХрд╛рд░рдг рд╕реЗ рд░рдирдХрд┐рдЯ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред

// Employs 'mini-mocha' to emulate running in the Mocha test runner (mochajs.org)
require("@fatso83/mini-mocha").install();
// const sinon = require('[email protected]'); // WORKS!
const sinon = require('[email protected]'); // FAILS!
// const sinon = require('sinon');       // FAILS!
const { assert } = require('@sinonjs/referee');

const SAMPLE_USER = {
    id: 1,
    name: 'Kid',
    age: 22,
    weight: 83.5,
    notes: [{ txt: 'abc' }, { txt: 'def' }, { txt: 'ghi' }],
};

class MyUser {
    constructor(id, name, age, weight, notes = []) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.notes = notes;
    }
}

const createFakeUser = overrides => ({
    id: '007',
    name: 'Bond',
    ...overrides,
});

class Talkie {
    talk(user, topic) {
        console.log('talked to', user.name, 'about', topic);
    }
}

const action = (userId, talkie) => {
    const { name, age, weight, notes } = SAMPLE_USER;
    const user = new MyUser(userId, name, age, weight, notes);

    talkie.talk(user, 'apples');

    return user;
}


describe('stubbing', () => {
    const talkie = new Talkie();

    afterEach(() => {
        sinon.restore();
    });

    beforeEach(() => {
        sinon.spy(talkie, 'talk');
    });

    it('is the same user', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        assert.equals(JSON.stringify(userA), JSON.stringify(userB));
    });

    it('should set the return value', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        sinon.assert.calledWith(talkie.talk, userB, sinon.match.string);
    });
});

рдЬрдм рдЖрдкрдХреЗ рдкрд╛рд╕ рд╕рдордп рд╣реЛ рддреЛ рдХреГрдкрдпрд╛ рдПрдХ рдФрд░ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдзрдиреНрдпрд╡рд╛рджред

рд╕рдзрдиреНрдпрд╡рд╛рдж,
рдбреИрдирд┐рдпрд▓

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

JakobJingleheimer picture JakobJingleheimer  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

fearphage picture fearphage  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

brettz9 picture brettz9  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

NathanHazout picture NathanHazout  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

stephanwlee picture stephanwlee  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ