Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions ui-react/apps/console/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const SecureVault = lazy(() => import("./pages/secure-vault"));
const AdminDashboard = lazy(() => import("./pages/admin/Dashboard"));
const AdminLicense = lazy(() => import("./pages/admin/License"));
const AdminUnauthorized = lazy(() => import("./pages/admin/Unauthorized"));
const AdminUsers = lazy(() => import("./pages/admin/users"));
const AdminUserDetails = lazy(() => import("./pages/admin/users/UserDetails"));

export default function App() {
return (
Expand All @@ -59,7 +61,10 @@ export default function App() {
<Route element={<SignUpGuard />}>
<Route path="/sign-up" element={<SignUp />} />
<Route path="/confirm-account" element={<ConfirmAccount />} />
<Route path="/validation-account" element={<ValidationAccount />} />
<Route
path="/validation-account"
element={<ValidationAccount />}
/>
</Route>
{getConfig().cloud && (
<>
Expand All @@ -71,15 +76,26 @@ export default function App() {
<Route element={<ProtectedRoute />}>
{/* Admin panel — layout wraps all /admin routes including unauthorized */}
<Route element={<AdminLayout />}>
<Route path="/admin/unauthorized" element={<AdminUnauthorized />} />
<Route
path="/admin/unauthorized"
element={<AdminUnauthorized />}
/>
<Route element={<AdminRoute />}>
<Route path="/admin/license" element={<AdminLicense />} />
<Route element={<LicenseGuard />}>
<Route
path="/admin"
element={<Navigate to="/admin/dashboard" replace />}
/>
<Route path="/admin/dashboard" element={<AdminDashboard />} />
<Route
path="/admin/dashboard"
element={<AdminDashboard />}
/>
<Route path="/admin/users" element={<AdminUsers />} />
<Route
path="/admin/users/:id"
element={<AdminUserDetails />}
/>
</Route>
</Route>
</Route>
Expand Down
66 changes: 66 additions & 0 deletions ui-react/apps/console/src/api/__tests__/errors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { describe, it, expect } from "vitest";
import { isSdkError } from "../errors";

describe("isSdkError", () => {
describe("returns true for valid SDK errors", () => {
it("returns true when object has numeric status property", () => {
expect(isSdkError({ status: 400 })).toBe(true);
});

it("returns true for status 200", () => {
expect(isSdkError({ status: 200 })).toBe(true);
});

it("returns true for status 500", () => {
expect(isSdkError({ status: 500, headers: new Headers() })).toBe(true);
});

it("returns true when extra properties are present", () => {
expect(isSdkError({ status: 401, extra: true })).toBe(true);
});

it("returns true for enriched arrays (real SDK shape)", () => {
expect(
isSdkError(Object.assign(["username"], { status: 400, headers: new Headers() })),
).toBe(true);
});
});

describe("returns false for non-SDK errors", () => {
it("returns false for null", () => {
expect(isSdkError(null)).toBe(false);
});

it("returns false for undefined", () => {
expect(isSdkError(undefined)).toBe(false);
});

it("returns false for a plain string", () => {
expect(isSdkError("error")).toBe(false);
});

it("returns false for a number", () => {
expect(isSdkError(42)).toBe(false);
});

it("returns false for an object missing status", () => {
expect(isSdkError({ code: 404 })).toBe(false);
});

it("returns false when status is a string instead of a number", () => {
expect(isSdkError({ status: "400" })).toBe(false);
});

it("returns false for an empty object", () => {
expect(isSdkError({})).toBe(false);
});

it("returns false for a plain Error instance without status", () => {
expect(isSdkError(new Error("oops"))).toBe(false);
});

it("returns false for a plain array without status", () => {
expect(isSdkError(["username"])).toBe(false);
});
});
});
Loading
Loading