import test from "node:test"; import assert from "node:assert/strict"; import request from "supertest"; import { setup, signup } from "./helpers.js"; import { blankPlan } from "../shared/fields.js"; test("plans table page and single-plan route require authentication and enforce ownership", async () => { const { app, agent } = await setup(); assert.equal((await agent.get("/plans")).status, 302); const { csrf } = await signup(agent, "owner@example.com"); const other = request.agent(app); await signup(other, "other@example.com"); const made = await agent .post("/api/plans") .set("x-csrf-token", csrf) .send({ name: "Owned plan", plan: blankPlan() }); const id = made.body.plan.id; assert.equal((await agent.get("/plans")).status, 200); assert.equal((await agent.get("/plans.html")).status, 302); assert.equal( (await agent.get("/api/plans/" + id)).body.plan.name, "Owned plan", ); assert.equal((await other.get("/api/plans/" + id)).status, 404); assert.equal((await request(app).get("/api/plans/" + id)).status, 401); assert.equal((await agent.get("/api/plans/not-a-uuid")).status, 404); }); test("summary search, filters and pagination exclude full telemetry and other accounts", async () => { const { app, agent, db } = await setup(); await signup(agent, "table@example.com"); const other = request.agent(app); const { csrf } = await signup(other, "private@example.com"); await other .post("/api/plans") .set("x-csrf-token", csrf) .send({ name: "Hidden Ethiopia", plan: blankPlan() }); const owner = ( await db.query("SELECT id FROM users WHERE email=$1", ["table@example.com"]) ).rows[0].id; for (let i = 0; i < 62; i++) { const p = blankPlan(); Object.assign(p.fields, { 0.1: "Coffee " + i, 1.3: i % 2 ? "Ethiopia" : "Burundi", 3.1: i % 2 ? "natural" : "washed", 4.1: i % 2 ? "light" : "medium", }); p.reference = { curve: Array(30).fill({ t: 1, bt: 180 }) }; await db.query( "INSERT INTO roast_plans(user_id,plan,name) VALUES($1,$2,$3)", [owner, p, "Plan " + String(i).padStart(2, "0")], ); } const first = (await agent.get("/api/plans?view=summary")).body; assert.equal( (await agent.get("/api/plans?view=summary&sort=constructor")).status, 200, ); assert.equal( (await agent.get("/api/plans?view=summary&page=9007199254740991")).status, 400, ); assert.equal(first.total, 62); assert.equal(first.plans.length, 25); assert.ok(!("plan" in first.plans[0])); const second = (await agent.get("/api/plans?view=summary&page=2")).body; assert.equal(second.plans.length, 25); assert.equal( first.plans.some((a) => second.plans.some((b) => a.id === b.id)), false, ); const filtered = ( await agent.get( "/api/plans?view=summary&q=ethiopia&process=natural&level=light", ) ).body; assert.equal(filtered.total, 31); assert.ok(filtered.plans.every((p) => p.origin === "Ethiopia")); assert.equal( (await agent.get("/api/plans?view=summary&level=dark")).body.total, 0, ); assert.equal((await agent.get("/api/plans?view=summary&page=0")).status, 400); assert.equal( (await agent.get("/api/plans?view=summary&limit=999")).status, 400, ); assert.equal( (await agent.get("/api/plans?view=summary&q=%25")).body.total, 0, ); });