157 lines
3.8 KiB
TypeScript
157 lines
3.8 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const { createAuditEntry } = vi.hoisted(() => ({
|
|
createAuditEntry: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("../lib/audit.js", () => ({
|
|
createAuditEntry,
|
|
}));
|
|
|
|
import {
|
|
createCountry,
|
|
deleteMetroCity,
|
|
updateCountry,
|
|
} from "../router/country-procedure-support.js";
|
|
|
|
function createContext(db: Record<string, unknown>) {
|
|
return {
|
|
db: db as never,
|
|
dbUser: { id: "user_admin" } as never,
|
|
};
|
|
}
|
|
|
|
describe("country procedure support", () => {
|
|
beforeEach(() => {
|
|
createAuditEntry.mockReset();
|
|
});
|
|
|
|
it("creates a country after checking code uniqueness", async () => {
|
|
const findUnique = vi.fn().mockResolvedValue(null);
|
|
const create = vi.fn().mockResolvedValue({
|
|
id: "country_de",
|
|
code: "DE",
|
|
name: "Germany",
|
|
metroCities: [],
|
|
});
|
|
|
|
const result = await createCountry(
|
|
createContext({
|
|
country: { findUnique, create },
|
|
}),
|
|
{
|
|
code: "DE",
|
|
name: "Germany",
|
|
dailyWorkingHours: 8,
|
|
},
|
|
);
|
|
|
|
expect(findUnique).toHaveBeenCalledWith({
|
|
where: { code: "DE" },
|
|
});
|
|
expect(create).toHaveBeenCalledWith({
|
|
data: {
|
|
code: "DE",
|
|
name: "Germany",
|
|
dailyWorkingHours: 8,
|
|
},
|
|
include: { metroCities: true },
|
|
});
|
|
expect(result.id).toBe("country_de");
|
|
expect(createAuditEntry).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
entityType: "Country",
|
|
action: "CREATE",
|
|
entityId: "country_de",
|
|
userId: "user_admin",
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("rechecks code uniqueness only when the code changes", async () => {
|
|
const findUnique = vi
|
|
.fn()
|
|
.mockResolvedValueOnce({
|
|
id: "country_de",
|
|
code: "DE",
|
|
name: "Germany",
|
|
})
|
|
.mockResolvedValueOnce(null);
|
|
const update = vi.fn().mockResolvedValue({
|
|
id: "country_de",
|
|
code: "DEU",
|
|
name: "Germany",
|
|
metroCities: [],
|
|
});
|
|
|
|
const result = await updateCountry(
|
|
createContext({
|
|
country: { findUnique, update },
|
|
}),
|
|
{
|
|
id: "country_de",
|
|
data: {
|
|
code: "DEU",
|
|
},
|
|
},
|
|
);
|
|
|
|
expect(findUnique).toHaveBeenNthCalledWith(1, {
|
|
where: { id: "country_de" },
|
|
});
|
|
expect(findUnique).toHaveBeenNthCalledWith(2, {
|
|
where: { code: "DEU" },
|
|
});
|
|
expect(update).toHaveBeenCalledWith({
|
|
where: { id: "country_de" },
|
|
data: { code: "DEU" },
|
|
include: { metroCities: true },
|
|
});
|
|
expect(result.code).toBe("DEU");
|
|
expect(createAuditEntry).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
entityType: "Country",
|
|
action: "UPDATE",
|
|
before: expect.objectContaining({ code: "DE" }),
|
|
after: expect.objectContaining({ code: "DEU" }),
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("deletes a metro city only after the resource-count guard passes", async () => {
|
|
const findUnique = vi.fn().mockResolvedValue({
|
|
id: "city_berlin",
|
|
name: "Berlin",
|
|
_count: { resources: 0 },
|
|
});
|
|
const remove = vi.fn().mockResolvedValue({ id: "city_berlin" });
|
|
|
|
const result = await deleteMetroCity(
|
|
createContext({
|
|
metroCity: { findUnique, delete: remove },
|
|
}),
|
|
{ id: "city_berlin" },
|
|
);
|
|
|
|
expect(findUnique).toHaveBeenCalledWith({
|
|
where: { id: "city_berlin" },
|
|
include: { _count: { select: { resources: true } } },
|
|
});
|
|
expect(remove).toHaveBeenCalledWith({
|
|
where: { id: "city_berlin" },
|
|
});
|
|
expect(result).toEqual({
|
|
success: true,
|
|
id: "city_berlin",
|
|
name: "Berlin",
|
|
});
|
|
expect(createAuditEntry).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
entityType: "MetroCity",
|
|
action: "DELETE",
|
|
entityId: "city_berlin",
|
|
}),
|
|
);
|
|
});
|
|
});
|