- getPreferences: SYSTEM par défaut si aucune ligne (même logique que dietId/allergies : absent = valeur par défaut, pas une omission) - updatePreferences: upsert (crée la ligne au premier PATCH) - Tests Mocha + Cucumber : 401, valeur invalide, défaut, création à la volée, cloisonnement entre profils
98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
import { ErrorCode, type SignupInput } from "@batch-cooking/shared";
|
|
import { faker } from "@faker-js/faker";
|
|
import { expect } from "chai";
|
|
import request from "supertest";
|
|
import { createApp } from "../src/app.js";
|
|
import { prisma } from "../src/db/prisma.js";
|
|
import { resetDatabase } from "../test-support/reset-db.js";
|
|
|
|
function buildSignupPayload(): SignupInput {
|
|
const firstName = faker.person.firstName();
|
|
const lastName = faker.person.lastName();
|
|
return {
|
|
firstName,
|
|
lastName,
|
|
email: faker.internet.email({ firstName, lastName }).toLowerCase(),
|
|
password: faker.internet.password({ length: 16 }),
|
|
};
|
|
}
|
|
|
|
describe("Preferences", () => {
|
|
const app = createApp();
|
|
|
|
beforeEach(async () => {
|
|
await resetDatabase();
|
|
});
|
|
|
|
after(async () => {
|
|
await prisma.$disconnect();
|
|
});
|
|
|
|
describe("GET /preferences", () => {
|
|
it("rejects requests without a session cookie with 401 NOT_AUTHENTICATED", async () => {
|
|
const res = await request(app).get("/preferences");
|
|
|
|
expect(res.status).to.equal(401);
|
|
expect(res.body.code).to.equal(ErrorCode.NOT_AUTHENTICATED);
|
|
});
|
|
|
|
it("defaults to SYSTEM when the profile has no preferences row yet", async () => {
|
|
const agent = request.agent(app);
|
|
await agent.post("/auth/signup").send(buildSignupPayload());
|
|
|
|
const res = await agent.get("/preferences");
|
|
|
|
expect(res.status).to.equal(200);
|
|
expect(res.body).to.deep.equal({ theme: "SYSTEM" });
|
|
});
|
|
});
|
|
|
|
describe("PATCH /preferences", () => {
|
|
it("rejects requests without a session cookie with 401 NOT_AUTHENTICATED", async () => {
|
|
const res = await request(app).patch("/preferences").send({ theme: "DARK" });
|
|
|
|
expect(res.status).to.equal(401);
|
|
expect(res.body.code).to.equal(ErrorCode.NOT_AUTHENTICATED);
|
|
});
|
|
|
|
it("rejects an unknown theme with 400 VALIDATION_ERROR", async () => {
|
|
const agent = request.agent(app);
|
|
await agent.post("/auth/signup").send(buildSignupPayload());
|
|
|
|
const res = await agent.patch("/preferences").send({ theme: "PURPLE" });
|
|
|
|
expect(res.status).to.equal(400);
|
|
expect(res.body.code).to.equal(ErrorCode.VALIDATION_ERROR);
|
|
});
|
|
|
|
it("creates the preferences row on first write, and reuses it on later reads/writes", async () => {
|
|
const agent = request.agent(app);
|
|
await agent.post("/auth/signup").send(buildSignupPayload());
|
|
|
|
const patchRes = await agent.patch("/preferences").send({ theme: "DARK" });
|
|
expect(patchRes.status).to.equal(200);
|
|
expect(patchRes.body).to.deep.equal({ theme: "DARK" });
|
|
|
|
const getRes = await agent.get("/preferences");
|
|
expect(getRes.body).to.deep.equal({ theme: "DARK" });
|
|
|
|
const secondPatchRes = await agent.patch("/preferences").send({ theme: "LIGHT" });
|
|
expect(secondPatchRes.body).to.deep.equal({ theme: "LIGHT" });
|
|
|
|
const secondGetRes = await agent.get("/preferences");
|
|
expect(secondGetRes.body).to.deep.equal({ theme: "LIGHT" });
|
|
});
|
|
|
|
it("scopes preferences to the caller's own profile", async () => {
|
|
const aliceAgent = request.agent(app);
|
|
await aliceAgent.post("/auth/signup").send(buildSignupPayload());
|
|
await aliceAgent.patch("/preferences").send({ theme: "DARK" });
|
|
|
|
const bobAgent = request.agent(app);
|
|
await bobAgent.post("/auth/signup").send(buildSignupPayload());
|
|
|
|
const res = await bobAgent.get("/preferences");
|
|
expect(res.body).to.deep.equal({ theme: "SYSTEM" });
|
|
});
|
|
});
|
|
});
|