import { afterAll, beforeAll, describe, expect, it, onTestFailed } from "vitest"; import { PrismaClient } from "@prisma/client"; import { isDateString } from "./lib"; const prisma = new PrismaClient({ datasourceUrl: process.env.TEST_DATABASE_URL || process.env.DATABASE_URL, }); const baseUrl = process.env.TEST_BASE_URL || "http://localhost"; const record: Record = { code: "CMT", taxNo: "1052299402851", name: "Chamomind", nameEN: "Chamomind", email: "contact@chamomind.com", lineId: "@chamomind", telephoneNo: "0988929248", contactName: "John", webUrl: "https://chamomind.com", latitude: "", longitude: "", virtual: false, permitNo: "1135182804792", permitIssueDate: "2025-01-01T00:00:00.000Z", permitExpireDate: "2030-01-01T00:00:00.000Z", address: "11/3", addressEN: "11/3", soi: "1", soiEN: "1", moo: "2", mooEN: "2", street: "Straight", streetEN: "Straight", provinceId: "50", districtId: "5001", subDistrictId: "500107", }; const recordList: Record[] = []; let token: string; beforeAll(async () => { const body = new URLSearchParams(); body.append("grant_type", "password"); body.append("client_id", "app"); body.append("username", process.env.TEST_USERNAME || ""); body.append("password", process.env.TEST_PASSWORD || ""); body.append("scope", "openid"); const res = await fetch( process.env.KC_URL + "/realms/" + process.env.KC_REALM + "/protocol/openid-connect/token", { method: "POST", body: body, }, ); expect(res.ok).toBe(true); await res.json().then((data) => { token = data["access_token"]; }); }); afterAll(async () => { if (!record["id"]) return; await prisma.branch.deleteMany({ where: { id: { in: [record, ...recordList].map((v) => v["id"]) } }, }); await prisma.runningNo.deleteMany({ where: { key: { in: [record, ...recordList].map((v) => `MAIN_BRANCH_${v["code"].slice(0, -5)}`) }, }, }); }); describe("branch management", () => { it("create branch without required fields", async () => { const requiredFields = [ "taxNo", "name", "nameEN", "permitNo", "telephoneNo", "address", "addressEN", "email", ]; onTestFailed(() => console.log("Field:", requiredFields, "is required.")); for await (const field of requiredFields) { const res = await fetch(baseUrl + "/api/v1/branch", { method: "POST", headers: { ["Content-Type"]: "application/json", ["Authorization"]: "Bearer " + token, }, body: JSON.stringify({ ...record, [field]: undefined }), }); if (res.ok) recordList.push(await res.json()); expect(res.ok).toBe(false); expect(res.status).toBe(400); } }); it("create branch", async () => { const res = await fetch(baseUrl + "/api/v1/branch", { method: "POST", headers: { ["Content-Type"]: "application/json", ["Authorization"]: "Bearer " + token, }, body: JSON.stringify(record), }); if (!res.ok) { const text = await res.text(); try { console.log(JSON.parse(text)); } catch (e) { console.log(text); } } expect(res.ok).toBe(true); const data = await res.json(); record["id"] = data["id"]; // This field is auto generated record["code"] = data["code"]; // This field is auto generated recordList.push(data); expect(data).toMatchObject(record); }); it("get branch list", async () => { const res = await fetch(baseUrl + "/api/v1/branch", { method: "GET", headers: { ["Authorization"]: "Bearer " + token, }, }); if (!res.ok) { const text = await res.text(); try { console.log(JSON.parse(text)); } catch (e) { console.log(text); } } expect(res.ok).toBe(true); const data = await res.json(); expect(data).toHaveProperty("result"); expect(data).toHaveProperty("total"); expect(data).toHaveProperty("page"); expect(data).toHaveProperty("pageSize"); expect(data.result).toEqual( expect.arrayContaining([ expect.objectContaining({ id: expect.any(String), code: expect.any(String), virtual: expect.any(Boolean), name: expect.any(String), nameEN: expect.any(String), email: expect.any(String), taxNo: expect.any(String), telephoneNo: expect.any(String), latitude: expect.any(String), longitude: expect.any(String), contactName: expect.toBeOneOf([expect.any(String), null]), lineId: expect.toBeOneOf([expect.any(String), null]), webUrl: expect.toBeOneOf([expect.any(String), null]), remark: expect.toBeOneOf([expect.any(String), null]), selectedImage: expect.toBeOneOf([expect.any(String), null]), isHeadOffice: expect.any(Boolean), permitNo: expect.any(String), permitIssueDate: expect.toSatisfy(isDateString(true)), permitExpireDate: expect.toSatisfy(isDateString(true)), address: expect.any(String), addressEN: expect.any(String), moo: expect.toBeOneOf([expect.any(String), null]), mooEN: expect.toBeOneOf([expect.any(String), null]), street: expect.toBeOneOf([expect.any(String), null]), streetEN: expect.toBeOneOf([expect.any(String), null]), provinceId: expect.any(String), province: expect.objectContaining({ id: expect.any(String), name: expect.any(String), nameEN: expect.any(String), }), districtId: expect.any(String), district: expect.objectContaining({ id: expect.any(String), name: expect.any(String), nameEN: expect.any(String), }), subDistrictId: expect.any(String), subDistrict: expect.objectContaining({ id: expect.any(String), name: expect.any(String), nameEN: expect.any(String), zipCode: expect.any(String), }), status: expect.toBeOneOf(["CREATED", "ACTIVE", "INACTIVE"]), statusOrder: expect.toBeOneOf([1, 0]), createdAt: expect.toSatisfy(isDateString()), createdByUserId: expect.toBeOneOf([expect.any(String), null]), createdBy: expect.objectContaining({ id: expect.any(String), username: expect.any(String), firstName: expect.any(String), lastName: expect.any(String), firstNameEN: expect.any(String), lastNameEN: expect.any(String), }), updatedAt: expect.toSatisfy(isDateString()), updatedByUserId: expect.toBeOneOf([expect.any(String), null]), updatedBy: expect.objectContaining({ id: expect.any(String), username: expect.any(String), firstName: expect.any(String), lastName: expect.any(String), firstNameEN: expect.any(String), lastNameEN: expect.any(String), }), _count: expect.objectContaining({ branch: expect.any(Number), }), }), ]), ); }); it("get branch by id", async () => { const res = await fetch(baseUrl + "/api/v1/branch/" + record["id"], { method: "GET", headers: { ["Authorization"]: "Bearer " + token, }, }); if (!res.ok) { const text = await res.text(); try { console.log(JSON.parse(text)); } catch (e) { console.log(text); } } expect(res.ok).toBe(true); const data = await res.json(); expect(data).toMatchObject(record); }); it("update branch by id", async () => { const res = await fetch(baseUrl + "/api/v1/branch/" + record["id"], { method: "PUT", headers: { ["Content-Type"]: "application/json", ["Authorization"]: "Bearer " + token, }, body: JSON.stringify({ name: "Chamomind Intl.", nameEN: "Chamomind Intl." }), }); record["name"] = "Chamomind Intl."; record["nameEN"] = "Chamomind Intl."; expect(res.ok).toBe(true); const data = await res.json(); expect(data).toMatchObject(record); }); it("delete branch by id", async () => { const res = await fetch(baseUrl + "/api/v1/branch/" + record["id"], { method: "DELETE", headers: { ["Content-Type"]: "application/json", ["Authorization"]: "Bearer " + token, }, }); if (!res.ok) { const text = await res.text(); try { console.log(JSON.parse(text)); } catch (e) { console.log(text); } } expect(res.ok).toBe(true); const data = await res.json(); expect(data).toMatchObject(record); }); it("get deleted branch by id", async () => { const res = await fetch(baseUrl + "/api/v1/branch/" + record["id"], { method: "GET", headers: { ["Authorization"]: "Bearer " + token, }, }); expect(res.ok).toBe(false); }); });