From 4193b27b04c889d388471fae3309abc950014c39 Mon Sep 17 00:00:00 2001 From: ezzabuzaid Date: Wed, 9 Oct 2019 22:00:37 +0300 Subject: [PATCH] add a test to user api --- src/app/api/portal/portal.specs.ts | 2 ++ src/app/api/users/users.model.ts | 11 ++++---- src/app/api/users/users.spec.ts | 45 ++++++++++++++++++------------ src/app/server.ts | 10 ++++--- src/app/shared/crud/crud.spec.ts | 4 +++ src/assets/languages/en.json | 5 +++- src/lib/mongoose/field.ts | 6 ++-- src/lib/mongoose/index.ts | 4 ++- src/lib/translation/local.ts | 13 ++++----- src/lib/translation/translation.ts | 20 +++++++------ src/main.ts | 8 ++++-- src/test/fixture.ts | 4 +-- 12 files changed, 81 insertions(+), 51 deletions(-) diff --git a/src/app/api/portal/portal.specs.ts b/src/app/api/portal/portal.specs.ts index 870e4ca7..fdb9e0ab 100644 --- a/src/app/api/portal/portal.specs.ts +++ b/src/app/api/portal/portal.specs.ts @@ -16,3 +16,5 @@ // // request.send(exclude(user, 'email')); // }); + +// in login check login test cases diff --git a/src/app/api/users/users.model.ts b/src/app/api/users/users.model.ts index 7ef11c98..4d8b8efc 100644 --- a/src/app/api/users/users.model.ts +++ b/src/app/api/users/users.model.ts @@ -3,26 +3,26 @@ import { BaseModel, Entity, Field } from '@lib/mongoose'; import { ValidationPatterns } from '@shared/common'; import { parsePhoneNumberFromString } from 'libphonenumber-js'; import { Query } from 'mongoose'; +import { translate } from '@lib/translation'; @Entity(Constants.Schemas.USERS) export class UsersSchema { - @Field({ lowercase: false }) public password: string; + @Field({ pure: true, }) public password: string; @Field({ - match: [ValidationPatterns.NoSpecialChar, 'Value contain special char'], + match: [ValidationPatterns.NoSpecialChar, translate('no_speical_char')], unique: true, }) public username: string; @Field({ - match: [ValidationPatterns.EmailValidation, 'Please provide a valid email address'], + match: [ValidationPatterns.EmailValidation, translate('wrong_email')], unique: true, }) public email: string; - @Field({ validate: [ (value) => { const phonenumber = parsePhoneNumberFromString(value); return !!phonenumber && phonenumber.isValid(); }, - 'Please enter correct phonenumber' + translate('wrong_mobile_number') ], unique: true, }) public mobile: string; @@ -38,6 +38,7 @@ export class UsersSchema { } export const UsersModel = BaseModel(UsersSchema); + UsersModel.schema.pre('find', () => { (this as unknown as Query).select({ password: 0 }); }); diff --git a/src/app/api/users/users.spec.ts b/src/app/api/users/users.spec.ts index c10e1178..475cc700 100644 --- a/src/app/api/users/users.spec.ts +++ b/src/app/api/users/users.spec.ts @@ -33,21 +33,35 @@ describe('CREATE USER', () => { const deleteReq = await (await superAgent).delete(`${ENDPOINT}/${res1.body.id}`); expect(res2.status).toBe(NetworkStatus.BAD_REQUEST); }); + test('Special Char is not allowed', async () => { + const body = { + email: 'test@create2.com', + mobile: '0792807794', + password: '123456789', + username: 'testCreate2#$' + } as Body; + const req = (await superAgent).post(ENDPOINT); + const res = await req.send(body); + const deleteReq = await (await superAgent).delete(`${ENDPOINT}/${res.body.id}`); + expect(res.status).toBe(NetworkStatus.BAD_REQUEST); + }); + test('Mobile number shouldn"t be wrong', async () => { + const body = { + email: 'test@create3.com', + mobile: '079280779', + password: '123456789', + username: 'testCreate3' + } as Body; + const req = (await superAgent).post(ENDPOINT); + const res = await req.send(body); + const deleteReq = await (await superAgent).delete(`${ENDPOINT}/${res.body.id}`); + expect(res.status).toBe(NetworkStatus.BAD_REQUEST); + }); }); -// describe('GET ALL', () => { -// test('Reject request without token', async () => { -// const res = (await (await superAgent).get(`${ENDPOINT}`)); -// expect(res.status).toBe(NetworkStatus.UNAUTHORIZED); -// }); - -// test('Should return list', async () => { -// const req = (await superAgent).get(`${ENDPOINT}`); -// const res = await req.set('Authorization', user.token); -// expect(res.status).toBe(NetworkStatus.OK); -// expect(res.body.data).toBeInstanceOf(Array); -// }); -// }); +// STUB CREATE: user password should be hashed +// STUB CREATE: user should have an account +// STUB DELETE: remove associated account // describe('GET BY ${id}/', () => { // test('Reject request without token', async () => { @@ -110,8 +124,3 @@ describe('CREATE USER', () => { // }); // tslint:disable-next-line: max-line-length -// REVIEW in create and update you should check and verify if the data was update or created successfully other that the failur test -// and in delete you must check that the entity no longer in database -// in update and create you must test the validation by insert Wrong data -// in login check login test cases -// try to send wrong mobile, email diff --git a/src/app/server.ts b/src/app/server.ts index 2377a129..90efe43a 100644 --- a/src/app/server.ts +++ b/src/app/server.ts @@ -24,8 +24,8 @@ export class NodeServer extends Application { const server = new NodeServer(); const httpServer = await server.populateServer(); // server.application.get('/socket/:name', handleSocket); - server.application.get('/webhooks/github/deploy', deploy); - await server.init(); + // server.application.get('/webhooks/github/deploy', deploy); + return server.init(); } public static test() { @@ -65,10 +65,12 @@ export class NodeServer extends Application { } private init() { - const { MONGO_USER: user, + const { + MONGO_USER: user, MONGO_PASSWORD: password, MONGO_PATH: path, - MONGO_HOST: host } = envirnoment.env; + MONGO_HOST: host + } = envirnoment.env; log.debug(stage.LEVEL); try { return Promise.all([ diff --git a/src/app/shared/crud/crud.spec.ts b/src/app/shared/crud/crud.spec.ts index b52278d1..a7b302df 100644 --- a/src/app/shared/crud/crud.spec.ts +++ b/src/app/shared/crud/crud.spec.ts @@ -39,3 +39,7 @@ describe('Add router to wrapper', () => { // in update and create you must test the validation by insert Wrong data // in login check login test cases // try to send wrong mobile, email + +// REVIEW in create and update you should check and verify if the data was update or created successfully +// other that the failur test +// and in delete you must check that the entity no longer in database diff --git a/src/assets/languages/en.json b/src/assets/languages/en.json index ed25caaa..b3c9eb03 100644 --- a/src/assets/languages/en.json +++ b/src/assets/languages/en.json @@ -16,5 +16,8 @@ "not_exist": "Entity not exist", "success": "Sucesss", "error": "Error", - "email_exist": "email_exist" + "email_exist": "email_exist", + "no_speical_char": "Value contains special char", + "wrong_email": "Please provide a valid email address", + "wrong_mobile_number": "Please enter correct phonenumber" } \ No newline at end of file diff --git a/src/lib/mongoose/field.ts b/src/lib/mongoose/field.ts index c26390da..f5bea8bb 100644 --- a/src/lib/mongoose/field.ts +++ b/src/lib/mongoose/field.ts @@ -2,7 +2,9 @@ import { AppUtils } from '@core/utils'; import 'reflect-metadata'; import { MongooseTypes } from '.'; -export function Field(options: Exclude = {}) { +// TODO: the `type` property should be in the `options` type + +export function Field(options: MongooseTypes.FieldOptions) { return (instance: MongooseTypes.IFieldAttr & T, propertyKey: string) => { if (instance && !instance.fields) { AppUtils.defineProperty(instance, 'fields', { value: {} }); @@ -10,7 +12,7 @@ export function Field(options: Exclude | Schema | SchemaType; + export type FieldOptions = SchemaTypeOpts | Schema | SchemaType & { + pure?: boolean + }; export interface IFieldAttr { fields: { [keys: string]: FieldOptions }; } diff --git a/src/lib/translation/local.ts b/src/lib/translation/local.ts index 9a8f3515..a1149eca 100644 --- a/src/lib/translation/local.ts +++ b/src/lib/translation/local.ts @@ -1,4 +1,4 @@ -import { development } from '@core/helpers'; +import { stage, StageLevel } from '@core/helpers'; import { Logger } from '@core/utils'; const log = new Logger('Local Class'); @@ -19,7 +19,7 @@ export class Local { * @param name name of the local * @param language local object */ - constructor(name, language: object) { + constructor(name: string, language: object) { this.name = name; this._language = language; } @@ -37,11 +37,9 @@ export class Local { * @param value */ public set(key: string, value: any) { - development( - () => { - log.warn(`a key with name ${key} is already hold a value`); - } - ); + stage.test(StageLevel.DEV, () => { + log.warn(`a key with name ${key} is already hold a value`); + }); this.language[key] = value; } @@ -55,7 +53,6 @@ export class Local { if (!value) { throw new Error(`the key { ${key} } is not found in local { ${this.name} }`); } - return value; } } diff --git a/src/lib/translation/translation.ts b/src/lib/translation/translation.ts index 6c304420..26eee5ad 100644 --- a/src/lib/translation/translation.ts +++ b/src/lib/translation/translation.ts @@ -109,13 +109,17 @@ export const translation = new Translation(); * @returns the value of the key from the active local */ export function translate(key: string, params: object = {}) { - let value = translation.local.get(key); - const rawParams = value.match(/\{(.*?)\}/ig); - if (rawParams) { - value = rawParams.reduce((acc, el) => { - const param = el.substring(1, el.length - 1); - return `${acc}${value.replace(/\{(.*?)\}/, params[param])}`; - }, ''); + try { + let value = translation.local.get(key); + const rawParams = value.match(/\{(.*?)\}/ig); + if (rawParams) { + value = rawParams.reduce((acc, el) => { + const param = el.substring(1, el.length - 1); + return `${acc}${value.replace(/\{(.*?)\}/, params[param])}`; + }, ''); + } + return value; + } catch (error) { + return key; } - return value; } diff --git a/src/main.ts b/src/main.ts index 1b4bee8c..4654fc6c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,8 @@ import { NodeServer } from './app/server'; -NodeServer.bootstrap(); process.chdir('./src/'); -console.log('Node verions is => ', process.version); + +NodeServer.bootstrap() + .then(() => { + console.log('Node verions is => ', process.version); + console.log('Node title is => ', process.title); + }); diff --git a/src/test/fixture.ts b/src/test/fixture.ts index 7fea5b81..29d78026 100644 --- a/src/test/fixture.ts +++ b/src/test/fixture.ts @@ -15,9 +15,9 @@ export function getUri(value: string) { export async function createUser() { const req = (await superAgent).post(usersUri); const res = await req.send({ - email: 'test@test.com', + email: `test@test.com`, password: '123456789', - username: 'test', + username: `test`, mobile: '+962792807794' }); user.id = res.body.data._id;