mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-15 09:46:16 +01:00
separate validation logic to simplify testing and use same logic as backend
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {translate} from "react-i18next";
|
import { translate } from "react-i18next";
|
||||||
import type {User} from "../types/User";
|
import type { User } from "../types/User";
|
||||||
import {Checkbox, InputField} from "../../components/forms";
|
import { Checkbox, InputField } from "../../components/forms";
|
||||||
import {SubmitButton} from "../../components/buttons";
|
import { SubmitButton } from "../../components/buttons";
|
||||||
|
import * as validator from "./userValidation";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
submitForm: User => void,
|
submitForm: User => void,
|
||||||
@@ -21,11 +22,10 @@ type State = {
|
|||||||
validatePassword: string
|
validatePassword: string
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class UserForm extends React.Component<Props, State> {
|
class UserForm extends React.Component<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
user: {
|
user: {
|
||||||
name: "",
|
name: "",
|
||||||
@@ -46,7 +46,7 @@ class UserForm extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.setState({ user: {...this.props.user} });
|
this.setState({ user: { ...this.props.user } });
|
||||||
}
|
}
|
||||||
|
|
||||||
submit = (event: Event) => {
|
submit = (event: Event) => {
|
||||||
@@ -57,8 +57,14 @@ class UserForm extends React.Component<Props, State> {
|
|||||||
render() {
|
render() {
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
const user = this.state.user;
|
const user = this.state.user;
|
||||||
const ButtonClickable = (this.state.validatePasswordError || this.state.nameValidationError || this.state.mailValidationError || this.state.validatePasswordError
|
const ButtonClickable =
|
||||||
|| this.state.displayNameValidationError || user.name === undefined|| user.displayName === undefined);
|
this.state.validatePasswordError ||
|
||||||
|
this.state.nameValidationError ||
|
||||||
|
this.state.mailValidationError ||
|
||||||
|
this.state.validatePasswordError ||
|
||||||
|
this.state.displayNameValidationError ||
|
||||||
|
user.name === undefined ||
|
||||||
|
user.displayName === undefined;
|
||||||
let nameField = null;
|
let nameField = null;
|
||||||
if (!this.props.user) {
|
if (!this.props.user) {
|
||||||
nameField = (
|
nameField = (
|
||||||
@@ -66,8 +72,8 @@ class UserForm extends React.Component<Props, State> {
|
|||||||
label={t("user.name")}
|
label={t("user.name")}
|
||||||
onChange={this.handleUsernameChange}
|
onChange={this.handleUsernameChange}
|
||||||
value={user ? user.name : ""}
|
value={user ? user.name : ""}
|
||||||
validationError= {this.state.nameValidationError}
|
validationError={this.state.nameValidationError}
|
||||||
errorMessage= {t("validation.name-invalid")}
|
errorMessage={t("validation.name-invalid")}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -85,7 +91,7 @@ class UserForm extends React.Component<Props, State> {
|
|||||||
label={t("user.mail")}
|
label={t("user.mail")}
|
||||||
onChange={this.handleEmailChange}
|
onChange={this.handleEmailChange}
|
||||||
value={user ? user.mail : ""}
|
value={user ? user.mail : ""}
|
||||||
validationError= {this.state.mailValidationError}
|
validationError={this.state.mailValidationError}
|
||||||
errorMessage={t("validation.mail-invalid")}
|
errorMessage={t("validation.mail-invalid")}
|
||||||
/>
|
/>
|
||||||
<InputField
|
<InputField
|
||||||
@@ -114,47 +120,68 @@ class UserForm extends React.Component<Props, State> {
|
|||||||
onChange={this.handleActiveChange}
|
onChange={this.handleActiveChange}
|
||||||
checked={user ? user.active : false}
|
checked={user ? user.active : false}
|
||||||
/>
|
/>
|
||||||
<SubmitButton disabled={ButtonClickable} label={t("user-form.submit")} />
|
<SubmitButton
|
||||||
|
disabled={ButtonClickable}
|
||||||
|
label={t("user-form.submit")}
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
handleUsernameChange = (name: string) => {
|
handleUsernameChange = (name: string) => {
|
||||||
const REGEX_NAME = /^[^ ][A-z0-9\\.\-_@ ]*[^ ]$/;
|
this.setState({
|
||||||
this.setState( {nameValidationError: !REGEX_NAME.test(name), user : {...this.state.user, name} } );
|
nameValidationError: !validator.isNameValid(name),
|
||||||
|
user: { ...this.state.user, name }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDisplayNameChange = (displayName: string) => {
|
handleDisplayNameChange = (displayName: string) => {
|
||||||
const REGEX_NAME = /^[^ ][A-z0-9\\.\-_@ ]*[^ ]$/;
|
this.setState({
|
||||||
this.setState({displayNameValidationError: !REGEX_NAME.test(displayName), user : {...this.state.user, displayName} } );
|
displayNameValidationError: !validator.isDisplayNameValid(displayName),
|
||||||
|
user: { ...this.state.user, displayName }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEmailChange = (mail: string) => {
|
handleEmailChange = (mail: string) => {
|
||||||
const REGEX_MAIL = /^[A-z0-9][\w.-]*@[A-z0-9][\w\-\\.]*\.[A-z0-9][A-z0-9-]+$/;
|
this.setState({
|
||||||
this.setState( {mailValidationError: !REGEX_MAIL.test(mail), user : {...this.state.user, mail} } );
|
mailValidationError: !validator.isMailValid(mail),
|
||||||
|
user: { ...this.state.user, mail }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePasswordChange = (password: string) => {
|
handlePasswordChange = (password: string) => {
|
||||||
const validatePasswordError = !this.checkPasswords(password, this.state.validatePassword);
|
const validatePasswordError = !this.checkPasswords(
|
||||||
this.setState( {validatePasswordError: (password.length < 6) || (password.length > 32), passwordValidationError: validatePasswordError, user : {...this.state.user, password} } );
|
password,
|
||||||
|
this.state.validatePassword
|
||||||
|
);
|
||||||
|
this.setState({
|
||||||
|
validatePasswordError: !validator.isPasswordValid(password),
|
||||||
|
passwordValidationError: validatePasswordError,
|
||||||
|
user: { ...this.state.user, password }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePasswordValidationChange = (validatePassword: string) => {
|
handlePasswordValidationChange = (validatePassword: string) => {
|
||||||
const validatePasswordError = this.checkPasswords(this.state.user.password, validatePassword)
|
const validatePasswordError = this.checkPasswords(
|
||||||
this.setState({ validatePassword, passwordValidationError: !validatePasswordError });
|
this.state.user.password,
|
||||||
|
validatePassword
|
||||||
|
);
|
||||||
|
this.setState({
|
||||||
|
validatePassword,
|
||||||
|
passwordValidationError: !validatePasswordError
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
checkPasswords = (password1: string, password2: string) => {
|
checkPasswords = (password1: string, password2: string) => {
|
||||||
return (password1 === password2);
|
return password1 === password2;
|
||||||
}
|
};
|
||||||
|
|
||||||
handleAdminChange = (admin: boolean) => {
|
handleAdminChange = (admin: boolean) => {
|
||||||
this.setState({ user : {...this.state.user, admin} });
|
this.setState({ user: { ...this.state.user, admin } });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleActiveChange = (active: boolean) => {
|
handleActiveChange = (active: boolean) => {
|
||||||
this.setState({ user : {...this.state.user, active} });
|
this.setState({ user: { ...this.state.user, active } });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
scm-ui/src/users/components/userValidation.js
Normal file
24
scm-ui/src/users/components/userValidation.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
const nameRegex = /^([A-z0-9\.\-_@]|[^ ]([A-z0-9\.\-_@ ]*[A-z0-9\.\-_@]|[^\s])?)$/;
|
||||||
|
|
||||||
|
export const isNameValid = (name: string) => {
|
||||||
|
return nameRegex.test(name);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isDisplayNameValid = (displayName: string) => {
|
||||||
|
if (displayName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mailRegex = /^[A-z0-9][\w.-]*@[A-z0-9][\w\-\.]*\.[A-z0-9][A-z0-9-]+$/;
|
||||||
|
|
||||||
|
export const isMailValid = (mail: string) => {
|
||||||
|
return mailRegex.test(mail);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isPasswordValid = (password: string) => {
|
||||||
|
return password.length > 6 && password.length < 32;
|
||||||
|
};
|
||||||
114
scm-ui/src/users/components/userValidator.test.js
Normal file
114
scm-ui/src/users/components/userValidator.test.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// @flow
|
||||||
|
import * as validator from "./userValidation";
|
||||||
|
|
||||||
|
describe("test name validation", () => {
|
||||||
|
it("should return false", () => {
|
||||||
|
// invalid names taken from ValidationUtilTest.java
|
||||||
|
const invalidNames = [
|
||||||
|
" test 123",
|
||||||
|
" test 123 ",
|
||||||
|
"test 123 ",
|
||||||
|
"test/123",
|
||||||
|
"test%123",
|
||||||
|
"test:123",
|
||||||
|
"t ",
|
||||||
|
" t",
|
||||||
|
" t ",
|
||||||
|
""
|
||||||
|
];
|
||||||
|
for (let name of invalidNames) {
|
||||||
|
expect(validator.isNameValid(name)).toBe(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true", () => {
|
||||||
|
// valid names taken from ValidationUtilTest.java
|
||||||
|
const validNames = [
|
||||||
|
"test",
|
||||||
|
"test.git",
|
||||||
|
"Test123.git",
|
||||||
|
"Test123-git",
|
||||||
|
"Test_user-123.git",
|
||||||
|
"test@scm-manager.de",
|
||||||
|
"test 123",
|
||||||
|
"tt",
|
||||||
|
"t"
|
||||||
|
];
|
||||||
|
for (let name of validNames) {
|
||||||
|
expect(validator.isNameValid(name)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("test displayName validation", () => {
|
||||||
|
it("should return false", () => {
|
||||||
|
expect(validator.isDisplayNameValid("")).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true", () => {
|
||||||
|
// valid names taken from ValidationUtilTest.java
|
||||||
|
const validNames = [
|
||||||
|
"Arthur Dent",
|
||||||
|
"Tricia.McMillan@hitchhiker.com",
|
||||||
|
"Ford Prefect (ford.prefect@hitchhiker.com)",
|
||||||
|
"Zaphod Beeblebrox <zaphod.beeblebrox@hitchhiker.com>",
|
||||||
|
"Marvin, der depressive Roboter"
|
||||||
|
];
|
||||||
|
for (let name of validNames) {
|
||||||
|
expect(validator.isDisplayNameValid(name)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("test mail validation", () => {
|
||||||
|
it("should return false", () => {
|
||||||
|
// invalid taken from ValidationUtilTest.java
|
||||||
|
const invalid = [
|
||||||
|
"ostfalia.de",
|
||||||
|
"@ostfalia.de",
|
||||||
|
"s.sdorra@",
|
||||||
|
"s.sdorra@ostfalia",
|
||||||
|
"s.sdorra@@ostfalia.de",
|
||||||
|
"s.sdorra@ ostfalia.de",
|
||||||
|
"s.sdorra @ostfalia.de"
|
||||||
|
];
|
||||||
|
for (let mail of invalid) {
|
||||||
|
expect(validator.isMailValid(mail)).toBe(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true", () => {
|
||||||
|
// valid taken from ValidationUtilTest.java
|
||||||
|
const valid = [
|
||||||
|
"s.sdorra@ostfalia.de",
|
||||||
|
"sdorra@ostfalia.de",
|
||||||
|
"s.sdorra@hbk-bs.de",
|
||||||
|
"s.sdorra@gmail.com",
|
||||||
|
"s.sdorra@t.co",
|
||||||
|
"s.sdorra@ucla.college",
|
||||||
|
"s.sdorra@example.xn--p1ai",
|
||||||
|
"s.sdorra@scm.solutions"
|
||||||
|
];
|
||||||
|
for (let mail of valid) {
|
||||||
|
expect(validator.isMailValid(mail)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("test password validation", () => {
|
||||||
|
it("should return false", () => {
|
||||||
|
// invalid taken from ValidationUtilTest.java
|
||||||
|
const invalid = ["", "abc", "aaabbbcccdddeeefffggghhhiiijjjkkk"];
|
||||||
|
for (let password of invalid) {
|
||||||
|
expect(validator.isPasswordValid(password)).toBe(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return true", () => {
|
||||||
|
// valid taken from ValidationUtilTest.java
|
||||||
|
const valid = ["secret123", "mySuperSecretPassword"];
|
||||||
|
for (let password of valid) {
|
||||||
|
expect(validator.isPasswordValid(password)).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user