Jest how to check async response - unit-testing

I'm new to Jest and React so this should be a very simple question to answer... I have an api-endpoint I'd like to check that I can hit. I picked Axios as a client to try this and created the following test:
describe('Api Tests', () => {
it('can perform an axios request', () => {
console.log('Here goes!');
const resp = axios.get('api-endpoint');
console.log(resp);
expect(resp).toBeDefined();
console.log('Done...');
});
});
Thankfully, the test passes, but with the following output:
PASS src\api\api.test.js
Api Tests
√ can perform an axios request (39ms)
console.log src\api\api.test.js:15
Here goes!
console.log src\api\api.test.js:23
Promise { <pending> }
console.log src\api\api.test.js:25
Done...
How do I test a simple request (WITHOUT MOCKING) so that I can get back a response that I can then interrogate?

Since axios.get returns a promise you should instruct Jest to wait for the response to return.
it('can perform an axios request', async () => {
const resp = await axios.get('api-endpoint');
expect(resp).toBeDefined();
});
or without async functions:
it('can perform an axios request', () => {
return expect(axios.get('api-endpoint')).resolves.toBeDefined();
});

I have nice and easy method , maybe you will like it too. Just keep it simple.
`import axios from 'axios';
axios.get('url goes here')
.then(response =>{console.log(response)})`
Maybe find helpful to you.

Related

How to mock a #Header request for NestJS unit testing

I am attempting to implement unit testing in NestJS. However, I am new to both NestJS and unit testing in general.
So, what I need to do is to pass a test that gets all projects from a gitlab profile.
#Get()
getProjects(#Headers() headers: any): Observable<Project[]> {
if (!headers.token) {
throw new HttpException('Missing User Token', HttpStatus.BAD_REQUEST);
}
return this.projectsService.listProjects(headers.token);
}
This is the code in the project.controller.ts file. It works well, and returns an observable with the list of projects. However, it requires a header to be sent through the HTTP request(Which is received using the #Headers decorator), as the gitlab is locked behind an authentication that requires a token to be passed through the header of the request.
I have attempted to mock the header to no success, and I was wondering if anyone has any idea how to proceed with the unit testing for that get request.
You don't need anything special here. In your unit test, you just need to pass an object with a token property to your method call.
describe('SomeController', () => {
let controller: SomeController;
let service: jest.Mocked<SomeService>;
beforeAll(async () => {
const modRef = await Test.createTestingModule({
controllers: [SomeController],
providers: [{
provide: SomeService,
useValue: {
method: jest.fn(() => of('value'))
}
}]
}).compile();
controller = modRef.get(SomeController)
service = modRef.get<jest.Mocked<SomeService>>(SomeService)
});
it('getProjects', (done) => {
controller.getProejcts({ token: 'hey look! a token'}).subscribe({
next: (val) => expect(val).toBe('value'),
error: (err) => { throw err; }
complete: () => done()
});
});
})

VueComponent.mounted : TypeError: Cannot read property 'get' of undefined in mounted hook

I am using jest for unit testing in nuxt js
I have mounted hook like this
async mounted(){
try{
var response = await this.$axios.get("api_url here");
this.result = response.data;
} catch(e){
console.log("Exception: ",e)
}
}
when i do unit test for it my code is . utnit.spec.js
jest.mock("axios", () => ({
get: () => Promise.resolve({ data: [{ val: 1 }] })
}));
import { mount } from '#vue/test-utils';
import file from '../filefile';
import axios from "axios";
describe('file', () => {
test('check comp. working correctly', () => {
var wrapper = mount(file);
afterEach(() => {
wrapper.destroy()
})
})
})
I am getting this warn there and there is no data in the results
Exception: TypeError: Cannot read property 'get' of undefined
at VueComponent.mounted
how do I know what is the problem here, is this I can not access axios in the unit file Is there any specific way to test Axios in mounted hook
The error means that it's this.$axios.get that is not available, not axios.get. The component relies on Axios plugin that is commonly installed in Vue application entry point or Nuxt configuration.
It can be installed for localVue Vue instance in tests, or be supplied directly to the component:
var wrapper = mount(file, { mocks: { $axios: axios } });
Also, the mock will fail if Axios is used as axios() somewhere because default import is expected to be a function:
jest.mock("axios", () => Object.assign(
jest.fn(),
{ get: jest.fn() }
));
axios.get is Jest spy, the implementation is mocked per test depending on the use and isn't limited to hard-coded Promise.resolve({ data: ... }) supplied in the mock.

request.cookies is undefined when using Supertest

I'm passing my authentication token via an HTTP-Only cookie in my NestJS API.
As such, when writing some E2E tests for my Auth endpoints, I'm having an issue with cookies not being where I expect them.
Here's my pared-down test code:
describe('auth/logout', () => {
it('should log out a user', async (done) => {
// ... code to create user account
const loginResponse: Response = await request(app.getHttpServer())
.post('/auth/login')
.send({ username: newUser.email, password });
// get cookie manually from response.headers['set-cookie']
const cookie = getCookieFromHeaders(loginResponse);
// Log out the new user
const logoutResponse: Response = await request(app.getHttpServer())
.get('/auth/logout')
.set('Cookie', [cookie]);
});
});
In my JWT Strategy, I'm using a custom cookie parser. The problem I'm having is that request.cookies is always undefined when it gets to the parser. However, the cookie will be present in request.headers.
I'm following the manual cookie example from this Medium article: https://medium.com/#juha.a.hytonen/testing-authenticated-requests-with-supertest-325ccf47c2bb, and there don't appear to be any other methods available on the request object to set cookies.
If I test the same functionality from Postman, everything works as expected. What am I doing wrong?
I know this is an old thread but...
I also had req.cookies undefined, but for a different reason.
I'm testing my router independently, not the top level app. So I bootstrap the app in beforeEach and add the route to test.
I was getting req.cookies undefined because express 4 requires the cookieParser middleware to be present to parse the cookies from the headers.
E.g.
const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const request = require('supertest');
const {router} = require('./index');
describe('router', () => {
let app;
beforeAll(() => {
app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use('/', router);
});
beforeEach(() => jest.clearAllMocks());
it('GET to /', async () => {
const jwt = 'qwerty-1234567890';
const resp = await request(app)
.get('/')
.set('Cookie', `jwt=${jwt};`)
.set('Content-Type', 'application/json')
.send({});
});
});
Testing this way allows me to unit test a router in isolation of the app. The req.cookies turn up as expected.
Late but I hope I can help you. The problem is in the initialization of the app object. Probably in your main.ts file you have some middlewares configured as they are: cors and queryParse. You must also put them in your tests when you create the app.
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
const app = moduleFixture.createNestApplication();
// Add cors
app.enableCors({
credentials: true,
origin: ['http://localhost:4200'],
});
// Add cookie parser
app.use(cookieParser());
await app.init();
As per the article you're following, the code at https://medium.com/#juha.a.hytonen/testing-authenticated-requests-with-supertest-325ccf47c2bb :
1) has the 'cookie' value in .set('cookie', cookie) in lowercase and in your code it's in Pascal case ==> Have you tried with lowercase in your code instead ?
2) the cookie value assigned to the 'cookie' header is not an array, whereas in your code you're assigning an array ==> Have you tried with a non array value ?
So to resume, can you try with the following code:
describe('auth/logout', () => {
it('should log out a user', async (done) => {
// ... code to create user account
const loginResponse: Response = await request(app.getHttpServer())
.post('/auth/login')
.send({ username: newUser.email, password });
// get cookie manually from response.headers['set-cookie']
const cookie = getCookieFromHeaders(loginResponse);
// Log out the new user
const logoutResponse: Response = await request(app.getHttpServer())
.get('/auth/logout')
.set('cookie', cookie) // <== here goes the diff
.expect(200, done);
});
});
Let us know if that helps :)

Unit testing interceptor (axios)

I use axios for the api calls in my react redux app. I added this interceptor to intercept the response for all the api calls and redirect user to login if the status code is 401.
axios.interceptors.response.use((response) => {
if (response.status === 401) {
browserHistory.push('/login');
}
return response;
});
I am unit testing this and asserting on browserHistory spy to get called but I am not sure why my test keeps failing. I'm kind of stuck after loads of tries and am not able to sort out the issue. I am using moxios for mocking response.
Test
let sandbox;
beforeEach(() => {
moxios.install();
sandbox = sinon.sandbox.create();
});
afterEach(() => {
moxios.uninstall();
sandbox.restore();
});
describe('interceptors', () => {
it('should redirect to login if response status code is 401', (done) => {
moxios.withMock(() => {
sandbox.spy(browserHistory, 'push');
axios.get('/test');
moxios.wait(() => {
const request = moxios.requests.mostRecent();
request.respondWith({
status: 401,
response: {}
}).then(() => {
expect(browserHistory.push).to.have.been.called; // Fails
done();
}).catch(done);
});
});
});
});
Any sort of resources or guide would be really appreciated. I am pretty sure I am missing something here.

State not changing when unit testing VueJS and VueResource

I'm trying to test a service that I've created that makes an API call with vue-resource. The service should make the call and update the component with the new data, however in my tests it doesn't register the updated value. I'm using the same setup as the vue-cli webpack example and have based my auth service off this repo (which unfortunately doesn't have any tests)
my service:
export default {
login(context, creds){
context.$http.post(LOGIN_URL, creds)
.then((response) => {
//do something else here
}, (response) => {
context.error = response.data.error
}
}
}
my test:
import Vue from 'vue'
import VueResource from 'vue-resource'
Vue.use(VueResource)
import Auth from 'src/auth'
describe('Auth', () => {
it('should throw an error on unsuccessful login', (done) => {
//intercept the api call and force an invalid response
Vue.http.interceptors.unshift((request, next) => {
next(request.respondWidth({error: 'some error'}, {status: 401}));
});
const vm = new Vue({
data: {
error: ''
}
}).$mount()
Auth.login(vm, {email: 'test#test.com', pass: 'test'} )
//this always fails
expect(vm.error).to.equal('some error')
//ive also tried:
vm.$nextTick(() => {
expect(vm.error).to.equal('some error')
//done()
});
//undo our interceptor
Vue.http.interceptors.shift()
}
}
When I run the test it fails because it's expecting '' to equal 'some error'.
My suspicions are around the fact that vue-resource is using promises.
After reading through some of the Vue.js tests I found my answer. Instead of using vm.$nextTick I did the following:
setTimeout(function(){
expect(vm.error).to.equal('something')
done()
}, 0)