Academy v4: 3 research-backed lessons (30 slides + audio); new bean logo; custom plan/lot names
Test and deploy / test-and-deploy (push) Successful in 59s
Test and deploy / test-and-deploy (push) Successful in 59s
Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ec078116b4
commit
8b80c3fa6f
@@ -0,0 +1,130 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import request from "supertest";
|
||||
import { setup, signup, password } from "./helpers.js";
|
||||
|
||||
async function bootstrapAdmin(agent) {
|
||||
const response = await agent.post("/api/auth/bootstrap").send({
|
||||
email: "[email protected]",
|
||||
password,
|
||||
setupToken: "a-secure-bootstrap-token",
|
||||
});
|
||||
assert.equal(response.status, 201);
|
||||
return response.body.csrfToken;
|
||||
}
|
||||
|
||||
test("plans: custom name is created, listed, and defaults to blank", async () => {
|
||||
const { agent } = await setup();
|
||||
const { csrf } = await signup(agent, "[email protected]");
|
||||
|
||||
const unnamed = await agent
|
||||
.post("/api/plans")
|
||||
.set("x-csrf-token", csrf)
|
||||
.send({ plan: { fields: { 0.1: "House blend" } } });
|
||||
assert.equal(unnamed.status, 201);
|
||||
assert.equal(unnamed.body.plan.name, "");
|
||||
|
||||
const named = await agent
|
||||
.post("/api/plans")
|
||||
.set("x-csrf-token", csrf)
|
||||
.send({ plan: { fields: { 0.1: "House blend" } }, name: " Winter batch " });
|
||||
assert.equal(named.status, 201);
|
||||
assert.equal(named.body.plan.name, "Winter batch", "name is trimmed");
|
||||
|
||||
const list = (await agent.get("/api/plans")).body.plans;
|
||||
assert.equal(list.find((p) => p.id === named.body.plan.id).name, "Winter batch");
|
||||
assert.equal(list.find((p) => p.id === unnamed.body.plan.id).name, "");
|
||||
});
|
||||
|
||||
test("plans: PUT name-only preserves the plan JSONB, and PUT plan-only preserves the name", async () => {
|
||||
const { agent } = await setup();
|
||||
const { csrf } = await signup(agent, "[email protected]");
|
||||
|
||||
const created = await agent
|
||||
.post("/api/plans")
|
||||
.set("x-csrf-token", csrf)
|
||||
.send({ plan: { fields: { 0.1: "Original title", "0.4": "300" } }, name: "First name" });
|
||||
const planId = created.body.plan.id;
|
||||
|
||||
// Name-only update: the plan JSONB is untouched.
|
||||
const renamed = await agent
|
||||
.put(`/api/plans/${planId}`)
|
||||
.set("x-csrf-token", csrf)
|
||||
.send({ name: "Second name" });
|
||||
assert.equal(renamed.status, 200);
|
||||
assert.equal(renamed.body.plan.name, "Second name");
|
||||
assert.equal(renamed.body.plan.plan.fields["0.1"], "Original title");
|
||||
assert.equal(renamed.body.plan.plan.fields["0.4"], "300");
|
||||
|
||||
// Plan-only update: the name is untouched.
|
||||
const replanned = await agent
|
||||
.put(`/api/plans/${planId}`)
|
||||
.set("x-csrf-token", csrf)
|
||||
.send({ plan: { fields: { 0.1: "New title", "0.4": "350" } } });
|
||||
assert.equal(replanned.status, 200);
|
||||
assert.equal(replanned.body.plan.name, "Second name");
|
||||
assert.equal(replanned.body.plan.plan.fields["0.1"], "New title");
|
||||
|
||||
// Both at once.
|
||||
const both = await agent
|
||||
.put(`/api/plans/${planId}`)
|
||||
.set("x-csrf-token", csrf)
|
||||
.send({ plan: { fields: { 0.1: "Third title" } }, name: "Third name" });
|
||||
assert.equal(both.body.plan.name, "Third name");
|
||||
assert.equal(both.body.plan.plan.fields["0.1"], "Third title");
|
||||
|
||||
// Neither field present: bad request, same as the pre-existing plan-required behavior.
|
||||
assert.equal(
|
||||
(await agent.put(`/api/plans/${planId}`).set("x-csrf-token", csrf).send({})).status,
|
||||
400,
|
||||
);
|
||||
});
|
||||
|
||||
test("plans: ownership — a stranger cannot rename another user's plan", async () => {
|
||||
const { app } = await setup();
|
||||
const owner = request.agent(app);
|
||||
const stranger = request.agent(app);
|
||||
const { csrf: ownerCsrf } = await signup(owner, "[email protected]");
|
||||
const { csrf: strangerCsrf } = await signup(stranger, "[email protected]");
|
||||
|
||||
const created = await owner
|
||||
.post("/api/plans")
|
||||
.set("x-csrf-token", ownerCsrf)
|
||||
.send({ plan: { fields: { 0.1: "Owner's plan" } } });
|
||||
const planId = created.body.plan.id;
|
||||
|
||||
const hijack = await stranger
|
||||
.put(`/api/plans/${planId}`)
|
||||
.set("x-csrf-token", strangerCsrf)
|
||||
.send({ name: "Hijacked" });
|
||||
assert.equal(hijack.status, 404);
|
||||
|
||||
// The plan is unaffected.
|
||||
const stillOwners = (await owner.get("/api/plans")).body.plans;
|
||||
assert.equal(stillOwners.find((p) => p.id === planId).name, "");
|
||||
});
|
||||
|
||||
test("plans: admin plan list title falls back to worksheet field 0.1 when no custom name is set", async () => {
|
||||
const { app } = await setup();
|
||||
const admin = request.agent(app);
|
||||
await bootstrapAdmin(admin);
|
||||
|
||||
const user = request.agent(app);
|
||||
const { csrf: userCsrf } = await signup(user, "[email protected]");
|
||||
|
||||
const named = await user
|
||||
.post("/api/plans")
|
||||
.set("x-csrf-token", userCsrf)
|
||||
.send({ plan: { fields: { 0.1: "Worksheet title" } }, name: "Custom title" });
|
||||
const unnamed = await user
|
||||
.post("/api/plans")
|
||||
.set("x-csrf-token", userCsrf)
|
||||
.send({ plan: { fields: { 0.1: "Worksheet title only" } } });
|
||||
|
||||
const list = (await admin.get("/api/admin/plans")).body.plans;
|
||||
assert.equal(list.find((p) => p.id === named.body.plan.id).title, "Custom title");
|
||||
assert.equal(
|
||||
list.find((p) => p.id === unnamed.body.plan.id).title,
|
||||
"Worksheet title only",
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user