Files
TX/artifacts/api-server/tests/executive-meetings-visibility.test.mjs
Riyadh 914b7e41f3 Improve test reliability by adding cookie assertions and refining user cleanup
Add assertion for `connect.sid` cookie in login helper and refine user deletion in `executive-meetings-visibility.test.mjs` to only remove users from the current test run.
2026-04-29 07:15:02 +00:00

125 lines
4.2 KiB
JavaScript

import { test, before, after } from "node:test";
import assert from "node:assert/strict";
import pg from "pg";
const API_BASE = process.env.TEST_API_BASE ?? "http://localhost:8080";
const DATABASE_URL = process.env.DATABASE_URL;
if (!DATABASE_URL) {
throw new Error("DATABASE_URL must be set to run these tests");
}
const TEST_PASSWORD = "TestPass123!";
const TEST_PASSWORD_HASH =
"$2b$10$Bs636ukPMyz01nKrsi.5m.JlDXSN22AVCvn8cgPWWDbo5yJRQX2vu";
const pool = new pg.Pool({ connectionString: DATABASE_URL });
// Per-run uniqueness: every row this test creates is tagged with this stamp
// so the after-hook can clean up (and a defensive sweep can mop up any
// leftovers from a prior aborted run).
const STAMP = `${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
const USERNAME_PREFIX = `emvis_${STAMP}_`;
let receiverUserId;
let receiverUsername;
let receiverCookie;
async function login(username, password) {
const res = await fetch(`${API_BASE}/api/auth/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
});
assert.equal(res.status, 200, `login expected 200, got ${res.status}`);
const setCookie = res.headers.get("set-cookie");
assert.ok(setCookie, "login response missing set-cookie header");
const cookie = setCookie
.split(",")
.map((c) => c.split(";")[0].trim())
.find((c) => c.startsWith("connect.sid="));
assert.ok(cookie, "no connect.sid cookie returned by login");
return cookie;
}
async function listApps(cookie) {
const res = await fetch(`${API_BASE}/api/apps`, {
headers: { cookie },
});
assert.equal(res.status, 200, `apps expected 200, got ${res.status}`);
return res.json();
}
before(async () => {
// Defensive sweep: only remove leftovers from this exact run's stamp,
// which is fresh per process. Avoids touching unrelated fixtures that
// happen to share the `emvis_` family in a shared test DB.
await pool.query(
`DELETE FROM users WHERE username LIKE $1`,
[`${USERNAME_PREFIX}%`],
);
receiverUsername = `${USERNAME_PREFIX}receiver`;
const u = await pool.query(
`INSERT INTO users (username, email, password_hash, display_name_en,
preferred_language, is_active)
VALUES ($1, $2, $3, 'EM Visibility Test', 'en', true)
RETURNING id`,
[receiverUsername, `${receiverUsername}@ex.com`, TEST_PASSWORD_HASH],
);
receiverUserId = u.rows[0].id;
// Give them only the 'order_receiver' role — explicitly NOT any
// executive_* role. They should also not be in any admin group.
await pool.query(
`INSERT INTO user_roles (user_id, role_id)
SELECT $1, id FROM roles WHERE name = 'order_receiver'`,
[receiverUserId],
);
receiverCookie = await login(receiverUsername, TEST_PASSWORD);
});
after(async () => {
if (receiverUserId) {
await pool.query(
`DELETE FROM user_roles WHERE user_id = $1`,
[receiverUserId],
);
await pool.query(
`DELETE FROM user_groups WHERE user_id = $1`,
[receiverUserId],
);
await pool.query(`DELETE FROM users WHERE id = $1`, [receiverUserId]);
}
await pool.end();
});
test("user with only order_receiver role does NOT see the executive-meetings app", async () => {
const apps = await listApps(receiverCookie);
const slugs = apps.map((a) => a.slug);
assert.ok(
!slugs.includes("executive-meetings"),
`expected executive-meetings NOT in apps for non-executive user; got slugs: ${slugs.join(", ")}`,
);
});
test("after granting executive_coordinator, the same user DOES see executive-meetings", async () => {
await pool.query(
`INSERT INTO user_roles (user_id, role_id)
SELECT $1, id FROM roles WHERE name = 'executive_coordinator'
ON CONFLICT DO NOTHING`,
[receiverUserId],
);
// Re-login so the new role is reflected in the session's permission cache
// (some setups cache derived permissions on the session object).
receiverCookie = await login(receiverUsername, TEST_PASSWORD);
const apps = await listApps(receiverCookie);
const slugs = apps.map((a) => a.slug);
assert.ok(
slugs.includes("executive-meetings"),
`expected executive-meetings in apps after granting executive_coordinator; got slugs: ${slugs.join(", ")}`,
);
});