rename(phase 1): CapaKraken → Nexus across code, UI, docs, CI (#61)
CI / Architecture Guardrails (push) Successful in 2m38s
CI / Assistant Split Regression (push) Successful in 3m33s
CI / Typecheck (push) Successful in 3m51s
CI / Lint (push) Successful in 5m2s
CI / E2E Tests (push) Has been cancelled
CI / Fresh-Linux Docker Deploy (push) Has been cancelled
CI / Release Images (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Architecture Guardrails (push) Successful in 2m38s
CI / Assistant Split Regression (push) Successful in 3m33s
CI / Typecheck (push) Successful in 3m51s
CI / Lint (push) Successful in 5m2s
CI / E2E Tests (push) Has been cancelled
CI / Fresh-Linux Docker Deploy (push) Has been cancelled
CI / Release Images (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
rename(phase 1): CapaKraken → Nexus across code, UI, docs, CI (#61) Co-authored-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com> Co-committed-by: Hartmut Nörenberg <hn@hartmut-noerenberg.com>
This commit was merged in pull request #61.
This commit is contained in:
@@ -21,9 +21,16 @@ import { STORAGE_STATE } from "../../playwright.dev.config.js";
|
||||
|
||||
// ─── tRPC helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
type TrpcResult = { result?: { data?: unknown }; error?: { data?: { code?: string }; message?: string } };
|
||||
type TrpcResult = {
|
||||
result?: { data?: unknown };
|
||||
error?: { data?: { code?: string }; message?: string };
|
||||
};
|
||||
|
||||
async function trpcMutation(page: Page, procedure: string, input: unknown = null): Promise<TrpcResult> {
|
||||
async function trpcMutation(
|
||||
page: Page,
|
||||
procedure: string,
|
||||
input: unknown = null,
|
||||
): Promise<TrpcResult> {
|
||||
return page.evaluate(
|
||||
async ({ procedure, input }) => {
|
||||
const res = await fetch(`/api/trpc/${procedure}?batch=1`, {
|
||||
@@ -39,7 +46,11 @@ async function trpcMutation(page: Page, procedure: string, input: unknown = null
|
||||
);
|
||||
}
|
||||
|
||||
async function trpcQuery(page: Page, procedure: string, input: unknown = null): Promise<TrpcResult> {
|
||||
async function trpcQuery(
|
||||
page: Page,
|
||||
procedure: string,
|
||||
input: unknown = null,
|
||||
): Promise<TrpcResult> {
|
||||
return page.evaluate(
|
||||
async ({ procedure, input }) => {
|
||||
const encodedInput = encodeURIComponent(JSON.stringify({ "0": { json: input } }));
|
||||
@@ -60,7 +71,7 @@ async function enableMfaForSession(page: Page): Promise<TOTP> {
|
||||
if (!data?.secret) throw new Error(`generateTotpSecret failed: ${JSON.stringify(genRes)}`);
|
||||
|
||||
const totp = new TOTP({
|
||||
issuer: "CapaKraken",
|
||||
issuer: "Nexus",
|
||||
algorithm: "SHA1",
|
||||
digits: 6,
|
||||
period: 30,
|
||||
@@ -92,7 +103,9 @@ test.describe("MFA — setup flow (account/security page)", () => {
|
||||
test.afterEach(async ({ page }) => {
|
||||
// Clean up: disable MFA if a test enabled it
|
||||
if (totp) {
|
||||
await disableMfaForSession(page).catch(() => {/* already disabled or admin override */});
|
||||
await disableMfaForSession(page).catch(() => {
|
||||
/* already disabled or admin override */
|
||||
});
|
||||
totp = null;
|
||||
}
|
||||
});
|
||||
@@ -106,7 +119,7 @@ test.describe("MFA — setup flow (account/security page)", () => {
|
||||
|
||||
expect(data?.secret).toBeTruthy();
|
||||
expect(data?.uri).toMatch(/^otpauth:\/\/totp\//);
|
||||
expect(data?.uri).toContain("CapaKraken");
|
||||
expect(data?.uri).toContain("Nexus");
|
||||
});
|
||||
|
||||
test("verifyAndEnableTotp accepts a valid code and enables MFA", async ({ page }) => {
|
||||
@@ -137,9 +150,9 @@ test.describe("MFA — setup flow (account/security page)", () => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Click the enable/setup button if MFA is not yet enabled
|
||||
const setupBtn = page.getByRole("button", { name: /set up/i }).or(
|
||||
page.getByRole("button", { name: /enable.*mfa/i }),
|
||||
);
|
||||
const setupBtn = page
|
||||
.getByRole("button", { name: /set up/i })
|
||||
.or(page.getByRole("button", { name: /enable.*mfa/i }));
|
||||
|
||||
if (await setupBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
|
||||
await setupBtn.click();
|
||||
@@ -233,9 +246,10 @@ test.describe("MFA — login flow", () => {
|
||||
|
||||
// Should show error and remain on TOTP step
|
||||
await expect(
|
||||
page.getByText(/invalid.*code|incorrect.*token|try again/i).or(
|
||||
page.locator("[data-error]"),
|
||||
).first(),
|
||||
page
|
||||
.getByText(/invalid.*code|incorrect.*token|try again/i)
|
||||
.or(page.locator("[data-error]"))
|
||||
.first(),
|
||||
).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Should NOT have navigated away
|
||||
@@ -248,7 +262,9 @@ test.describe("MFA — login flow", () => {
|
||||
test.describe("MFA — users without MFA enabled", () => {
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test("login for MFA-less user goes straight to dashboard without TOTP prompt", async ({ page }) => {
|
||||
test("login for MFA-less user goes straight to dashboard without TOTP prompt", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/auth/signin");
|
||||
await page.fill('input[type="email"]', "manager@planarchy.dev");
|
||||
await page.fill('input[type="password"]', "manager123");
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Auth: e2e/dev-system/.auth/admin.json (created by global-setup.ts)
|
||||
*
|
||||
* Run:
|
||||
* pnpm --filter @capakraken/web exec playwright test \
|
||||
* pnpm --filter @nexus/web exec playwright test \
|
||||
* --config playwright.dev.config.ts \
|
||||
* e2e/dev-system/nav-smoke.spec.ts
|
||||
*/
|
||||
|
||||
@@ -27,10 +27,10 @@ test.describe("RBAC — admin routes (admin session)", () => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page.locator("table")).toBeVisible({ timeout: 10000 });
|
||||
// Seed users have planarchy.dev or capakraken.dev email domains
|
||||
await expect(
|
||||
page.locator("text=/planarchy\\.dev|capakraken\\.dev/").first(),
|
||||
).toBeVisible({ timeout: 10000 });
|
||||
// Seed users have planarchy.dev or nexus.dev email domains
|
||||
await expect(page.locator("text=/planarchy\\.dev|capakraken\\.dev/").first()).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
});
|
||||
|
||||
test("admin can access /admin/system-roles without errors", async ({ page }) => {
|
||||
@@ -99,9 +99,10 @@ test.describe("RBAC — allocations permitted for admin", () => {
|
||||
await page.goto("/allocations");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(
|
||||
page.locator("text=/do not have permission to view allocations/i"),
|
||||
).toHaveCount(0, { timeout: 8000 });
|
||||
await expect(page.locator("text=/do not have permission to view allocations/i")).toHaveCount(
|
||||
0,
|
||||
{ timeout: 8000 },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -112,9 +113,10 @@ test.describe("RBAC — allocations permitted for manager", () => {
|
||||
await page.goto("/allocations");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(
|
||||
page.locator("text=/do not have permission to view allocations/i"),
|
||||
).toHaveCount(0, { timeout: 8000 });
|
||||
await expect(page.locator("text=/do not have permission to view allocations/i")).toHaveCount(
|
||||
0,
|
||||
{ timeout: 8000 },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user