I am able to mock modules using jest easily like:
import * as PubNub from 'pubnub';
jest.mock('pubnub', () =>
jest.fn().mockImplementation(() => {
mockPubnubInstance = {
addListener(options) {
mockPubnubListener(options);
},
publish() {
return Promise.resolve({});
},
subscribe: jest.fn(),
history(params, callback) {
return mockHistory(params, callback);
},
};
return mockPubnubInstance;
}),
);
How do I do it in Cypress?
cy.stub('pubnub', 'publish').returns(Promise.resolve({}))
I tried looking at Cypress stub but it does not seem to work.
Add a visitWithStubs
command in cypress/support/commands.js
:
Cypress.Commands.add('visitWithStubs', (url, stubs) => {
if (!stubs) return cy.visit(url);
cy.visit(url, {
onBeforeLoad(win) {
Object.entries(stubs).forEach(([name, stubCallback]) => {
let target = undefined;
Object.defineProperty(win, name, {
// on set, stub the object
set: (object) => {
target = object;
stubCallback(target);
},
// on get, return the stubbed object
get: () => target,
});
});
},
});
});
Now if you expose the imported object on window
import PubNub from 'pubnub';
window.PubNub = PubNub
PubNub.subscribe();
You can stub it like this:
// pubnub.spec.js
describe('visitWithStubs', () => {
it('lets you stub stuff', () => {
cy.visitWithStubs('/pubnub-page', {
PubNub: (PubNub) => {
cy.stub(PubNub, 'addListener', mockPubnubListener);
cy.stub(PubNub, 'publish').resolves({});
cy.stub(PubNub, 'subscribe').as('subscribe');
cy.stub(PubNub, 'history', mockHistory);
},
});
cy.get('@subscribe').should('have.been.called');
});
});
Cypress use sinon
internally as its stub and spy library. Here is the unit test solution:
index.ts
:
import PubNub from 'pubnub';
export const pubnub = new PubNub({
publishKey: 'demo',
subscribeKey: 'demo'
});
export function publish() {
function publishSampleMessage() {
console.log("Since we're publishing on subscribe connectEvent, we're sure we'll receive the following publish.");
var publishConfig = {
channel: 'hello_world',
message: {
title: 'greeting',
description: 'hello world!'
}
};
pubnub.publish(publishConfig, function(status, response) {
console.log(status, response);
});
}
pubnub.addListener({
status: function(statusEvent) {
if (statusEvent.category === 'PNConnectedCategory') {
publishSampleMessage();
}
},
message: function(msg) {
console.log(msg.message.title);
console.log(msg.message.description);
},
presence: function(presenceEvent) {
// handle presence
}
});
console.log('Subscribing..');
pubnub.subscribe({
channels: ['hello_world']
});
}
index.spec.ts
:
/// <reference types="Cypress" />
import { publish, pubnub } from './';
describe('59170422', () => {
it('should pass', () => {
const logSpy = cy.spy(console, 'log');
const addListenerStub = cy.stub(pubnub, 'addListener');
const publishStub = cy.stub(pubnub, 'publish').resolves({});
const subscribeStub = cy.stub(pubnub, 'subscribe');
publish();
addListenerStub.yieldTo('status', { category: 'PNConnectedCategory' });
expect(addListenerStub).to.have.been.calledOnce;
expect(publishStub).to.have.been.calledOnce;
expect(subscribeStub).to.have.been.calledOnce;
publishStub.yield(200, 'haha');
expect(logSpy).to.have.been.calledWith(200, 'haha');
addListenerStub.yieldTo('message', { message: { title: 'I am title', description: 'I am description' } });
expect(logSpy).to.have.been.calledWith('I am title');
expect(logSpy).to.have.been.calledWith('I am description');
});
});
Unit test result:
====================================================================================================
(Run Starting)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Cypress: 3.8.0 │
│ Browser: Electron 78 (headless) │
│ Specs: 1 found (stackoverflow/59170422/index.spec.ts) │
│ Searched: cypress/integration/stackoverflow/59170422/index.spec.ts │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
────────────────────────────────────────────────────────────────────────────────────────────────────
Running: stackoverflow/59170422/index.spec.ts (1 of 1)
59170422
✓ should pass (66ms)
1 passing (202ms)
(Results)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Tests: 1 │
│ Passing: 1 │
│ Failing: 0 │
│ Pending: 0 │
│ Skipped: 0 │
│ Screenshots: 0 │
│ Video: true │
│ Duration: 0 seconds │
│ Spec Ran: stackoverflow/59170422/index.spec.ts │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
(Video)
- Started processing: Compressing to 32 CRF
- Finished processing: /Users/ldu020/workspace/github.com/mrdulin/cypress-codebase (1 second)
/cypress/videos/stackoverflow/59170422/index.spec.ts.mp4
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✔ stackoverflow/59170422/index.spec.t 184ms 1 1 - - - │
│ s │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
✔ All specs passed! 184ms 1 1 - - -
Source code: https://github.com/mrdulin/cypress-codebase/tree/master/cypress/integration/stackoverflow/59170422
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With