how to test cheerio js - javascript

this is my code and i don't know how to write test for it:
html.js
const getHtml = async (url) => {
const { data } = await axios.get(url);
return data;
};
const cheerioInit = async (url) => cheerio.load(await getHtml(url));
module.exports = {
cheerioInit,
getHtml
};
i think i should mock this, but don't know how to do that. i wrote this but getting error:
const htmlJs = require("./html");
describe("html", () => {
it("initializes cheerio js", () => {
const mock = jest.spyOn(htmlJs, "cheerioInit");
expect(mock).toHaveBeenCalled();
});
});
this is error:

You can use jest.spyOn(object, methodName) to mock axios.get() method and its resolved value and mock cheerio.load() method with a fake implementation. After executing the getHtml and cheerioInit functions, make assertion for above mocks to check if they have been called with specific arguments.
E.g.
html.js:
const axios = require('axios');
const cheerio = require('cheerio');
const getHtml = async (url) => {
const { data } = await axios.get(url);
return data;
};
const cheerioInit = async (url) => cheerio.load(await getHtml(url));
module.exports = {
cheerioInit,
getHtml,
};
html.test.js:
const { getHtml, cheerioInit } = require('./html');
const axios = require('axios');
const cheerio = require('cheerio');
describe('html', () => {
afterEach(() => {
jest.restoreAllMocks();
});
describe('getHtml', () => {
it('should get html', async () => {
const getSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({ data: '<div>teresa teng</div>' });
const actual = await getHtml('http://localhost:3000');
expect(actual).toEqual('<div>teresa teng</div>');
expect(getSpy).toBeCalledWith('http://localhost:3000');
});
});
describe('cheerioInit', () => {
it('should initializes cheerio', async () => {
const loadSpy = jest.spyOn(cheerio, 'load').mockImplementation();
const getSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({ data: '<div>teresa teng</div>' });
await cheerioInit('http://localhost:3000');
expect(loadSpy).toHaveBeenCalledWith('<div>teresa teng</div>');
});
});
});
unit test result:
PASS examples/66304918/html.test.js
html
getHtml
✓ should get html (3 ms)
cheerioInit
✓ should initializes cheerio
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
html.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 4.088 s

Related

Stub of Sinon using axios returns undefined

I'm testing using sinon with axios.
// index.js
{
.. more code
const result = await axios.get("http://save")
const sum = result.data.sum
}
And I made a test code by sinon and supertest for e2e test.
// index.test.js
describe('ADMINS GET API, METHOD: GET', () => {
it('/admins', async () => {
sandbox
.stub(axios, 'get')
.withArgs('http://save')
.resolves({sum: 12});
await supertest(app)
.get('/admins')
.expect(200)
.then(async response => {
expect(response.body.code).toBe(200);
});
});
});
But when I test it, it gives me this result.
// index.js
{
.. more code
const result = await axios.get("http://save")
const sum = result.data.sum
console.log(sum) // undefined
}
I think I resolved response. But it doesnt' give any response.
It just pass axios on supertest.
How can I return correct data in this case?
Thank you for reading it.
The resolved value should be { data: { sum: 12 } }.
E.g.
index.js:
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/admins', async (req, res) => {
const result = await axios.get('http://save');
const sum = result.data.sum;
res.json({ code: 200, sum });
});
module.exports = { app };
index.test.js:
const supertest = require('supertest');
const axios = require('axios');
const sinon = require('sinon');
const { app } = require('./index');
describe('ADMINS GET API, METHOD: GET', () => {
it('/admins', async () => {
const sandbox = sinon.createSandbox();
sandbox
.stub(axios, 'get')
.withArgs('http://save')
.resolves({ data: { sum: 12 } });
await supertest(app)
.get('/admins')
.expect(200)
.then(async (response) => {
sinon.assert.match(response.body.code, 200);
sinon.assert.match(response.body.sum, 12);
});
});
});
test result:
ADMINS GET API, METHOD: GET
✓ /admins
1 passing (22ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------

Stubing AWS SQS client

Im trying to stub aws-sdk/client-sqs calls. Im both new to aws and stubbing and I cant find much in the docs to do with stubbing using mocha/chai
My file
import { SQSClient, ReceiveMessageCommand, DeleteMessageCommand } from '#aws-sdk/client-sqs'
const sqsClient = new SQSClient()
const params = {
AttributeNames: ['SentTimestamp'],
MaxNumberOfMessages: 10,
QueueUrl: paymentsUrl,
//....more params
}
const getPolledMessages = async sqsClient => {
const data = await sqsClient.send(new ReceiveMessageCommand(params))
//....continue to do stuff with the data
}
My test is as below. I heavily borrowed from this test which stubs #aws-sdk/client-ses
import { ReceiveMessageCommand, SQSClient } from '#aws-sdk/client-sqs'
import { expect } from 'chai'
describe('mock sqs', () => {
let stub;
before(() => {
stub = sinon.stub(SQSClient.prototype, 'ReceiveMessageCommand')
})
after(() => stub.restore())
it('can send', async () => {
await SQSClient.send(new ReceiveMessageCommand(params))
expect(stub.calledOnce).to.be.true
})
})
Currently getting the following error
TypeError: Cannot stub non-existent property ReceiveMessageCommand
at Function.stub (node_modules/sinon/lib/sinon/stub.js:73:15)
at Sandbox.stub (node_modules/sinon/lib/sinon/sandbox.js:333:37)
You can stub out dependencies with link seams.. We should use proxyquire package to do that.
E.g.
index.ts:
import { SQSClient, ReceiveMessageCommand } from '#aws-sdk/client-sqs';
const sqsClient = new SQSClient({ region: 'REGION' });
const params = {
AttributeNames: ['SentTimestamp'],
MaxNumberOfMessages: 10,
QueueUrl: 'paymentsUrl',
};
export const getPolledMessages = async () => {
const data = await sqsClient.send(new ReceiveMessageCommand(params));
};
index.test.ts:
import proxyquire from 'proxyquire';
import sinon from 'sinon';
describe('68017252', () => {
it('should pass', async () => {
const sqsClientInstance = {
send: sinon.stub(),
};
const SQSClient = sinon.stub().returns(sqsClientInstance);
const ReceiveMessageCommand = sinon.stub();
const { getPolledMessages } = proxyquire('./', {
'#aws-sdk/client-sqs': {
SQSClient,
ReceiveMessageCommand,
},
});
await getPolledMessages();
sinon.assert.calledWithExactly(SQSClient, { region: 'REGION' });
sinon.assert.calledOnce(sqsClientInstance.send);
sinon.assert.calledWithExactly(ReceiveMessageCommand, {
AttributeNames: ['SentTimestamp'],
MaxNumberOfMessages: 10,
QueueUrl: 'paymentsUrl',
});
});
});
test result:
68017252
✓ should pass (3331ms)
1 passing (3s)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------

Mocking method of instance with Jest

How to mock the call of service.request in the code bellow?
import url from 'url'
import jayson from 'jayson/promise'
export async function dispatch(webHook, method, payload) {
const service = jayson.Client.https({ ...url.parse(webHook) })
return service.request(method, { ...payload })
}
In my unit-test I want to do something like this
jest.mock("") // what should go here?
it(() => {
const method = 'test'
expect(request).toHaveBeenCalledWith(method...) ?
})
UPDATE
I updated with my findings my code, but still no luck
import { Client } from 'jayson/promise'
import { dispatch } from '../src/remote'
jest.mock('jayson')
describe('remote', () => {
let spy: jest.SpyInstance<any>
beforeEach(() => {
spy = jest.spyOn(Client.https.prototype, 'request')
})
afterEach(() => {
spy.mockClear()
})
it('should invoke request method', () => {
const url = 'http://example.com:8000'
const method = ''
const payload = {}
dispatch(url, method, payload)
expect(spy).toHaveBeenCalledWith({})
})
})
You can use jest.mock to mock jayson/promise module. Don't need to use jest.spyOn.
E.g.
index.ts:
import url from 'url';
import jayson from 'jayson/promise';
export async function dispatch(webHook, method, payload) {
const service = jayson.Client.https({ ...url.parse(webHook) });
return service.request(method, { ...payload });
}
index.test.ts:
import { dispatch } from './';
import jayson, { HttpsClient } from 'jayson/promise';
import { mocked } from 'ts-jest';
jest.mock('jayson/promise');
const httpsClientMock = mocked(jayson.Client.https);
describe('65924278', () => {
afterAll(() => {
jest.resetAllMocks();
});
it('should pass', async () => {
const url = 'http://example.com:8000';
const method = '';
const payload = {};
const serviceMock = ({
request: jest.fn(),
} as unknown) as HttpsClient;
httpsClientMock.mockReturnValueOnce(serviceMock);
await dispatch(url, method, payload);
expect(jayson.Client.https).toBeCalledTimes(1);
expect(serviceMock.request).toBeCalledWith('', {});
});
});
unit test result:
PASS examples/65924278/index.test.ts (10.748 s)
65924278
√ should pass (13 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 13.15 s

Jest: Mock class method in a function

So just trying to understand how I mock a class function within a function itself. How do I mock the data returned from the exchange.someFunction() method so I can test the actual getPositions() function itself?
const library = require('library');
const exchange = new library.exchange_name();
async function getPositions() {
let positions = [];
const results = await exchange.someFunction();
// Do some stuff
return results;
}
I was trying to do the following but have no idea if I'm doing anything correct at all
const exchange = require('../../exchange');
jest.mock('library')
it('get balances', async () => {
library.someFunction.mockResolvedValue({
data: [{some data here}]
)}
}
Error thrown:
TypeError: Cannot read property 'mockResolvedValue' of undefined
Here is the unit test solution:
index.js:
const library = require('./library');
const exchange = new library.exchange_name();
async function getPositions() {
let positions = [];
const results = await exchange.someFunction();
return results;
}
module.exports = getPositions;
library.js:
function exchange_name() {
async function someFunction() {
return 'real data';
}
return {
someFunction,
};
}
module.exports = { exchange_name };
index.test.js:
const getPositions = require('./');
const mockLibrary = require('./library');
jest.mock('./library', () => {
const mockExchange = { someFunction: jest.fn() };
return { exchange_name: jest.fn(() => mockExchange) };
});
describe('61649788', () => {
it('get balances', async () => {
const mockExchange = new mockLibrary.exchange_name();
mockExchange.someFunction.mockResolvedValueOnce({ data: ['mocked data'] });
const actual = await getPositions();
expect(actual).toEqual({ data: ['mocked data'] });
expect(mockExchange.someFunction).toBeCalled();
});
});
unit test results with 100% coverage:
PASS stackoverflow/61649788/index.test.js (8.775s)
61649788
✓ get balances (7ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.099s

TypeError: sns.publish is not a function , jest mock AWS SNS

I am trying to mock AWS.SNS and I am getting error. I referred posts on StackOverflow and could come up with below. Still, I am getting an error. I have omitted the irrelevant portion. Can someone please help me?
Below is my index.ts
import { SNS } from "aws-sdk";
export const thishandler = async (event: thisSNSEvent): Promise<any> => {
// I have omitted other code that works and not related to issue I am facing.
// I am receiving correct value of 'snsMessagetoBeSent' I verified that.
const response = await sendThisToSNS(snsMessagetoBeSent);
} // thishandler ends here
async function sendThisToSNS(thisMessage: snsAWSMessage) {
const sns = new SNS();
const TOPIC_ARN = process.env.THIS_TOPIC_ARN;
var params = {
Message: JSON.stringify(thisMessage), /* required */
TopicArn: TOPIC_ARN
};
return await sns.publish(params).promise();
}
My test case is below
jest.mock('aws-sdk', () => {
const mockedSNS = {
publish: jest.fn().mockReturnThis(),
promise: jest.fn()
};
return {
SNS: jest.fn(() => mockedSNS),
};
});
import aws, { SNS } from 'aws-sdk';
const snsPublishPromise = new aws.SNS().publish().promise;
import { thishandler } from "../src/index";
describe("async testing", () => {
beforeEach(() => {
jest.restoreAllMocks();
jest.resetAllMocks();
});
it("async test", async () => {
const ENRICHER_SNS_TOPIC_ARN = process.env.ENRICHER_SNS_TOPIC_ARN;
process.env.ENRICHER_SNS_TOPIC_ARN = "OUR-SNS-TOPIC";
const mockedResponseData ={
"Success": "OK"
};
(snsPublishPromise as any).mockResolvedValueOnce(mockedResponseData);
const result = await thishandler(thisSNSEvent);
});
I get error as TypeError: sns.publish is not a function
Here is the unit test solution:
index.ts:
import { SNS } from 'aws-sdk';
export const thishandler = async (event): Promise<any> => {
const snsMessagetoBeSent = {};
const response = await sendThisToSNS(snsMessagetoBeSent);
return response;
};
async function sendThisToSNS(thisMessage) {
const sns = new SNS();
const TOPIC_ARN = process.env.THIS_TOPIC_ARN;
const params = {
Message: JSON.stringify(thisMessage),
TopicArn: TOPIC_ARN,
};
return await sns.publish(params).promise();
}
index.test.ts:
import { thishandler } from './';
import { SNS } from 'aws-sdk';
jest.mock('aws-sdk', () => {
const mSNS = {
publish: jest.fn().mockReturnThis(),
promise: jest.fn(),
};
return { SNS: jest.fn(() => mSNS) };
});
describe('59810802', () => {
let sns;
beforeEach(() => {
sns = new SNS();
});
afterEach(() => {
jest.clearAllMocks();
});
it('should pass', async () => {
const THIS_TOPIC_ARN = process.env.THIS_TOPIC_ARN;
process.env.THIS_TOPIC_ARN = 'OUR-SNS-TOPIC';
const mockedResponseData = {
Success: 'OK',
};
sns.publish().promise.mockResolvedValueOnce(mockedResponseData);
const mEvent = {};
const actual = await thishandler(mEvent);
expect(actual).toEqual(mockedResponseData);
expect(sns.publish).toBeCalledWith({ Message: JSON.stringify({}), TopicArn: 'OUR-SNS-TOPIC' });
expect(sns.publish().promise).toBeCalledTimes(1);
process.env.THIS_TOPIC_ARN = THIS_TOPIC_ARN;
});
});
Unit test results with 100% coverage:
PASS src/stackoverflow/59810802/index.test.ts (13.435s)
59810802
✓ should pass (9ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 15.446s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59810802

Categories

Resources