-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
334 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import prisma from "../src/application/database"; | ||
import bcrypt from "bcrypt"; | ||
import supertest from "supertest"; | ||
import { basePath, web } from "../src/application/web"; | ||
import { Address, Contact } from "@prisma/client"; | ||
import logger from "../src/application/logger"; | ||
|
||
describe("POST /contacts/:contactId/addresses", () => { | ||
let token: string = ""; | ||
let contact: Contact = {} as Contact; | ||
|
||
beforeAll(async () => { | ||
token = await AddressTestUtil.getToken(); | ||
contact = await AddressTestUtil.createContact(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await AddressTestUtil.deleteAddress(); | ||
await AddressTestUtil.deleteContact(); | ||
await AddressTestUtil.deleteUser(); | ||
}) | ||
|
||
it("should return 200 - success creating an address", async () => { | ||
const res = await supertest(web) | ||
.post(`${basePath}/contacts/${contact.id}/addresses`) | ||
.send(AddressTestUtil.address) | ||
.set('Authorization', `Bearer ${token}`); | ||
|
||
logger.info(res.body); | ||
expect(res.status).toBe(200); | ||
expect(res.body.data.id).toBeGreaterThanOrEqual(1); | ||
expect(res.body.data.street).toBe(AddressTestUtil.address.street); | ||
expect(res.body.data.city).toBe(AddressTestUtil.address.city); | ||
expect(res.body.data.province).toBe(AddressTestUtil.address.province); | ||
expect(res.body.data.country).toBe(AddressTestUtil.address.country); | ||
expect(res.body.data.postal_code).toBe(AddressTestUtil.address.postal_code); | ||
}); | ||
|
||
it("should return 200 - success creating an address with empty street, city, and province", async () => { | ||
const res = await supertest(web) | ||
.post(`${basePath}/contacts/${contact.id}/addresses`) | ||
.send({ | ||
country: AddressTestUtil.address.country, | ||
postal_code: AddressTestUtil.address.postal_code, | ||
}) | ||
.set('Authorization', `Bearer ${token}`); | ||
|
||
logger.info(res.body); | ||
expect(res.status).toBe(200); | ||
expect(res.body.data.id).toBeGreaterThanOrEqual(1); | ||
expect(res.body.data.street).toBe(""); | ||
expect(res.body.data.city).toBe(""); | ||
expect(res.body.data.province).toBe(""); | ||
expect(res.body.data.country).toBe(AddressTestUtil.address.country); | ||
expect(res.body.data.postal_code).toBe(AddressTestUtil.address.postal_code); | ||
}); | ||
|
||
it("should return 400 - invalid postal code", async () => { | ||
const res = await supertest(web) | ||
.post(`${basePath}/contacts/${contact.id}/addresses`) | ||
.send({ | ||
country: AddressTestUtil.address.country, | ||
postal_code: "123", | ||
}) | ||
.set('Authorization', `Bearer ${token}`); | ||
|
||
logger.info(res.body); | ||
expect(res.status).toBe(400); | ||
expect(res.body.errors.postal_code).toBeDefined(); | ||
}); | ||
|
||
it("should return 401 - empty authorization", async () => { | ||
const res = await supertest(web) | ||
.post(`${basePath}/contacts/${contact.id}/addresses`) | ||
.send(AddressTestUtil.address); | ||
|
||
logger.info(res.body); | ||
expect(res.status).toBe(401); | ||
expect(res.body.errors).toBeDefined(); | ||
}); | ||
}); | ||
|
||
class AddressTestUtil { | ||
static user = { | ||
name: "user_test_address", | ||
username: "user_test_address", | ||
password: "password" | ||
}; | ||
|
||
static contact = { | ||
first_name: "First", | ||
last_name: "Last", | ||
email: "[email protected]", | ||
phone: "08123456789" | ||
}; | ||
|
||
static address = { | ||
street: "Test Street", | ||
city: "Test City", | ||
province: "Test Province", | ||
country: "Test Country", | ||
postal_code: "123456", | ||
} | ||
|
||
static async createUser() { | ||
await prisma.user.create({ | ||
data: { | ||
name: AddressTestUtil.user.name, | ||
username: AddressTestUtil.user.username, | ||
password: await bcrypt.hash(AddressTestUtil.user.password, 10) | ||
} | ||
}); | ||
} | ||
|
||
static async getToken() { | ||
await AddressTestUtil.createUser(); | ||
|
||
const loginRes = await supertest(web) | ||
.post(`${basePath}/auth/login`) | ||
.send({ | ||
username: AddressTestUtil.user.username, | ||
password: AddressTestUtil.user.password, | ||
}); | ||
|
||
return loginRes.body.data.token; | ||
} | ||
|
||
static async deleteUser() { | ||
await prisma.user.deleteMany({}); | ||
} | ||
|
||
static async createContact(): Promise<Contact> { | ||
const contact = await prisma.contact.create({ | ||
data: { | ||
...AddressTestUtil.contact, | ||
username: AddressTestUtil.user.username | ||
} | ||
}); | ||
|
||
return contact as Contact; | ||
} | ||
|
||
static async deleteContact() { | ||
await prisma.contact.deleteMany({}); | ||
} | ||
|
||
static async createAddress(contactId: number): Promise<Address> { | ||
const address = await prisma.address.create({ | ||
data: { | ||
...AddressTestUtil.address, | ||
contact_id: contactId | ||
} | ||
}); | ||
|
||
return address as Address; | ||
} | ||
|
||
static async deleteAddress() { | ||
await prisma.address.deleteMany({}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { Request, Response, NextFunction } from "express"; | ||
import AddressService from "../service/address"; | ||
import { AddressRequest } from "../model/address"; | ||
import { ResponseError } from "../error/response"; | ||
|
||
export class AddressController { | ||
|
||
static async create(req: Request, res: Response, next: NextFunction) { | ||
try { | ||
if (isNaN(Number(req.params.contactId)) || Number(req.params.contactId) < 1) { | ||
throw new ResponseError(404, "contact doesn't exists"); | ||
} | ||
|
||
const createReq = req.body as AddressRequest; | ||
createReq.contact_id = Number(req.params.contactId); | ||
|
||
const createRes = await AddressService.create(res.locals.user.usename, createReq); | ||
|
||
return res.status(200) | ||
.json({ | ||
data: createRes | ||
}); | ||
} catch (e) { | ||
next(e); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Address } from "@prisma/client"; | ||
|
||
export interface AddressRequest { | ||
street?: string, | ||
city?: string, | ||
province?: string, | ||
country: string, | ||
postal_code: string, | ||
contact_id: number | ||
} | ||
|
||
export interface AddressResponse { | ||
id: number, | ||
street?: string, | ||
city?: string, | ||
province?: string, | ||
country: string, | ||
postal_code: string, | ||
} | ||
|
||
export function toAddressResponse(address: Address): AddressResponse { | ||
return { | ||
id: address.id, | ||
street: address.street ?? "", | ||
city: address.city ?? "", | ||
province: address.province ?? "", | ||
country: address.country, | ||
postal_code: address.postal_code | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import express from "express"; | ||
import { accessValidation } from "../middleware/accessValidation"; | ||
import { AddressController } from "../controller/address"; | ||
|
||
export const getAddressRouter = (basePath: string) => { | ||
const addressRouter = express.Router(); | ||
addressRouter.use(accessValidation); | ||
addressRouter.post(`${basePath}/contacts/:contactId/addresses`, AddressController.create); | ||
|
||
return addressRouter; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import prisma from "../application/database"; | ||
import { ResponseError } from "../error/response"; | ||
import { AddressRequest, toAddressResponse } from "../model/address"; | ||
import { AddressValidation } from "../validation/address"; | ||
import { Validation } from "../validation/validation"; | ||
|
||
export default class AddressService { | ||
|
||
// static async | ||
|
||
static async create(username: string, req: AddressRequest) { | ||
const validateReq = Validation.validate(AddressValidation.SAVE, req); | ||
|
||
const isContactExists = await prisma.contact.count({ | ||
where: { | ||
id: validateReq.contact_id, | ||
username: username | ||
} | ||
}) === 1; | ||
if (!isContactExists) { | ||
throw new ResponseError(404, "contact doesn't exists"); | ||
} | ||
|
||
const address = await prisma.address.create({ | ||
data: validateReq | ||
}); | ||
|
||
return toAddressResponse(address); | ||
} | ||
} |
Oops, something went wrong.