Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
63 changes: 42 additions & 21 deletions src/validateRegisterForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,60 @@

/**
* @param {string} email
*
* @param {string} password
*
* @returns {object}
*/
function validateRegisterForm(email, password) {
// eslint-disable-next-line max-len
const validPassword = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?!.*\s).{8,16}$/;
// Password regex: krótkie zmienne
const n = '(?=.*\\d)';
const l = '(?=.*[a-z])';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lowercase check (?=.*[a-z]) and uppercase check (?=.*[A-Z]) only match Latin letters. The task requires that allowed letters include both English and Cyrillic (А–Я, а–я). Update these parts to include the Cyrillic ranges (for example a-zA-Z\u0400-\u04FF or use Unicode property escapes) so uppercase detection and lowercase detection work for Cyrillic characters as well.

const u = '(?=.*[A-Z])';
const s = '(?=.*[^a-zA-Z0-9])';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The special-character assertion (?=.*[^a-zA-Z0-9]) treats any character outside the ASCII letters/digits range as a special character. That will incorrectly classify Cyrillic letters as "special characters". After you add Cyrillic ranges to the letter classes, update this special-character check so it excludes Cyrillic letters (e.g. use a negative class that excludes the combined letter ranges and digits). Consider using Unicode property escapes (e.g. \p{L}) with the u flag to make this clearer and correct.

const ns = '(?!.*\\s)';
const len = '.{8,16}';

// eslint-disable-next-line max-len
const validEmailMask = new RegExp(/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\./i);
const validPassword = new RegExp('^' + n + l + u + s + ns + len + '$');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validPassword is built from multiple parts and uses .{8,16} for length and (?!.*\s) to forbid spaces — those parts are fine for enforcing the 8–16 length and no-space requirement. However to fully meet the spec you must ensure the letter checks include Cyrillic (see earlier comments) and that the special-character check doesn't capture Cyrillic as special. Also consider using the u flag and explicit Unicode ranges to make the regex robust.


if (!email.match(validEmailMask) && password.match(validPassword)) {
return {
code: 422, message: 'Email is invalid.',
};
// Email regex: krótkie zmienne
const loc = '([\\w-]+(?:\\.[\\w-]+)*)';
const dom = '([\\w-]+(?:\\.[\\w-]+)+)';
const at = '@';
const validEmailMask = new RegExp('^' + loc + at + dom + '$', 'i');

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local-part (loc) and domain (dom) regex parts only allow \w/-/dot groups. That excludes the list of allowed special characters specified in the task (for example: ! # $ % & ' * + - / = ? ^ _ { | } ~). The local-part must accept those characters in addition to letters and digits (while still enforcing the dot rules). Please expand the local-part regex to include the allowed characters and ensure the domain rules still satisfy the TLD constraints. Also note \w` includes underscore — which is allowed — but you still need to explicitly permit the full allowed set from the spec.


const isEmailValid = validEmailMask.test(email);
const isPasswordValid = validPassword.test(password);
Comment on lines +28 to +29

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code currently runs the email and password tests by using the parameter names email and password here. The task requires the function signature to be validateRegisterForm(password, email) (password first, email second). Because the implementation expects the reversed order, callers/tests that follow the spec will pass arguments in the opposite order and validation will be performed on the wrong values. Please update the function signature and parameter usage to match the required order, or (preferably) change the function declaration to accept (password, email) so it matches the specification exactly.


// Dodatkowe reguły dla emaila
let emailExtraValid = true;
if (isEmailValid) {
const parts = email.split('@');
const local = parts[0];
const domain = parts[1];

const localInvalid = local.startsWith('.');
const domainInvalid = domain.startsWith('.');
const dotsInvalid = email.includes('..');
Comment on lines +38 to +40

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additional checks for leading dots and double dots (local.startsWith('.'), domain.startsWith('.'), email.includes('..')) are a useful supplement to the regex and correctly address several dot-related rules. Good to keep these, but do not rely on them instead of updating the main regex: both should work together so the allowed-special-chars requirement and dot rules are all satisfied.


if (localInvalid || domainInvalid || dotsInvalid) {
emailExtraValid = false;
}
}

if (email.match(validEmailMask) && !password.match(validPassword)) {
return {
code: 422, message: 'Password is invalid.',
};
// Walidacja wyników
if (!isEmailValid || !emailExtraValid) {
if (isPasswordValid) {
return { code: 422, message: 'Email is invalid.' };
} else {
return { code: 500, message: 'Password and email are invalid.' };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation flow (the result-code branching) correctly distinguishes the four required outcomes: both valid -> 200, email invalid & password valid -> 422 (Email), password invalid & email valid -> 422 (Password), both invalid -> 500. After fixing the parameter order and the regexes above this branching logic will produce the expected outputs and messages. No change required here besides ensuring the earlier issues are fixed so the flags evaluated here are accurate.

}
}

if (!email.match(validEmailMask) && !password.match(validPassword)) {
return {
code: 500, message: 'Password and email are invalid.',
};
if (!isPasswordValid) {
return { code: 422, message: 'Password is invalid.' };
}

return {
code: 200, message: 'Email and password are valid.',
};
return { code: 200, message: 'Email and password are valid.' };
}

module.exports = validateRegisterForm;

69 changes: 58 additions & 11 deletions src/validateRegisterForm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,70 @@ describe(`Function 'validateRegisterForm':`, () => {
});

it(`should return object`, () => {
expect(typeof validateRegisterForm('test@mail.com', 'P@ssword1!'))
.toBe('object');
const result = validateRegisterForm('test@mail.com', 'P@ssword1!');
expect(typeof result).toBe('object');
});

it(`should return success message for the valid input`, () => {
const isValid = validateRegisterForm('test@mail.com', 'P@ssword1!');
it(`should return 200 for valid email and password`, () => {
const valid = validateRegisterForm('test@mail.com', 'P@ssword1!');
expect(valid.code).toBe(200);
expect(valid.message).toBe('Email and password are valid.');
});

it(`should return 422 for valid email and password missing digit`, () => {
const invalidPass = validateRegisterForm('test@mail.com', 'P@ssword');
expect(invalidPass.code).toBe(422);
expect(invalidPass.message).toBe('Password is invalid.');
});

expect(isValid.code).toBe(200);
expect(isValid.message).toBe('Email and password are valid.');
it(`should return 422 for invalid email and valid password`, () => {
const invalidEmail = validateRegisterForm('test@com', 'P@ssword1!');
expect(invalidEmail.code).toBe(422);
expect(invalidEmail.message).toBe('Email is invalid.');
});

it(`should return error for valid email and password without number`, () => {
const invalidPassword = validateRegisterForm('test@mail.com', 'P@ssword');
it(`should return 500 for invalid email and password`, () => {
const bothInvalid = validateRegisterForm('test@com', 'ssword1');
expect(bothInvalid.code).toBe(500);
expect(bothInvalid.message)
.toBe('Password and email are invalid.');
});

expect(invalidPassword.code).toBe(422);
expect(invalidPassword.message).toBe('Password is invalid.');
it(`should return 422 if password too short`, () => {
const tooShort = validateRegisterForm('valid@mail.com', 'Aa1!');
expect(tooShort.code).toBe(422);
expect(tooShort.message).toBe('Password is invalid.');
});

// write more tests here
it(`should return 422 if password too long`, () => {
const tooLong = validateRegisterForm(
'valid@mail.com', 'A1!aaaaaaaaaaaaaaa'
);
expect(tooLong.code).toBe(422);
expect(tooLong.message).toBe('Password is invalid.');
});

it(`should return 422 if email missing '@' symbol`, () => {
const noAt = validateRegisterForm('invalidmail.com', 'P@ssword1!');
expect(noAt.code).toBe(422);
expect(noAt.message).toBe('Email is invalid.');
});

it(`should return 422 if email starts with dot`, () => {
const startDot = validateRegisterForm('.test@mail.com', 'P@ssword1!');
expect(startDot.code).toBe(422);
expect(startDot.message).toBe('Email is invalid.');
});

it(`should return 422 if email has double dots`, () => {
const doubleDot = validateRegisterForm('test..mail@mail.com', 'P@ssword1!');
expect(doubleDot.code).toBe(422);
expect(doubleDot.message).toBe('Email is invalid.');
});

it(`should return 422 if top-level domain starts with dot`, () => {
const tldDot = validateRegisterForm('test@mail..com', 'P@ssword1!');
expect(tldDot.code).toBe(422);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: All test invocations pass arguments in (email, password) order, but the specification requires the signature validateRegisterForm(password, email). Passing arguments reversed will feed the email into the password checks and vice versa, causing incorrect test behavior.

Why it matters: The test harness must call the function using the correct parameter order described in the task so it validates the implementation properly.

What to change: Update each call so the first argument is the password string and the second is the email string. Example change:

// current
validateRegisterForm('test@mail.com', 'P@ssword1!')
// should be
validateRegisterForm('P@ssword1!', 'test@mail.com')

Locations to update: every validateRegisterForm(...) call between lines 11 and 74 (all test invocations).

expect(tldDot.message).toBe('Email is invalid.');
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All test invocations in this block pass arguments in the wrong order. The required function signature is validateRegisterForm(password, email) per the task spec, but the tests call validateRegisterForm(email, password). Update every call in this range so the first argument is the password string and the second is the email string. Example:

  • Wrong: validateRegisterForm('test@mail.com', 'P@ssword1!')
  • Correct: validateRegisterForm('P@ssword1!', 'test@mail.com')

Fix the calls used for: returning an object, 200 valid case, invalid password, invalid email, both invalid, password too short, password too long, missing '@', starting dot, double dots, and TLD dot checks. After changing the tests, ensure the implementation signature matches the required (password, email) order (the implementation file currently defines function validateRegisterForm(email, password) and needs to be aligned) — see the task description and implementation for context.

});