Skip to content

Commit

Permalink
Merge pull request #976 from Klantinteractie-Servicesysteem/pc-554-di…
Browse files Browse the repository at this point in the history
…gitale-adressen-opslaan-conform-validatieregels-ok2

Pc 554 digitale adressen opslaan conform validatieregels ok2
  • Loading branch information
mstokericatt authored Dec 12, 2024
2 parents c78c151 + 4f59656 commit b2bc81e
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@
type="tel"
name="Telefoonnummer 1"
class="utrecht-textbox utrecht-textbox--html-input"
@input="setActive"
@input="handleTelefoonInput"
/>
</label>
<label class="utrecht-form-label">
Expand All @@ -260,7 +260,7 @@
type="tel"
name="Telefoonnummer 2"
class="utrecht-textbox utrecht-textbox--html-input"
@input="setActive"
@input="handleTelefoonInput"
/>
</label>
<label class="utrecht-form-label">
Expand All @@ -276,10 +276,9 @@
<span>E-mailadres</span>
<input
v-model="form.emailadres"
type="email"
name="E-mailadres"
class="utrecht-textbox utrecht-textbox--html-input"
@input="setActive"
@input="handleEmailInput"
/>
</label>
</div>
Expand All @@ -301,7 +300,7 @@ import type {
} from "@/stores/contactmoment";
import { ActorType } from "@/stores/contactmoment";
import { ref, watch } from "vue";
import { computed, ref, watch } from "vue";
import {
FormFieldsetLegend,
FormFieldset,
Expand All @@ -319,6 +318,7 @@ import AfdelingenSearch from "../../components/AfdelingenSearch.vue";
import GroepenSearch from "./components/GroepenSearch.vue";
import { fetchAfdelingen } from "@/features/contact/components/afdelingen";
import { fetchGroepen } from "./components/groepen";
import { TELEFOON_PATTERN, EMAIL_PATTERN } from "@/helpers/validation";
const props = defineProps<{
modelValue: ContactmomentContactVerzoek;
Expand Down Expand Up @@ -472,21 +472,47 @@ watch(
//////////////////////////////////////////////////////
const hasContact = computed(
() =>
!!form.value.telefoonnummer1 ||
!!form.value.telefoonnummer2 ||
!!form.value.emailadres,
);
const noContactMessage =
"Vul minimaal een telefoonnummer of een e-mailadres in";
watch(
[
telEl,
() =>
!!form.value.telefoonnummer1 ||
!!form.value.telefoonnummer2 ||
!!form.value.emailadres,
],
([el, hasContact]) => {
if (!el) return;
[telEl, hasContact],
([el, bool]) => el && el.setCustomValidity(!bool ? noContactMessage : ""),
);
const handleTelefoonInput = (event: Event) => {
const el = event.target as HTMLInputElement;
setActive();
if (!el.value || TELEFOON_PATTERN.test(el.value)) {
// telEl: back to custom noContactMessage if applicable, otherwise clear
el.setCustomValidity(
hasContact ? "" : "Vul minimaal een telefoonnummer of een e-mailadres in",
el === telEl.value && !hasContact.value ? noContactMessage : "",
);
},
);
} else {
el.setCustomValidity("Vul een geldig telefoonnummer in.");
}
};
const handleEmailInput = (event: Event) => {
const el = event.target as HTMLInputElement;
setActive();
el.setCustomValidity(
!el.value || EMAIL_PATTERN.test(el.value)
? ""
: "Vul een geldig emailadres in.",
);
};
//als de afdeling wijzigt, dan moet de medewerker gereset worden
watch(
Expand Down
16 changes: 16 additions & 0 deletions src/helpers/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,19 @@ export const vValidate: Directive<HTMLInputElement, ValidatorSetup> = {
(el as any).removeValidatorSetup?.();
},
};

// https://github.com/maykinmedia/open-klant/blob/f231f368c48276ffe429fb7e3105b0ce9f0eb444/src/openklant/utils/validators.py#L26
export const TELEFOON_PATTERN =
/^(0[8-9]00[0-9]{4,7}|0[1-9][0-9]{8}|\+[0-9]{9,20}|1400|140[0-9]{2,3})$/;

// https://github.com/django/django/blob/4.2/django/core/validators.py#L174
export const EMAIL_PATTERN = new RegExp(
"^" +
// user_regex (without quoted string)
"([-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*)" +
"@" +
// domain_regex (without literal_regex)
"((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+(?:[A-Z0-9-]{2,63}(?<!-)))" +
"$",
"i",
);
85 changes: 81 additions & 4 deletions src/test/helpers/validation.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { describe, expect, test } from "vitest";

import { parseDutchDate, parseBsn } from "@/helpers/validation";
import {
parseDutchDate,
parseBsn,
TELEFOON_PATTERN,
EMAIL_PATTERN,
} from "@/helpers/validation";

describe("parseDutchDate", () => {
test("should allow dd/MM/yyyy", async () => {
Expand Down Expand Up @@ -52,7 +56,7 @@ describe("parseDutchDate", () => {
expect(parsed).toBeInstanceOf(Error);
const error = parsed as Error;
expect(error.message).toBe(
"Voer een valide datum in, bijvoorbeeld 17-09-2022 of 17092022."
"Voer een valide datum in, bijvoorbeeld 17-09-2022 of 17092022.",
);
});

Expand All @@ -61,7 +65,7 @@ describe("parseDutchDate", () => {
expect(parsed).toBeInstanceOf(Error);
const error = parsed as Error;
expect(error.message).toBe(
"Voer een valide datum in, bijvoorbeeld 17-09-2022 of 17092022."
"Voer een valide datum in, bijvoorbeeld 17-09-2022 of 17092022.",
);
});
});
Expand All @@ -84,3 +88,76 @@ describe("parseBsn", () => {
expect(parsedError.message).toBe("Voer een BSN in van negen cijfers.");
});
});

describe("TELEFOON_PATTERN", () => {
test("validates phone numbers correctly", () => {
const testCases = [
{ number: "+31612345678", isValid: true },
{ number: "+441134960000", isValid: true },
{ number: "+12065550100", isValid: true },
{ number: "0612345678", isValid: true },
{ number: "09001234567", isValid: true },
{ number: "1400", isValid: true },
{ number: "14012", isValid: true },
{ number: "14079", isValid: true },
{ number: "0695azerty", isValid: false },
{ number: "azerty0545", isValid: false },
{ number: "@4566544++8", isValid: false },
{ number: "onetwothreefour", isValid: false },
{ number: "020 753 0523", isValid: false },
{ number: "+311234", isValid: false },
{ number: "0800852", isValid: false },
{ number: "080085285212", isValid: false },
];

testCases.forEach(({ number, isValid }) =>
expect(TELEFOON_PATTERN.test(number)).toBe(isValid),
);
});
});

describe("EMAIL_PATTERN", () => {
test("validates email addresses correctly", () => {
const testCases = [
{ email: "[email protected]", isValid: true },
{ email: "[email protected]", isValid: true },
{ email: "[email protected]", isValid: true },
{ email: "[email protected]", isValid: true },
{ email: `example@atm.${"a".repeat(63)}`, isValid: true },
{ email: `example@${"a".repeat(63)}.atm`, isValid: true },
{
email: `example@${"a".repeat(63)}.${"b".repeat(10)}.atm`,
isValid: true,
},
{ email: `example@atm.${"a".repeat(64)}`, isValid: false },
{
email: `example@${"b".repeat(64)}.atm.${"a".repeat(63)}.atm`,
isValid: false,
},
{ email: "", isValid: false },
{ email: "abc", isValid: false },
{ email: "abc@", isValid: false },
{ email: "abc@bar", isValid: false },
{ email: "a @x.cz", isValid: false },
{ email: "[email protected]", isValid: false },
{ email: `"test@test"@example.com`, isValid: false },
{ email: "something@@somewhere.com", isValid: false },
{ email: "[email protected]", isValid: false },
{ email: "[email protected]", isValid: false },
{ email: "[email protected]", isValid: false },
{ email: "[email protected]", isValid: false },
{ email: "[email protected]", isValid: false },
{ email: "[email protected]", isValid: false },
{ email: `[email protected]\n\n<script src="x.js">`, isValid: false },
{ email: "[email protected].", isValid: false },
{ email: `example@${"a".repeat(63)}.us`, isValid: true },
{ email: `example@${"a".repeat(64)}.us`, isValid: false },
{ email: "[email protected]\n", isValid: false },
{ email: "a\[email protected]", isValid: false },
];

testCases.forEach(({ email, isValid }) =>
expect(EMAIL_PATTERN.test(email)).toBe(isValid),
);
});
});

0 comments on commit b2bc81e

Please sign in to comment.