Aurelia Unit Testing error due to aurelia.setRoot('shell/shell'); - unit-testing

I'm trying to implement unit test on login method but I'm getting "Cannot read property 'setRoot' of undefined" error.
Here is my Login Method:
import { inject, Aurelia, NewInstance, computedFrom } from 'aurelia-framework';
import { Router } from 'aurelia-router';
import { Server, User } from 'backend/server';
import { ValidationRules, ValidationController, validateTrigger } from 'aurelia-validation';
import { ValidationRenderer } from 'resources/validation-renderer';
#inject(Aurelia, Router, Server, NewInstance.of(ValidationController), NewInstance.of(User))
constructor(aurelia, router, server, validationController, user) {
this.router = router;
this.aurelia = aurelia;
this.validationController = validationController;
this.server = server;
this.user = user;
}
activate() {
this.validationController.validateTrigger = validateTrigger.blur;
this.validationController.addRenderer(new ValidationRenderer());
ValidationRules
.ensure(u => u.email)
.required()
.matches(/^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)
.ensure('password')
.required()
.on(this.user);
}
logUserIn()
{
let promise = new Promise((resolve, reject) =>
{
this.loggingIn = true;
this.messageColor = 'green';
this.message = 'Authenticating...';
this.loginSuccess = false;
this.validationController.validate().then(errors => {
if (!errors.valid) {
this.loggingIn = false;
return ({error: true});
}
return this.server.authenticate(this.user.email, this.user.password);
}).then(result => {
if (!result.error) {
this.messageColor = 'green';
this.message = 'Login Successful';
this.loginSuccess = true;
this.aurelia.setRoot('shell/shell');
resolve(result);
} else {
this.message = '';
resolve();
}
}).catch(err => {
if(!this.loginSuccess)
{
this.messageColor = 'red';
this.message = err.message;
}
this.loggingIn = false;
resolve(err);
});
});
return promise;
}
My unit test code:
login.spec.js:
describe('Login Unit Test', () => {
var login = new Login();
login.validationController = new ValidationController();
login.server = new Server();
it("shouldn't allow login", (done) => {
console.log(login.messageColor);
login.logUserIn().then((result) => {
console.log(login.messageColor);
console.log(login.message);
expect(login.messageColor).toBe('red');
done();
});
});
it("Should log in", (done) => {
login.user = {email:'a#b.com', password:'abc'};
console.log(login.user.email);
console.log(login.user.password);
login.logUserIn().then((result) => {
console.log(login.messageColor);
console.log(login.message);
expect(login.messageColor).toBe('green');
done();
});
});
});
Here is the error that i'm getting
I would really appreciate any help.
Thanks.

Did you post exactly the Login code?
In this case before the constructor the #inject statement is missing.
Some like:
#inject(Aurelia, Router, Server, ValidationController, User)
constructor(aurelia, router, server, validationController, user)

Related

Proper way to test type-graphql middleware with jest

Context
I am trying to write a jest test for an authentication middleware for a resolver function. I am attempting to mock an implementation so that the next function is called so that the test passes.
Error
The error I receive is "next is not a function". I can verify that the mocked function is called through expect(isAuth).toHaveBeenCalledTimes(1);, but there is clearly an issue with my mocked implementation. Any help is much appreciated.
Code
//isAuth Middleware
import { MiddlewareFn } from "type-graphql";
import { Context } from "../utils/interfaces/context";
export const isAuth: MiddlewareFn<Context> = ({ context }, next) => {
const loggedInUserId = context.req.session.id;
if (!loggedInUserId) {
throw new Error("Not authenticated!");
}
return next();
};
//transaction.test.ts
jest.mock("../middleware/isAuth", () => {
return {
isAuth: jest.fn((_, next) => next()), //also tried (next) => next() and (next)=>Promise.resolve(next())
};
});
test("should create a txn successfully", async () => {
//ARRANGE
const user = await createUser(orm);
const txn = createTxnOptions();
const txnToBeCreated = { ...txn, userId: user.id };
//ACT
const response = await testClientMutate(
TXN_QUERIES_AND_MUTATIONS.CREATE_TXN,
{
variables: txnToBeCreated,
}
);
//expect(isAuth).toHaveBeenCalledTimes(1); passes so it's getting called
console.log(response);
const newlyCreatedTxn: Transaction = (response.data as any)
?.createTransaction;
//ASSERT
const dbTxn = await em.findOne(Transaction, {
id: newlyCreatedTxn.id,
});
expect(newlyCreatedTxn.id).toBe(dbTxn?.id);
});
//transaction.resolver.ts
import { Transaction } from "../entities/Transaction";
import {
Arg,
Ctx,
Mutation,
Query,
Resolver,
UseMiddleware,
} from "type-graphql";
import { Context } from "../utils/interfaces/context";
import { isAuth } from "../middleware/isAuth";
#Mutation(() => Transaction)
#UseMiddleware(isAuth)
async createTransaction(
#Arg("title") title: string,
#Arg("userId") userId: string,
#Ctx() { em }: Context
): Promise<Transaction> {
const transaction = em.create(Transaction, {
title,
user: userId,
});
await em.persistAndFlush(transaction);
return transaction;
}
Replace
jest.mock("../middleware/isAuth", () => {
return {
isAuth: jest.fn((_, next) => next()), //also tried (next) => next() and (next)=>Promise.resolve(next())
};
});
With
jest.mock("../middleware/isAuth", () => {
return {
isAuth: (_, next) => next()
};
});

hapi authentication strategy karma test with sinon with async function

I am trying to test the authentication scheme with hapi server. I have two helper function within the same file where I put my authentication scheme. I want to test when this successfully authenticate the user. But in my test case I always get 401 which is the unauthenicated message.
export const hasLegitItemUser = async (request, email, id) => {
const {
status,
payload: {users}
} = await svc.getRel(request, email);
if (status !== STATUS.OK) {
return false;
}
return users.includes(user)
};
export const getUser = async request => {
const token = request.state._token;
const res = await svc.validateToken({request, token});
const {
userInfo: {email}
} = res;
const id = extractId(request.path);
const isLetgitUser = await hasLegitItemUser(
request,
email,
id
);
res.isLegitUser = isLegitUser;
return res;
};
const scheme = (server, options) => {
server.state("my_sso", options.cookie);
server.ext("onPostAuth", (request, h) => {
return h.continue;
});
return {
async authenticate(request, h) {
try {
const {
tokenValid,
isLegitUser,
userInfo
} = await getUser(request);
if (tokenValid && isLegitUser) {
request.state["SSO"] = {
TOKEN: request.state._token
};
return h.authenticated({
credentials: {
userInfo
}
});
} else {
throw Boom.unauthorized(null,"my_auth");
}
} catch (err) {
throw Boom.unauthorized(null, "my_auth");
}
}
};
};
My Test file:
import Hapi from "hapi";
import sinon from "sinon";
import auth, * as authHelpers from "server/auth";
import {expect} from "chai";
import pcSvc from "server/plugins/services/pc-svc";
describe("Authentication Plugin", () => {
const sandbox = sinon.createSandbox();
const server = new Hapi.Server();
const authHandler = request => ({
credentials: request.auth.credentials,
artifacts: "boom"
});
before(() => {
server.register({
plugin: auth,
});
const route = ["/mypage/{id}/home"];
route.forEach(path => {
server.route({
method: "GET",
path,
options: {
auth: auth,
handler:{}
}
});
});
});
afterEach(() => {
sandbox.restore();
});
it("should authorize user if it is a validated user", async () => {
sandbox
.stub(authHelpers, "getUser")
.withArgs(request)
.resolves({
tokenValid: true,
isLegitUser: true,
userInfo: {}
});
return server
.inject({
method: "GET",
url:
"/mypage/888/home"
})
.then(res => {
expect(res.statusCode).to.equal(200);
expect(res.result).to.eql({
userInfo: {
email: "abc#gmail.com",
rlUserId: "abc",
userId: "abc#gmail.com"
}
});
});
});
});
I always get the 401 error for unauthenticated. It seems like my "getUser" function in my test is not triggering for some reason, it goes straight to the throw statement in the catch phase in my code. Please help.

Jasmine Karma calling Login component in angular 5

I am new to Jasmine karma test cases. I try to write the karma test case for login component. In that clicking, the submit button is not calling the onSubmit method in the component.ts file
login.component.ts
onSubmit() {
this.authService.login(this.data.username, this.data.password)
.delay(1000)
.subscribe(data => {
sessionStorage.setItem('token', JSON.stringify(data.token));
if (this.urlDirect !== null) {
window.location.href = this.sharedService.baseUrl + '/' + this.urlDirect;
} else { this.router.navigate(['/dashboard']); }
},
error => {
this.submitted = false;
setInterval(() => {
this.spinnerlogo = false;
}, 1000);
let i = 0;
const timer = setInterval(() => {
this.errorDiagnostic = 'Incorrect username or password.';
i++;
if (i === 10) {
clearInterval(timer);
this.spinnerlogo = false;
this.errorDiagnostic = null;
}
}, 500);
});
}
login.component.spec.ts
it(`entering value in username and password input controls`, () => {
userNameEl.nativeElement.value = 'admin';
passwordEl.nativeElement.value = 'admin';
fixture.detectChanges();
});
it('after entering value the button should enabled and click Action should happen', () => {
submitEl.triggerEventHandler('click', null)
// tslint:disable-next-line:no-unused-expression
expect(comp.onSubmit).toHaveBeenCalled;
// const loginButtonSpy = spyOn(comp, 'onSubmit');
// submitEl.triggerEventHandler('click', null);
// expect(loginButtonSpy).toHaveBeenCalled();
});

how to unit test Angularfire2(version 5) auth service with google provider login

I'm trying to set up unit tests for a sample Angular5 app using AngularFire2 (version5) google provider login, My auth service is fairly simple and it looks like this:
let authState = null;
let mockAngularFireAuth: any = {authState: Observable.of(authState)};
#Injectable()
export class AuthService {
loggedIn: boolean;
private user: Observable<firebase.User>;
constructor(
public afAuth: AngularFireAuth
) {
this.user = afAuth.authState;
this.user.subscribe(
(user) => {
if (user) {
this.loggedIn = true;
} else {
this.loggedIn = false;
}
});
}
// --------------------------------- Google Login -----------------------------------
loginWithGoogle() {
// Sign in/up with google provider
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION)
.then(() => {
this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider())
.catch((error) => {
if (error.code === 'auth/account-exists-with-different-credential') {
alert('This email address is already registered');
}
});
});
}
// ------------------------- Checks User Authentication -----------------------
isAuthenticated() {
// returns true if the user is logged in
return this.loggedIn;
}
// --------------------------------- User LogOut -----------------------------------
logOut() {
this.afAuth.auth.signOut()
.then(() => {
this.loggedIn = false;
});
}
}
I want to test my loginWithGoogle() method but I am not sure where to start. So far my auth service spec file looks like this:
describe('AuthService', () => {
let authService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
AngularFireDatabaseModule,
AngularFireModule.initializeApp(environment.firebase),
RouterTestingModule
],
providers: [
{provide: AngularFireAuth, useValue: mockAngularFireAuth},
AuthService,
]
});
inject([AuthService], (service: AuthService) => {
authService = service;
})();
});
it('should be defined', () => {
expect(authService).toBeDefined();
});
it('should return true if loggedIn is true', () => {
expect(authService.isAuthenticated()).toBeFalsy();
authService.loggedIn = true;
expect(authService.isAuthenticated()).toBeTruthy();
});
});
Any help would be appreciated.
Well, this is what I did. I mocked the AngularFireAuth and returned the promise with reject or resolve promise to be caught. I am new to jasmine and testing, so feel free to correct me if I am doing something wrong.
it('should return a rejected promise', () => {
authState = {
email: 'lanchanagupta#gmail.com',
password: 'password',
};
mockAngularFireAuth = {
auth: jasmine.createSpyObj('auth', {
'signInWithPopup': Promise.reject({
code: 'auth/account-exists-with-different-credential'
}),
}),
authState: Observable.of(authState)
};
mockAngularFireAuth.auth.signInWithPopup()
.catch((error: { code: string }) => {
expect(error.code).toBe('auth/account-exists-with-different-credential');
});
});
it('should return a resolved promise', () => {
authState = {
email: 'lanchanagupta#gmail.com',
password: 'password',
uid: 'nuDdbfbhTwgkF5C6HN5DWDflpA83'
};
mockAngularFireAuth = {
auth: jasmine.createSpyObj('auth', {
'signInWithPopup': Promise.resolve({
user: authState
}),
})
};
mockAngularFireAuth.auth.signInWithPopup()
.then(data => {
expect(data['user']).toBe(authState);
});
});

Angular2, Ionic2 post to web service

import {Page, Platform} from 'ionic-angular';
import { Http, Headers, Response, RequestOptions, HTTP_PROVIDERS} from 'angular2/http';
import { bootstrap } from 'angular2/platform/browser';
import { Component, Injectable, Inject } from 'angular2/core';
import 'rxjs/Rx';
import { CORE_DIRECTIVES, FORM_DIRECTIVES } from 'angular2/common';
import {Observable} from 'rxjs/Observable';
#Page({
directives: [ CORE_DIRECTIVES, FORM_DIRECTIVES ],
templateUrl: 'build/pages/getting-started/getting-started.html'
})
#Injectable()
export class GettingStartedPage {
public platform;
public networkState;
private headers;
private _apiUrl = 'http://172.16.2.115:3004/message';
subject: string;
message: string;
comments: string;
constructor(platform: Platform, public http: Http) {
this.platform = platform;
this.headers = new Headers();
this.headers.append('Content-Type', 'application/x-www-form-urlencoded');
}
onSubmit(value) {
this.send(value.subject, value.body);
}
send(subject, body)
{
var message = "subject=" + subject + "&body=" + body;
let result = this.http.post(this._apiUrl,
body,
{
headers: this.headers
}).map(res => {
this.comments = res.json();
});
this.send(subject, body).subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
return result;
}
}
I am trying to create a mobile app using Ionic2 and Angular2 beta.This app will send an email using POST to a Rails web service. The Rails web service is working just fine. I dont seem to be getting to work the mobile app.
There was a misunderstanding
this.send(subject, body).subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
would be in a different method
onSubmit(value) {
this.send(value.subject, value.body)
.subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
}
send(subject, body)
{
var message = "subject=" + subject + "&body=" + body;
return this.http.post(this._apiUrl,
body,
{
headers: this.headers
}).map(res => {
this.comments = res.json();
});
}
You should refactor your code this way:
onSubmit(value) {
this.send(value.subject, value.body).subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
}
send(subject, body)
{
var message = "subject=" + subject + "&body=" + body;
let result = this.http.post(this._apiUrl,
body,
{
headers: this.headers
}).map(res => {
this.comments = res.json();
});
return result;
}