How to feed values in constructor in testcase in NestJs(jest)? - node.js

I am using NestJs framework in my project. Here i want to write testcase for a service file. But i am facing an issue in feeding the value of this.userPool in the service file.I am getting userPoolId and clientId undefined error.
I tried different solutions, but nothing works for me.
service.js
export class AuthService {
private userPool: CognitoUserPool;
constructor(private readonly authConfig: AuthConfig) {
this.userPool = new CognitoUserPool({
UserPoolId: this.authConfig.userPoolId,
ClientId: this.authConfig.clientId,
});
}
authenticateUser(user: AuthCredentialsDto) {
try {
const { userName, password } = user;
const authenticateDetails = new AuthenticationDetails({
Username: userName,
Password: password,
});
const userData = {
Username: userName,
Pool: this.userPool,
};
const newUser = new CognitoUser(userData);
return new Promise((resolve, reject) => {
------------------------
--------------------------------
});
} catch (error) {
throw new BadRequestException(error.message);
}
}
service.spec.ts
import { AuthService } from './auth.service';
import {
AuthenticationDetails,
CognitoUser,
CognitoUserAttribute,
CognitoUserPool,
} from 'amazon-cognito-identity-js';
import { AuthConfig } from './cognito.service';
// const mockCognitoUserPool = () => ({
// registerUser: jest.fn(),
// });
describe('AuthService', () => {
let service: AuthService;
let authConfig: AuthConfig;
let userPool: CognitoUserPool;
userPool = new CognitoUserPool({
UserPoolId: authConfig.userPoolId,
ClientId: authConfig.clientId,
});
// let userPool;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
AuthService,
AuthConfig,
userPool
],
}).compile();
service = module.get<AuthService>(AuthService);
authConfig = module.get<AuthConfig>(AuthConfig);
// cognitoUserPool = module.get<CognitoUserPool>(CognitoUserPool);
});
describe('authenticateUser', () => {
it('calls registerUser and returns the result', async () => {
const mockUser = {
userName: 'usernme',
password: 'password',
};
// tasksRepository.findOne.mockResolvedValue(mockTask);
const result = await service.authenticateUser(mockUser);
expect(result).toEqual('result');
});
});
// it('should be defined', () => {
// expect(service).toBeDefined();
// });
});

Did you mean to spell your username property ‘usernme’ in the test file?

Related

Cypress automation test continuously generating authentication token while doing authentication test in SharePoint Sites

All the test is passing successfully but still the cypress test is generating token continuously.
cypress.config.js
const { defineConfig } = require("cypress");
const spauth = require("node-sp-auth");
let getLoginTest = async () => {
const username = "****#****.com";
const password = "******";
const pageUrl = "https://*****.sharepoint.com"
// Connect to SharePoint
const data = await spauth.getAuth(pageUrl, {
username: username,
password: password
});
return data;
};
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
on('task', {
// deconstruct the individual properties
async getLogin() {
try {
const res = await getLoginTest();
return res;
} catch (error) {
return error;
}
}
});
},
},
});
Below I have mentioned the tests case which I have created."Testspec.cy.js"
// <reference types="cypress" />
require('cypress-xpath')
describe('SharePoint Authentication', () => {
beforeEach(() => {
cy.task("getLogin").then(token => {
cy.visit({
method: "GET",
url: "https://*****.sharepoint.com/SitePages/Home.aspx",
headers: token.headers
});
});
});
it('SharePoint Authentication Test', () => {
cy.xpath('//*[contains(text(),"Customer Dashboard")]').should('be.visible');
cy.get('.alphabet > :nth-child(3)').click();
cy.contains('Leader').click();
});
});
Test Screen
Here is the screenshot of the cypress test

How do you mock Auth0 MangementClient using jest?

This is also a question on Auth0 node-auth0 library. The use case is that I am using the Auth0 create Actions API through Terraform and want to be able to writes tests against the Actions.
In this example I want to be able to test the onExecutePostLogin without using real values.
// auth0-post-login.js
exports.onExecutePostLogin = async (event, api) => {
const userId = event.user.user_id
const ManagementClient = require('auth0').ManagementClient
const management = new ManagementClient({
domain: event.secrets.domain,
clientId: event.secrets.clientId,
clientSecret: event.secrets.clientSecret,
audience: `https://${event.secrets.domain}/api/v2/`,
scope: 'read:users',
})
const params = { id: userId, page: 0, per_page: 50, include_totals: false }
let userPermissions = await management.getUserPermissions(params)
const map = require('array-map')
const permissions = map(userPermissions, function(permission) {
return permission.permission_name
})
api.accessToken.setCustomClaim('https://example.com/access', permissions.join(' '))
}
One of the main issues is that the functions like getUserPermissions is created through their utility wrapper:
utils.wrapPropertyMethod(ManagementClient, 'getUserPermissions', 'users.getPermissions');
This causes jest to have issues finding the functions.
I did something similar as stsmurf to mock the response of the Auth0 methods.
I have a file where I store my helper methods like "find a role by its name"
// helper.ts
import { ManagementClient } from 'auth0';
export const getRoleByName = async (roleName: string) => {
const api = new ManagementClient({
clientId: clientId,
clientSecret: clientSecret,
domain: domain,
});
const roles = await api.getRoles();
const role = roles.find((r) => r.name == roleName);
if (!role) throw new Error('Role not found');
return role;
};
// helper.test.ts
import { Role } from 'auth0';
import { getRoleByName } from './helpers';
const mockGetRoles = jest.fn();
jest.mock('auth0', () => {
return {
ManagementClient: jest.fn().mockImplementation(() => {
return {
getRoles: mockGetRoles,
};
}),
};
});
describe('Get role', () => {
beforeAll(() => {
const dummyRoles: Role[] = [
{ id: 'fake_id_1', description: 'Fake role nr 1', name: 'Fake Role 1' },
{ id: 'fake_id_2', description: 'Fake role nr 2', name: 'Fake Role 2' },
];
mockGetRoles.mockImplementation(() => dummyRoles);
});
it('can return a role if it exists', async () => {
const expectedResult: Role = {
id: 'fake_id_1',
description: 'Fake role nr 1',
name: 'Fake Role 1',
};
const result = await getRoleByName('Fake Role 1');
expect(expectedResult).toEqual(result);
});
it('will throw an error when a role is not found', async () => {
await expect(getRoleByName('Fake Role 3')).rejects.toThrowError();
});
});
In order to get to functions like getUserPermissions I needed to override the implementation of the ManagementClient. This allowed me to then define getUserPermissions as a mock function.
import { onExecutePostLogin } from './auth0-post-login'
const mockManagementClient = jest.fn()
const mockGetUserPermissions = jest.fn()
jest.mock('auth0', () => {
return {
ManagementClient: (opts) => {
mockManagementClient(opts)
return {
getUserPermissions: (params) => {
return mockGetUserPermissions(params)
},
}
},
}
})
describe('onExecutePostLogin', () => {
const mockSetCustomClaim = jest.fn()
beforeEach(() => {
mockSetCustomClaim.mockClear()
mockManagementClient.mockClear()
mockGetUserPermissions.mockClear()
mockGetUserPermissions.mockReturnValue([
{
permission_name: 'read:foo',
},
{
permission_name: 'update:bar',
},
])
})
const event = {
user: {
user_id: 'abcd123',
},
secrets: {
domain: 'test-example.us.auth0.com',
clientId: 'a-client-id',
clientSecret: 'a-client-secret',
},
}
const api = {
accessToken: {
setCustomClaim: mockSetCustomClaim,
},
}
it('initializes a ManagementClient', async () => {
await onExecutePostLogin(event, api)
expect(mockManagementClient).toHaveBeenCalledWith({
domain: event.secrets.domain,
clientId: event.secrets.clientId,
clientSecret: event.secrets.clientSecret,
audience: `https://${event.secrets.domain}/api/v2/`,
scope: 'read:users',
})
})
it('gets users permissions', async () => {
await onExecutePostLogin(event, api)
expect(mockGetUserPermissions).toHaveBeenCalledWith(
{ id: event.user.user_id, page: 0, per_page: 50, include_totals: false },
)
})
it('sets custom claims', async () => {
await onExecutePostLogin(event, api)
const expectedPermissions = 'read:foo update:bar'
expect(mockSetCustomClaim).toHaveBeenCalledWith(
'https://example.com/access', expectedPermissions,
)
})
})

How to use jest.spyOn with NestJS Transaction code on Unit Test

NestJS provides a sample Transaction code on (https://docs.nestjs.com/techniques/database#transactions), and I now would like to create Unit test script against the code. Here are the some dependent files:
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column({type: 'text', name: 'first_name'})
firstName: string;
#Column({type: 'text', name: 'last_name'})
lastName: string;
#Column({name: 'is_active', default: true})
isActive: boolean;
}
#Injectable()
export class UsersService {
constructor(
private connection: Connection
) {}
async createMany(users: User[]): User[] {
const queryRunner = this.connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const user1 = await queryRunner.manager.save(users[0]);
await queryRunner.commitTransaction();
return [user1];
} catch (err) {
// since we have errors lets rollback the changes we made
await queryRunner.rollbackTransaction();
} finally {
// you need to release a queryRunner which was manually instantiated
await queryRunner.release();
}
}
}
Here is the unit test script. I am close to accomplish but still I am getting undefined from await queryRunner.manager.save(users[0]) with the jest.spyOn setup below:
describe('UsersService', () => {
let usersService: UsersService;
let connection: Connection;
class ConnectionMock {
createQueryRunner(mode?: "master" | "slave"): QueryRunner {
const qr = {
manager: {},
} as QueryRunner;
qr.manager;
Object.assign(qr.manager, {
save: jest.fn()
});
qr.connect = jest.fn();
qr.release = jest.fn();
qr.startTransaction = jest.fn();
qr.commitTransaction = jest.fn();
qr.rollbackTransaction = jest.fn();
qr.release = jest.fn();
return qr;
}
}
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService, {
provide: Connection,
useClass: ConnectionMock,
}],
}).compile();
usersService = module.get<UsersService>(UsersService);
connection = module.get<Connection>(Connection);
});
it('should be defined', () => {
expect(usersService).toBeDefined();
});
it('should return expected results after user create', async () => {
const user1: User = { id: 1, firstName: 'First', lastName: 'User', isActive: true };
const queryRunner = connection.createQueryRunner();
// I would like to make the following spyOn work
jest.spyOn(queryRunner.manager, 'save').mockResolvedValueOnce(user1);
expect(await appService.createMany([user1])).toEqual([user1]);
});
});
connection.createQueryRunner(); will return difference instance of QueryRunner.
This mean queryRunner of const queryRunner = connection.createQueryRunner(); will not reference to queryRunner in const queryRunner = this.connection.createQueryRunner(); of createMany function.
Then your mock jest.spyOn(queryRunner.manager, 'save').mockResolvedValueOnce(user1); does not make sense.
Keep it simple, make QueryRunner as a "global" variable, then binding it to ConnectionMock, this mean we will have the same "variable" when we call createQueryRunner.
Updated beforeEach content, ConnectionMock class.
describe('UsersService', () => {
let usersService: UsersService;
let connection: Connection;
const qr = {
manager: {},
} as QueryRunner;
class ConnectionMock {
createQueryRunner(mode?: "master" | "slave"): QueryRunner {
return qr;
}
}
beforeEach(async () => {
// reset qr mocked function
Object.assign(qr.manager, {
save: jest.fn()
});
qr.connect = jest.fn();
qr.release = jest.fn();
qr.startTransaction = jest.fn();
qr.commitTransaction = jest.fn();
qr.rollbackTransaction = jest.fn();
qr.release = jest.fn();
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService, {
provide: Connection,
useClass: ConnectionMock,
}],
}).compile();
usersService = module.get<UsersService>(UsersService);
connection = module.get<Connection>(Connection);
});
it('should be defined', () => {
expect(usersService).toBeDefined();
});
it('should return expected results after user create', async () => {
const user1: User = { id: 1, firstName: 'First', lastName: 'User', isActive: true };
const queryRunner = connection.createQueryRunner();
// I would like to make the following spyOn work
jest.spyOn(queryRunner.manager, 'save').mockResolvedValueOnce(user1);
expect(await appService. createMany([user1])).toEqual([user1]);
});
});

Could not mock oracledb.getConnection() in jest unit test for nodejs typescript class that use oracledb npm

This is nodejs typescript class to execute query or getConnection using oracledb npm.
I could not mock oraclebd getConnection in jest unit test.
How to write unit test for executeQuery. It shows test coverage to be done on finally block all statement.
I written unit test but
import { Inject, Injectable } from '#nestjs/common';
import * as oracledb from 'oracledb';
import { ORACLE_DB_OPTIONS } from '../constant';
import { OracleDBOptions } from '../interface';
import { PromInstanceCounter, PromMethodCounter } from '#digikare/nestjs-prom';
#PromInstanceCounter
#Injectable()
export class OracleDBService {
constructor(
#Inject(ORACLE_DB_OPTIONS)
private readonly oracleDbOptions: OracleDBOptions[],
) { }
#PromMethodCounter()
async executeQuery(
dbName: string,
query: string,
bindValue: any[] = [],
) {
let localConnection: any;
try {
const oracleDbOption = this.oracleDbOptions.filter(
x => x.name === dbName,
);
if (!oracleDbOption) {
throw Error('Connection string does not exist');
}
localConnection = await oracledb.getConnection({
user: oracleDbOption[0].user,
password: oracleDbOption[0].password,
connectString: oracleDbOption[0].connectString,
});
const result = await localConnection.execute(query, bindValue);
await localConnection.close();
return result;
} finally {
if (localConnection) {
try {
await localConnection.close();
} catch (err) {
console.log('Error when closing the database connection: ', err);
}
}
}
}
#PromMethodCounter()
async getConnection(dbName: string) {
const oracleDbOption = this.oracleDbOptions.filter(x => x.name === dbName);
if (!oracleDbOption) {
throw Error('Connection string does not exist');
}
const localConnection = await oracledb.getConnection({
user: oracleDbOption[0].user,
password: oracleDbOption[0].password,
connectString: oracleDbOption[0].connectString,
});
return localConnection;
}
}
Written Unit Test for getConnection() method.
describe('OracleDbService', () => {
let oracleDBService: OracleDBService;
let oracleDBOptions = [
{
name: 'rfdest',
user: 'rfdest',
password: 'rfdest',
connectString: 'alsyntstb.ohlogistics.com:1521/syntstb',
},
{
name: 'DOCGENDEV',
user: 'DOCGENDEV',
password: 'DocGen$dev18',
connectString: 'alsynwebd.ohlogistics.com/synwebd_maint',
},
];
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
OracleDBService,
{
provide: ORACLE_DB_OPTIONS,
useValue: oracleDBOptions,
},
],
}).compile();
oracleDBService = module.get<OracleDBService>(OracleDBService);
});
it('should be defined', () => {
expect(oracleDBService).toBeDefined();
});
it('getConnection success', () => {
jest.fn(getConnection).mockReturnValue({
execute: function() {},
close: function() {},
});
oracleDBService.getConnection('rfdest').then(resolve => {
expect(resolve).not.toBeNull();
});
});
it('getConnection throw error', () => {
jest.fn(getConnection).mockReturnValue({
execute: function() {},
close: function() {},
});
oracleDBService
.getConnection('')
.then(resolve => {
expect(resolve).not.toBeNull();
})
.catch(reject => {
expect(reject).not.toBeNull();
});
});
});

how to fix octokit.authenticate() is deprecated

I am starting the ginit module but getting the error like this:
=> octokit.authenticate() is deprecated. Use "auth" constructor
option instead.
How can I fix it?
my code
module.exports = {
getInstance: () => {
return octokit;
},
setGithubCredentials : async () => {
const credentials = await inquirer.askGithubCredentials();
octokit.authenticate(
_.extend(
{
type: 'basic',
},
credentials
)
);
},
}
Maybe you code from this article: https://www.sitepoint.com/javascript-command-line-interface-cli-node-js/
And my solution is below
const Octokit = require("#octokit/rest");
const Configstore = require("configstore");
const pkg = require("../package.json");
const _ = require("lodash");
const CLI = require("clui");
const Spinner = CLI.Spinner;
const chalk = require("chalk");
const inquirer = require("./inquirer");
const conf = new Configstore(pkg.name);
module.exports = {
getInstance: () => {
return global.octokit;
},
getStoredGithubToken: () => {
return conf.get("github.token");
},
setGithubCredentials: async () => {
const credentials = await inquirer.askGithubCredentials();
const result = _.extend(
{
type: "basic"
},
credentials
);
global.octokit = Octokit({
auth: result
});
},
registerNewToken: async () => {
const status = new Spinner("Authenticating you, please wait...");
status.start();
try {
const response = await global.octokit.oauthAuthorizations.createAuthorization({
scopes: ["user", "public_repo", "repo", "repo:status"],
note: "ginits, the command-line tool for initalizing Git repos"
});
const token = response.data.token;
if (token) {
conf.set("github.token", token);
return token;
} else {
throw new Error(
"Missing Token",
"GitHub token was not found in the response"
);
}
} catch (err) {
throw err;
} finally {
status.stop();
}
}
};
Try something like:
const Octokit = require('#octokit/rest');
module.export = {
getInstance({username, password}) {
return Octokit({
auth: {
username,
password,
},
});
}
}
The PR introducing the auth property shows some other examples of specifying credentials.

Resources