Skip to content

Commit

Permalink
wip: unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
arden-dave-sun committed Sep 8, 2023
1 parent 6454a9a commit d49b988
Show file tree
Hide file tree
Showing 20 changed files with 1,034 additions and 371 deletions.
1 change: 1 addition & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"jest-junit": "^16.0.0",
"moment": "^2.29.4",
"nestjs-seeder": "^0.3.2",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1"
Expand Down
26 changes: 26 additions & 0 deletions server/src/api/job/dtos/person-in-charge.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { OmitType } from "@nestjs/swagger";
import { IsString } from "class-validator";
import { UserDto } from "../../user/dtos/user.dto";
import { Exclude, Expose } from "class-transformer";

export class PersonInChargeDto extends OmitType(UserDto, [
"createdAt",
"updatedAt",
]) {
@Exclude()
createdAt: Date;

@Exclude()
updatedAt: Date;

@Expose()
@IsString()
get fullname(): string | undefined {
return `${this.firstName} ${this.lastName}`;
}

constructor(partial: Partial<PersonInChargeDto>) {
super();
Object.assign(this, partial);
}
}
182 changes: 128 additions & 54 deletions server/src/api/job/job.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,45 @@
import { $Enums } from '@prisma/client';
import { $Enums } from "@prisma/client";

import { PrismaService } from '../../database/connection.service';
import { PrismaService } from "../../database/connection.service";

import { JobService } from './job.service';
import { JobController } from './job.controller';
import { CustomerService } from '../customer/customer.service';
import { JobService } from "./job.service";
import { JobController } from "./job.controller";
import { CustomerService } from "../customer/customer.service";
import { Test } from "@nestjs/testing";
import { NotFoundException } from "@nestjs/common";
import { PersonInChargeDto } from "./dtos/person-in-charge.dto";

describe('JobController', () => {
describe("JobController", () => {
let jobService: JobService;
let jobController: JobController;
let customerService: CustomerService
let prisma: PrismaService

beforeEach(() => {
jobService = new JobService(prisma, customerService)
jobController = new JobController(jobService)
let prisma: PrismaService;

const mockPrisma = {
job: {
groupBy: jest.fn(),
},
user: {
findMany: jest.fn(),
},
};

beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
controllers: [JobController],
providers: [
JobService,
CustomerService,
{ provide: PrismaService, useValue: mockPrisma },
],
}).compile();

jobController = moduleRef.get<JobController>(JobController);
jobService = moduleRef.get<JobService>(JobService);
prisma = moduleRef.get<PrismaService>(PrismaService);
});

describe('create', () => {
it('should return a new job', async () => {
describe("create", () => {
it("should return a new job", async () => {
const jobInput = {
customer_registration: {
firstName: "John",
Expand All @@ -34,8 +55,8 @@ describe('JobController', () => {
remarks: "string",
paymentMethod: $Enums.PaymentMethod.CASH,
},
work_schedules: []
}
work_schedules: [],
};

const newJob = {
id: 1,
Expand All @@ -46,50 +67,57 @@ describe('JobController', () => {
customerId: 1,
paymentMethod: $Enums.PaymentMethod.CASH,
userId: 1,
}
};

const mockCreateJobWithCustomerAndSchedules = jest
.fn()
.mockResolvedValue(newJob);

const mockCreateJobWithCustomerAndSchedules = jest.fn().mockResolvedValue(newJob)

jest.spyOn(jobService, 'createJobWithCustomerAndSchedules').mockImplementation(mockCreateJobWithCustomerAndSchedules)
const createdJob = await jobController.create(jobInput)
jest
.spyOn(jobService, "createJobWithCustomerAndSchedules")
.mockImplementation(mockCreateJobWithCustomerAndSchedules);

const createdJob = await jobController.create(jobInput);

expect(createdJob).toEqual(newJob);
})
})
});
});

describe('findAll', () => {
it('should return an array of jobs', async () => {
const jobs = [{
id: 1,
title: "Sample title 1",
type: "A",
tags: [$Enums.Tag.TAG_A],
remarks: "",
customerId: 1,
paymentMethod: "CARD",
userId: 1,
}, {
id: 2,
title: "Sample title 2",
type: "A",
tags: [$Enums.Tag.TAG_A],
remarks: "",
customerId: 1,
paymentMethod: "CARD",
userId: 1,
}];
describe("findAll", () => {
it("should return an array of jobs", async () => {
const jobs = [
{
id: 1,
title: "Sample title 1",
type: "A",
tags: [$Enums.Tag.TAG_A],
remarks: "",
customerId: 1,
paymentMethod: "CARD",
userId: 1,
},
{
id: 2,
title: "Sample title 2",
type: "A",
tags: [$Enums.Tag.TAG_A],
remarks: "",
customerId: 1,
paymentMethod: "CARD",
userId: 1,
},
];

jest.spyOn(jobService, 'findAll').mockResolvedValue(jobs)
jest.spyOn(jobService, "findAll").mockResolvedValue(jobs);

const foundJobs = await jobController.findAll();

expect(foundJobs).toEqual(jobs);
})
})
});
});

describe('findOne', () => {
it('should return a single job', async () => {
describe("findOne", () => {
it("should return a single job", async () => {
const job = {
id: 1,
title: "Sample title 1",
Expand All @@ -99,13 +127,59 @@ describe('JobController', () => {
customerId: 1,
paymentMethod: "CARD",
userId: 1,
}
};

jest.spyOn(jobService, 'findOne').mockResolvedValue(job);
jest.spyOn(jobService, "findOne").mockResolvedValue(job);

const foundJob = await jobController.findOne(1);

expect(foundJob).toEqual(job);
})
})
});
});

describe("findAllTypes", () => {
const mockValues = [
{ type: "developer" },
{ type: "writer" },
{ type: "designer" },
];

it("should return string array of types", async () => {
prisma.job.groupBy = jest.fn().mockResolvedValue(mockValues);

const expectedReturn = ["developer", "writer", "designer"];
const returnedTypes = await jobController.findAllTypes();
expect(returnedTypes).toEqual(expectedReturn);
});

it("should throw error", async () => {
jobService.findAllTypes = jest.fn().mockResolvedValue([]);
expect(async () => jobController.findAllTypes()).rejects.toThrow(
NotFoundException,
);
});
});

describe("findAllPersonInCharge", () => {
const mockReturnValues = [
{ id: 1, name: "john" },
{ id: 2, name: "doe" },
{ id: 3, name: "jane" },
];

it("should return array of PersonInChargeDto", async () => {
prisma.user.findMany = jest.fn().mockResolvedValue(mockReturnValues);

const result = await jobController.findAllPersonInCharge();

expect(result).toBeInstanceOf(Array<PersonInChargeDto>);
});

it("should throw error", async () => {
jobService.findAllPersonInCharge = jest.fn().mockResolvedValue([]);
expect(async () => jobController.findAllPersonInCharge()).rejects.toThrow(
NotFoundException,
);
});
});
});
109 changes: 74 additions & 35 deletions server/src/api/job/job.controller.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,87 @@
import { Job } from '@prisma/client';
import { ApiTags } from '@nestjs/swagger';
import { BadRequestException, Body, Controller, Get, NotFoundException, Param, ParseIntPipe, Post, UsePipes, ValidationPipe } from '@nestjs/common';
import { Job } from "@prisma/client";
import { ApiTags } from "@nestjs/swagger";
import {
BadRequestException,
Body,
ClassSerializerInterceptor,
Controller,
Get,
NotFoundException,
Param,
ParseIntPipe,
Post,
UseInterceptors,
UsePipes,
ValidationPipe,
} from "@nestjs/common";

import { JobService } from './job.service';
import { JobService } from "./job.service";

import { CreateJobWithCustomerAndSchedulesDto } from './dtos/create-job-with-customer-and-schedule.dto';
import { CreateJobWithCustomerAndSchedulesDto } from "./dtos/create-job-with-customer-and-schedule.dto";
import { PersonInChargeDto } from "./dtos/person-in-charge.dto";

@ApiTags('job')
@Controller('job')
@ApiTags("job")
@Controller("job")
export class JobController {
constructor(
private readonly jobService: JobService
) { }

@Post()
@UsePipes(new ValidationPipe())
async create(@Body() options: CreateJobWithCustomerAndSchedulesDto): Promise<Job> {
const job = await this.jobService.createJobWithCustomerAndSchedules(options);

if (!job ) {
throw new BadRequestException("Something went wrong. Job not created.")
}

return job;
constructor(private readonly jobService: JobService) {}

@Get("types")
async findAllTypes(): Promise<string[]> {
const types = await this.jobService.findAllTypes();

if (types.length === 0) {
throw new NotFoundException("No job types found.");
}

@Get()
async findAll(): Promise<Job[]> {
const jobs = await this.jobService.findAll()
return types;
}

@Get("personInCharge")
@UseInterceptors(ClassSerializerInterceptor)
async findAllPersonInCharge(): Promise<PersonInChargeDto[]> {
const person = await this.jobService.findAllPersonInCharge();

if (jobs == 0) {
throw new NotFoundException("No job found.")
}
return jobs
if (person.length === 0) {
throw new NotFoundException("No person in charge found.");
}

@Get('/:id')
async findOne(@Param('id', ParseIntPipe) id: number): Promise<Job> {
const job = await this.jobService.findOne({ id })
return person.map((person) => new PersonInChargeDto({ ...person }));
}

if (!job) {
throw new NotFoundException("No job found.")
}
@Post()
@UsePipes(new ValidationPipe())
async create(
@Body() options: CreateJobWithCustomerAndSchedulesDto,
): Promise<Job> {
const job = await this.jobService.createJobWithCustomerAndSchedules(
options,
);

return job
if (!job) {
throw new BadRequestException("Something went wrong. Job not created.");
}

return job;
}

@Get()
async findAll(): Promise<Job[]> {
const jobs = await this.jobService.findAll();

if (jobs == 0) {
throw new NotFoundException("No job found.");
}
return jobs;
}

@Get("/:id")
async findOne(@Param("id", ParseIntPipe) id: number): Promise<Job> {
const job = await this.jobService.findOne({ id });

if (!job) {
throw new NotFoundException("No job found.");
}

return job;
}
}
Loading

0 comments on commit d49b988

Please sign in to comment.