Sinon stub axios throws error : TypeError: Attempted to wrap get which is already wrapped - axios

There are few existing questions on stack overflow with this error but none of them explains this error on stubbing axios. I took the boilerplate working example from sinonjs.org and tried to mock axios. It throws the error
TypeError: Attempted to wrap get which is already wrapped
Code below:
import Axios from 'axios';
var sandbox = require('sinon').createSandbox();
describe('axios.get method', function () {
beforeEach(function () {
// stub out the `axios` method
sandbox.stub(Axios, 'get');
});
afterEach(function () {
// completely restore all fakes created through the sandbox
sandbox.restore();
});
it('should be called once', function () {});
});

The reason why you got this error is that you stub the Axios.get method more than once. The code you provided works fine. So you need to call sanbox.restore() method to restore all fakes created through the sandbox before stubbing the method again. Please check your code DOES NOT stub the Axios.get method continuous.
E.g.
index.test.ts:
import Axios from 'axios';
import sinon from 'sinon';
const sandbox = sinon.createSandbox();
describe('axios.get method', () => {
let axiosGetStub;
beforeEach(() => {
axiosGetStub = sandbox.stub(Axios, 'get');
});
afterEach(() => {
sandbox.restore();
});
it('should be called once', () => {
Axios.get('http://localhost:3000');
sandbox.assert.calledOnce(axiosGetStub);
});
it('should be called once again', () => {
Axios.get('http://localhost:3000');
sandbox.assert.calledOnce(axiosGetStub);
});
});
unit test result:
axios.get method
✓ should be called once
✓ should be called once again
2 passing (29ms)

Related

Jest + Axios: Test Whether Promise Was Fulfilled

Using Vue test utils with Jest, I am attempting to spy on an axios.get call which runs in my component's created() lifecycle hook. I would like to test that the promise has been fulfilled (i.e. was not rejected) based on a method that runs in the then() block, but not the catch() block.
The way I have the test setup right now, the spyOn always resolves because I am using .mockResolveValue(). I tried declaring mockResolveValue() in the it('') portion of the test, but it says the axios get is called 0 times when I do that.
DeptPrefs.vue
<script>
import axios from 'axios'
export default {
name: "DeptPrefs",
data () {
return {
...
}
},
async created () {
await this.getPrefs()
},
computed: {},
methods: {
async getPrefs () {
await axios.get('/coolsite/api/admin/getstuff?dept=216001')
.then(r => {
this.setDeptPrefs(r.data)
}).catch((e) => {})
}
...
</script>
And this is how the deptprefs.spec.js currently looks.
describe('when prefs created() hook loads', () => {
const localVue = createLocalVue()
localVue.use(Vuex)
...
const getPrefs = jest.spyOn(DeptPrefs.methods, 'getPrefs') // spy on getPrefs() method
jest.spyOn(axios, 'get').mockResolvedValue([]) // spy on axios .get() method
const wrapper = mount(DeptPrefs, {
...
})
it('makes an api call to get the dept prefs', async () => {
await expect(getPrefs).toHaveBeenCalled() // works fine
await expect(axios.get).toHaveBeenCalledTimes(1) // works fine
const setDeptPrefs = jest.spyOn(appModule.mutations, 'setDeptPrefs')
expect(setDeptPrefs).toHaveBeenCalledTimes(1) // this is the expectation in question. It's always 1.
})
})
So let's say I change the URL of the API call to be a non-existent route. The test will still say that the setDeptPrefs() method has been called 1 time. It shouldn't be called at all because the axios should've hit the catch block, where that method does not run.
I want to amend my test to reflect this; when the then() block is hit, setDeptPrefs should NOT be called. When it does, it should be.
Also please feel free to chime in on if this is something I should even be unit testing. I am trying to get a feel for what's test-worthy and what isn't.

react testing, button not clicking from userevent

im trying to do a write a test where i can click a button in a react component but its not working and i don't know why. as far as i can tell this should be working. im expecting the callback to be called once.
it("should work", () => {
var mockCallback = jest.fn();
render(<button onClick={mockCallback}>hello world</button>);
act(() => {
let test = screen.getByRole("button");
console.log(test);
userEvent.click(test);
});
expect(mockCallback).toHaveBeenCalledTimes(1);
});
here is a link to a codesandbox
what am i doing wrong?
userEvent.click returns a Promise<void> as you can see here. So, to your test work you need to make your test async and await the click event:
it("should work", async () => {
var mockCallback = jest.fn();
render(<button onClick={mockCallback}>hello world</button>);
const button = screen.getByRole("button");
screen.debug();
await userEvent.click(button);
expect(mockCallback).toHaveBeenCalledTimes(1);
});
* Also, you don´t need the act in this case. Check more about it here.

Chai with promises is not waiting for previous promises to be resolved

I have below function and I am using it in expect.
function Create() {
var that = this;
// Goto home page of App.
// Async call
that.homePage();
// Async call
Utils.click(projectsSelectors.project_create, false, that.browser);
// Async call
Utils.elementIsVisible(stock_avatar, that.browser);
// Async call
Utils.fill(name_input, that.name, that.browser);
// Async call
stockAvatar.call(that);
// Async call
Utils.click(create_save, false, that.browser);
// Verify if it's created.
// Async call
return that.$is_Created();
}
But when I use like below
expect(Create()).to.eventually.equal(true);
The expectation is just passed without doing anything. The above Create method contains multiple asynchronous calls.
I even chained all the calls inside Create method, but still, the expectation is just passing without doing anything on the screen.
Your test method must return the promise
it("should do something", function()
{
return expect(Create()).to.eventually.equal(true);
}

wait for http request to complete in protractor

I am trying to wait for spinner to disappear and then for my steps to execute but nothing is working for me.
browser.wait(function () {
return this.spinner.isDisplayed().then(function (result) {
return !result;});}, 20000);
and i even tried with
browser.wait(function () {
return !browser.isElementPresent(this.spinner);}, 20000);
even with below method
browser.sleep(1000);
this.spinner.isPresent().then(function (result) {
if (result === true) {
var EC = protractor.ExpectedConditions;
browser.wait(EC.invisibilityOf(this.spinner), 10000);}});
then only thing that works is
browse.sleep(10000);
i don't want to use sleep in my code. can anyone help me with how to wait for complete http request to complete and then process with testing
you should consider using Expected Conditions since they return true/false based on current conditions
http://www.protractortest.org/#/api?view=ProtractorExpectedConditions.prototype.invisibilityOf
so your test case would become:
browser.wait(EC.invisibilityOf(this.spinner),20000).then(function(){
...continue test, spinner gone
});
UPDATE
in order to use done, you would generally pass this cb into your it() function. This means your test could look like
describe("example describe",function(){
it("should be an example only", function(done){
request.get("www.google.com",function(res){
//done with async request, now call done
done();
})
})
});
Since your entire code isn't posted up here, you should have something similar to:
it("should wait for spinner to go bye-bye",function(done){
browser.wait(EC.invisibilityOf(this.spinner),20000).then(function(){
done()
});
});

Protractor: inconsistent test reports?

Testing an angular app, the test are sometimes passing and sometimes failing...
My test cases look like:
it('test-1: should has main button', function () {
expect(page.demoButton).not.toBeUndefined();
});
it('test-2: should open modal on click secondary button', function () {
page.demoButton.click().then(function () {
page.SecondaryButton.click().then(function() {
expect(page.Modal).not.toBeUndefined();
});
});
});
it('test-3: should open modal with correct text', function () {
page.demoButton.click().then(function () {
page.SecondaryButton.click().then(function() {
expect(page.Modal.text.getText()).toEqual('Are you sure to cancel
this?');
});
});
});
If I run the test, sometimes the tests are passed sometimes some of them get failed..
Most of the time error is like: No element found using locator: By.cssSelector(".myButton"). or Cannot read property 'getText' of undefined
Thank you in advance!
I fixed that issue with using:
browser.waitForAngular();
As I see that issue occurs with getText and click events, So:
it('test-2: should open modal on click secondary button', function () {
page.demoButton.click().then(function () {
browser.waitForAngular();
page.SecondaryButton.click().then(function() {
browser.waitForAngular();
expect(page.Modal.text.getText()).toEqual('Are you sure to cancel
this?');
});
});
});
was the solution.