All files / src/app/teacher-page/components/settings teacherProfileUpdate.js

100% Statements 10/10
80% Branches 16/20
100% Functions 2/2
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75                                  2x 2x   2x   2x                                                       8x 5x                           8x 1x   7x            
/**
 * EI-2574 — pure helpers extracted from `ChangeName.jsx`.
 *
 * Two layers:
 *   1. Yup schema (`teacherNameValidationSchema`) — locks the form's
 *      validation contract: firstName + lastName required (1-25 chars,
 *      letter-class regex); middleName optional (≤25 chars, same regex).
 *   2. Payload mapper (`buildTeacherFullnamePayload`) — camelCase form
 *      values → snake_case wire shape consumed by the
 *      `PATCH /v1/teacher/account/{teacherUUID}/update` endpoint.
 *
 * Extracted so the AIO scenarios are unit-testable without rendering
 * MUI / Formik / Redux.
 */
 
import * as yup from "yup";
 
const NAME_REGEX = /^[a-zA-ZÀ-ÖØ-öø-ÿ '-]+$/;
const OPTIONAL_NAME_REGEX = /^[a-zA-ZÀ-ÖØ-öø-ÿ '-]*$/;
 
export const TEACHER_NAME_MAX_LENGTH = 25;
 
export const teacherNameValidationSchema = yup.object({
    firstName: yup
        .string()
        .trim()
        .min(1, "First name must be at least 1 character long")
        .max(TEACHER_NAME_MAX_LENGTH, `First name must be no more than ${TEACHER_NAME_MAX_LENGTH} characters long`)
        .matches(NAME_REGEX, "First name contains invalid characters")
        .required("First name is required"),
    middleName: yup
        .string()
        .trim()
        .max(TEACHER_NAME_MAX_LENGTH, `Middle name must be no more than ${TEACHER_NAME_MAX_LENGTH} characters long`)
        .matches(OPTIONAL_NAME_REGEX, "Middle name contains invalid characters"),
    lastName: yup
        .string()
        .trim()
        .min(1, "Last name must be at least 1 character long")
        .max(TEACHER_NAME_MAX_LENGTH, `Last name must be no more than ${TEACHER_NAME_MAX_LENGTH} characters long`)
        .matches(NAME_REGEX, "Last name contains invalid characters")
        .required("Last name is required"),
});
 
/**
 * Form values (camelCase) → API payload (snake_case).  Mirrors lines
 * 89–93 of `ChangeName.jsx::clickSave`.  Defensive: undefined
 * middleName collapses to "" so the wire shape is stable.
 */
export function buildTeacherFullnamePayload(values) {
    if (!values || typeof values !== "object") return null;
    return {
        first_name: values.firstName ?? "",
        middle_name: values.middleName ?? "",
        last_name: values.lastName ?? "",
    };
}
 
/**
 * Round-trip the API teacher record → form initial values (lines
 * 105–109 of `ChangeName.jsx`).  Pure so the prefill behavior is
 * testable.  Missing/undefined middle_name collapses to "" so the
 * MUI TextField is always controlled.
 */
export function buildTeacherNameInitialValues(teacherData) {
    if (!teacherData || typeof teacherData !== "object") {
        return { firstName: "", middleName: "", lastName: "" };
    }
    return {
        firstName: teacherData.first_name ?? "",
        middleName: teacherData.middle_name ?? "",
        lastName: teacherData.last_name ?? "",
    };
}