mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-26 23:51:14 +02:00
feat: map 422 field errors for playground forms
This commit is contained in:
parent
18f5d30e61
commit
d7f89bb3fd
2 changed files with 52 additions and 0 deletions
34
surfsense_web/lib/playground/field-errors.test.ts
Normal file
34
surfsense_web/lib/playground/field-errors.test.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { test } from "node:test";
|
||||||
|
import { AppError } from "@/lib/error";
|
||||||
|
import { fieldErrorsFromError } from "./field-errors";
|
||||||
|
|
||||||
|
// Run with: pnpm exec tsx --test lib/playground/field-errors.test.ts
|
||||||
|
|
||||||
|
function validationError(fields: { loc: string[]; msg: string }[]): AppError {
|
||||||
|
const error = new AppError("Validation failed", 422, "Unprocessable Entity", "VALIDATION_ERROR");
|
||||||
|
error.fields = fields;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
test("maps a body field failure to its top-level field name", () => {
|
||||||
|
const error = validationError([
|
||||||
|
{ loc: ["body", "startUrls", "0"], msg: "must be a valid http(s) URL" },
|
||||||
|
]);
|
||||||
|
assert.deepEqual(fieldErrorsFromError(error), {
|
||||||
|
startUrls: "must be a valid http(s) URL",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("keeps the first failure per field", () => {
|
||||||
|
const error = validationError([
|
||||||
|
{ loc: ["body", "urls", "0"], msg: "first" },
|
||||||
|
{ loc: ["body", "urls", "3"], msg: "second" },
|
||||||
|
]);
|
||||||
|
assert.deepEqual(fieldErrorsFromError(error), { urls: "first" });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns nothing for non-AppError or errors without fields", () => {
|
||||||
|
assert.deepEqual(fieldErrorsFromError(new Error("boom")), {});
|
||||||
|
assert.deepEqual(fieldErrorsFromError(new AppError("no fields", 500)), {});
|
||||||
|
});
|
||||||
18
surfsense_web/lib/playground/field-errors.ts
Normal file
18
surfsense_web/lib/playground/field-errors.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { AppError } from "@/lib/error";
|
||||||
|
|
||||||
|
/** Map a 422 response's field failures to ``{ fieldName: message }`` for the form. */
|
||||||
|
export function fieldErrorsFromError(error: unknown): Record<string, string> {
|
||||||
|
if (!(error instanceof AppError) || !error.fields) return {};
|
||||||
|
const errors: Record<string, string> = {};
|
||||||
|
for (const { loc, msg } of error.fields) {
|
||||||
|
const name = topLevelField(loc);
|
||||||
|
if (name && !errors[name]) errors[name] = msg;
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The input field a location path points at, dropping the ``body`` request root. */
|
||||||
|
function topLevelField(loc: string[]): string | undefined {
|
||||||
|
const path = loc[0] === "body" ? loc.slice(1) : loc;
|
||||||
|
return path[0];
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue