What have I got wrong?
You are not controlling the maximum length:
Let's eliminate the inspections (lookaheads), and let's see:
[a-zA-ZáéíóúÁÉÍÓÚñÑ\$\/\.\d]{7,15}(?=.*\d$)
The .*
means that there can be any number of characters from the last repeated in the character class to the \d$
of the end.
On the other hand, much simpler:
[a-zA-ZáéíóúÁÉÍÓÚñÑ$/.\d]{7,15}\d$
- No need to escape
$
, *
, /
, .
, etc. within a class (they have no special meaning there).
At least one upper case: you are not including accented capitalization in% (?=.*[A-ZÑ])
, but I guess it is intentional.
Contain a character with an accent. In (?=.*[áéíóúÁÉIÓÚ])
you missed the accent in Í
(and I guess üÜ
do not go).
4 digits maximum and at least 2 ... This is an important error for you to understand. You are using:
(?=.*\d){2,4}
But keep in mind that in an inspection ( lookaround ), after trying the match, the cursor returns to the position it was before trying (in this case at the beginning of the string) . When an inspection is repeated, in fact, you are asking (2 to 4 times) if there is 1 digit from the beginning of the string ...
If it was not understood:
- There is 1 digit from the beginning of the string ... Yes
- There is 1 digit from the beginning of the string ... Yes
- There is 1 digit from the beginning of the string ... Yes
- There is 1 digit from the beginning of the string ... Yes -Déjà vu: -)
At no time are you seeing if there are 2 to 4 digits in the whole string.
To see that there are only between 2 and 4, we have to repeat it in the inspection:
^(?=(?:\D*\d){2,4}$)
The condition " alphabetic characters (at least 2) " is not being checked anywhere. It would be:
^(?=(?:[^A-Za-záéíóúüÁÉÍÓÚÜñÑ]*[A-Za-záéíóúüÁÉÍÓÚÜñÑ]){2})
You used (?=.*[a-zñ])
but did not mention that you had to have a lowercase in your rules.
In short:
/^(?=(?:[^A-Za-záéíóúüÁÉÍÓÚÜñÑ]*[A-Za-záéíóúüÁÉÍÓÚÜñÑ]){2})(?=.*[A-ZÑ])(?=.*[áéíóúÁÉÍÓÚ])(?=(?:\D*\d){2,4}$)(?=.*[$/.])[a-zA-ZáéíóúÁÉÍÓÚñÑ$/.\d]{7,15}\d$/
Simplify
But let's go deeper. On the one hand you said:
One capital + one accented letter.
And also:
2 alphabetic characters
There is no way to meet the first and not the second. If it has a capital letter and 1 accented letter, it obviously has 2 alphabetic characters ... we can eliminate a condition:
/^(?=.*[A-ZÑ])(?=.*[áéíóúÁÉÍÓÚ])(?=(?:\D*\d){2,4}$)(?=.*[$/.])[a-zA-ZáéíóúÁÉÍÓÚñÑ$/.\d]{7,15}\d$/
And we know that it has to end with 1 digit, we are already controlling it in
^(?=(?:\D*\d){2,4}$)
We can eliminate the condition of \d$
at the end
/^(?=.*[A-ZÑ])(?=.*[áéíóúÁÉÍÓÚ])(?=(?:\D*\d){2,4}$)(?=.*[$/.])[a-zA-ZáéíóúÁÉÍÓÚñÑ$/.\d]{8,16}$/
Demo:
input { width: 30ch; padding: 0.5em 1ch; border: 5px solid red; }
input:valid { border: 5px solid green; }
<input pattern="(?=.*[A-ZÑ])(?=.*[áéíóúÁÉÍÓÚ])(?=(?:\D*\d){2,4}$)(?=.*[$/.])[a-zA-ZáéíóúÁÉÍÓÚñÑ$/.\d]{8,16}"
placeholder="Validación de contraseña"
required>