Skip to content

Commit

Permalink
Fixed #63, and refactor some part of test files (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
ofuochi committed Oct 10, 2019
1 parent 0c4f979 commit d3776e2
Show file tree
Hide file tree
Showing 16 changed files with 103 additions and 80 deletions.
30 changes: 15 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"@hapi/joi": "^16.1.7",
"@hasezoey/typegoose": "^5.9.2",
"agenda": "^2.1.0",
"automapper-nartc": "^3.0.23",
"automapper-nartc": "^3.1.2",
"bcrypt": "^3.0.6",
"body-parser": "^1.19.0",
"class-transformer": "^0.2.3",
Expand All @@ -72,7 +72,7 @@
"jsonwebtoken": "^8.5.1",
"mailgun-js": "^0.22.0",
"method-override": "^3.0.0",
"mongoose": "^5.7.3",
"mongoose": "^5.7.4",
"reflect-metadata": "^0.1.13",
"tsconfig-paths": "^3.9.0",
"winston": "^3.2.1",
Expand All @@ -86,14 +86,14 @@
"@types/cors": "^2.8.6",
"@types/dotenv": "^6.1.1",
"@types/express": "^4.17.1",
"@types/hapi__joi": "^16.0.0",
"@types/hapi__joi": "^16.0.1",
"@types/helmet": "0.0.44",
"@types/http-status-codes": "^1.2.0",
"@types/jsonwebtoken": "^8.3.4",
"@types/mailgun-js": "^0.22.3",
"@types/method-override": "0.0.31",
"@types/mocha": "^5.2.7",
"@types/mongoose": "^5.5.19",
"@types/mongoose": "^5.5.20",
"@types/supertest": "^2.0.8",
"@types/winston": "^2.4.4",
"@typescript-eslint/eslint-plugin": "^2.3.3",
Expand All @@ -113,7 +113,7 @@
"supertest": "^4.0.2",
"ts-mocha": "^6.0.0",
"ts-node": "^8.4.1",
"typescript": "^3.6.3"
"typescript": "^3.6.4"
},
"config": {
"ghooks": {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/interfaces/repositories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type Query<T> = {
};

export interface IBaseRepository<T> {
save(doc: T): Promise<T>;
insertOrUpdate(doc: T): Promise<T>;
findAll(): Promise<T[]>;
findById(id: string): Promise<T>;
hardFindById(id: string): Promise<T>;
Expand Down
13 changes: 7 additions & 6 deletions src/domain/model/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import { User } from "./user";
@pre<BaseEntity>("findOneAndUpdate", function(this: Query<BaseEntity>, next) {
try {
const entity = this.getUpdate();
const user = global.currentUser.user as User;
entity.updatedBy = user.id;

if (entity.isDeleted) {
entity.deletedBy = user.id;
entity.deletionTime = new Date();
const user = (global.currentUser && global.currentUser.user) as User;
if (user) {
entity.updatedBy = user.id;
if (entity.isDeleted) {
entity.deletedBy = user.id;
entity.deletionTime = new Date();
}
}
next();
} catch (error) {
Expand Down
7 changes: 3 additions & 4 deletions src/domain/utils/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ import { User } from "../model/user";
import { Writable } from "./writable";

export class CurrentUser {
private static _instance: CurrentUser;
private static Instance: CurrentUser;
readonly tenant: Tenant;
readonly user?: User;
private constructor(tenant: Tenant, user?: User) {
this.tenant = tenant;
this.user = user;
}
static createInstance = (tenant: Tenant, user?: User): CurrentUser => {
if (CurrentUser._instance) return CurrentUser._instance;
const newInstance = new CurrentUser(tenant, user);
return newInstance;
if (CurrentUser.Instance) return CurrentUser.Instance;
return new CurrentUser(tenant, user);
};
setUser = (user: User) => {
(this as Writable<CurrentUser>).user = user;
Expand Down
2 changes: 1 addition & 1 deletion src/infrastructure/config/inversify.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { ITenantService } from "../../ui/interfaces/tenant_service";
import { TenantProfile } from "../../ui/profiles/tenant_profile";

// Service implementations
import { LoggerService } from "../../domain/services/logger_service";
import { LoggerService } from "../services/logger_service";
import { MailService } from "../services/mail_service";
import { AuthService } from "../../ui/services/auth_service";
import { TenantService } from "../../ui/services/tenant_service";
Expand Down
11 changes: 5 additions & 6 deletions src/infrastructure/db/repositories/base_repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { BaseEntity } from "../../../domain/model/base";
export class BaseRepository<TEntity extends BaseEntity, TModel extends Document>
implements IBaseRepository<TEntity> {
protected Model: Model<TModel>;
protected CurrentTenantId?: string =
global.currentUser && global.currentUser.tenant.id;
protected _constructor: () => TEntity;
public constructor(
@unmanaged() model: Model<TModel>,
Expand All @@ -21,14 +23,11 @@ export class BaseRepository<TEntity extends BaseEntity, TModel extends Document>
this._constructor = constructor;
}

// We wrap the mongoose API here so we can use async / await

public async findAll() {
return new Promise<TEntity[]>((resolve, reject) => {
this.Model.find((err, res) => {
if (err) return reject(err);
let results = res.map(r => this.readMapper(r));
results = results.filter(r => !r.isDeleted);
const results = res.map(r => this.readMapper(r));
return resolve(results);
});
});
Expand Down Expand Up @@ -57,7 +56,7 @@ export class BaseRepository<TEntity extends BaseEntity, TModel extends Document>
});
}

public async save(doc: TEntity): Promise<TEntity> {
public async insertOrUpdate(doc: TEntity): Promise<TEntity> {
return new Promise<TEntity>((resolve, reject) => {
if (doc.id) {
this.Model.findByIdAndUpdate(
Expand Down Expand Up @@ -119,7 +118,7 @@ export class BaseRepository<TEntity extends BaseEntity, TModel extends Document>
const item = await this.findById(id);
if (!item) return false;
item.delete();
await this.save(item);
await this.insertOrUpdate(item);
return true;
}
// deleteOneByQuery(query: Query<TEntity>): Promise<number> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { injectable } from "inversify";
import {
winstonLoggerInstance,
IWinstonLogger
} from "../../infrastructure/bootstrapping/loaders/logger";
import { ILoggerService } from "../interfaces/services";
} from "../bootstrapping/loaders/logger";
import { ILoggerService } from "../../domain/interfaces/services";

@injectable()
export class LoggerService implements ILoggerService {
Expand Down
14 changes: 8 additions & 6 deletions src/ui/profiles/tenant_profile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MappingProfileBase } from "automapper-nartc";
import { MappingProfileBase, AutoMapper } from "automapper-nartc";
import { Tenant } from "../../domain/model/tenant";
import { TenantDto } from "../models/tenant_dto";

Expand All @@ -7,9 +7,11 @@ export class TenantProfile extends MappingProfileBase {
super();
}

configure(): void {
this.createMap(Tenant, TenantDto)
.forMember("id", options => options.mapFrom(tenant => tenant.id.toString()));
configure(mapper: AutoMapper): void {
mapper
.createMap(Tenant, TenantDto)
.forMember("id", options =>
options.mapFrom(tenant => tenant.id.toString())
);
}

}
}
12 changes: 7 additions & 5 deletions src/ui/profiles/user_profile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MappingProfileBase } from "automapper-nartc";
import { MappingProfileBase, AutoMapper } from "automapper-nartc";
import { UserDto } from "../models/user_dto";
import { User } from "../../domain/model/user";

Expand All @@ -7,9 +7,11 @@ export class UserProfile extends MappingProfileBase {
super();
}

configure(): void {
this.createMap(User, UserDto).forMember("id", options =>
options.mapFrom(user => user.id.toString())
);
configure(mapper: AutoMapper): void {
mapper
.createMap(User, UserDto)
.forMember("id", options =>
options.mapFrom(user => user.id.toString())
);
}
}
2 changes: 1 addition & 1 deletion src/ui/services/auth_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class AuthService implements IAuthService {
});
if (user) throw new HttpError(httpStatus.CONFLICT);

user = await this._userRepository.save(
user = await this._userRepository.insertOrUpdate(
User.createInstance({
...dto,
password: hashedPassword
Expand Down
2 changes: 1 addition & 1 deletion src/ui/services/tenant_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class TenantService implements ITenantService {
@tenantRepository public _tenantRepository: ITenantRepository;

async create(name: string, description: string): Promise<TenantDto> {
const tenant = await this._tenantRepository.save(
const tenant = await this._tenantRepository.insertOrUpdate(
Tenant.createInstance(name, description)
);
return this._mapper.map(tenant, TenantDto);
Expand Down
30 changes: 30 additions & 0 deletions test/infrastructure/db/repository/tenant_repository.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { TYPES } from "../../../../src/domain/constants/types";
import { ITenantRepository } from "../../../../src/domain/interfaces/repositories";
import { Tenant } from "../../../../src/domain/model/tenant";
import { container } from "../../../../src/infrastructure/utils/ioc_container";
import { cleanupDb } from "../../../setup";

describe("Tenant Repository", () => {
const tenants: Tenant[] = [
Tenant.createInstance("T0", "T0"),
Tenant.createInstance("T1", "T1"),
Tenant.createInstance("T2", "T2")
];
let tenantRepository: ITenantRepository;
before("Create seed tenants", async () => {
await cleanupDb();
tenantRepository = container.get<ITenantRepository>(
TYPES.TenantRepository
);
tenants.forEach(async (doc, i) => {
tenants[i] = await tenantRepository.insertOrUpdate(doc);
});
});
it("should get all the tenants without the deleted one", async () => {
tenants[0].delete();
// console.log(tenants);
// await tenantRepository.insertOrUpdate(tenants[0]);
// const res = await tenantRepository.findAll();
// expect(res.length).to.equal(2);
});
});
18 changes: 1 addition & 17 deletions test/setup.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import { Server } from "http";
import { cleanUpMetadata } from "inversify-express-utils";
import { MongoMemoryServer } from "mongodb-memory-server";
import mongoose from "mongoose";
import supertest from "supertest";

import { TYPES } from "../src/domain/constants/types";
import { ITenantRepository } from "../src/domain/interfaces/repositories";
import { Tenant } from "../src/domain/model/tenant";
import { bootstrap } from "../src/infrastructure/bootstrapping";
import { referenceDataIoCModule } from "../src/infrastructure/config/inversify.config";
import { container } from "../src/infrastructure/utils/ioc_container";
Expand All @@ -28,21 +24,9 @@ before("Setup", async () => {

server = startAppServer(app);
req = supertest(server);
cleanUpMetadata();

const tenantRepository = container.get<ITenantRepository>(
TYPES.TenantRepository
);
const tenant = await tenantRepository.findOneByQuery({
name: "Default"
});
if (!tenant)
await tenantRepository.save(
Tenant.createInstance("Default", "Default tenant")
);
});

async function cleanupDb() {
export async function cleanupDb() {
const collections = await mongoose.connection.db
.listCollections(undefined, { nameOnly: true })
.toArray();
Expand Down
12 changes: 7 additions & 5 deletions test/ui/api/auth_controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
UserSignUpInput
} from "../../../src/ui/models/user_dto";
import { TYPES } from "../../../src/domain/constants/types";
import { req } from "../../setup";
import { req, cleanupDb } from "../../setup";

const endpoint = `${config.api.prefix}/auth`;
const tenantHeaderProp = "x-tenant-id";
Expand All @@ -25,17 +25,19 @@ describe("Auth controller", () => {
let tenant1: Tenant;
let tenant2: Tenant;
before(async () => {
await cleanupDb();

tenantRepository = container.get<ITenantRepository>(
TYPES.TenantRepository
);

// Get first tenant because it already exists from the setup.ts file
tenant1 = await tenantRepository.findOneByQuery({
name: "Default"
});
tenant1 = await tenantRepository.insertOrUpdate(
Tenant.createInstance("Tenant1", "Second tenant")
);

// Create a second tenant
tenant2 = await tenantRepository.save(
tenant2 = await tenantRepository.insertOrUpdate(
Tenant.createInstance("Tenant2", "Second tenant")
);
tenant = tenant1;
Expand Down
Loading

0 comments on commit d3776e2

Please sign in to comment.