fix(client): add validation to profile image URL (#41927)

* fix: fix broken image url after validation

* feat: add tests for a broken image url submission

* fix: reduce event related calls

* Update cypress/integration/settings/image-picture-check.js

Co-authored-by: Sem Bauke <46919888+Sembauke@users.noreply.github.com>

* Update cypress/integration/settings/image-picture-check.js

Co-authored-by: Ahmad Abdolsaheb <ahmad.abdolsaheb@gmail.com>
Co-authored-by: Sem Bauke <46919888+Sembauke@users.noreply.github.com>
This commit is contained in:
Ismail Tlemcani
2021-05-23 15:08:12 +01:00
committed by GitHub
parent 3b2be48dea
commit 914ff44f74
2 changed files with 86 additions and 9 deletions

View File

@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
import {
FormGroup,
ControlLabel,
FormControl
FormControl,
HelpBlock,
Alert
} from '@freecodecamp/react-bootstrap';
import { FullWidthRow, Spacer } from '../helpers';
@ -28,7 +30,7 @@ const propTypes = {
class AboutSettings extends Component {
constructor(props) {
super(props);
this.validationImage = new Image();
const { name = '', location = '', picture = '', about = '' } = props;
const values = {
name,
@ -39,7 +41,8 @@ class AboutSettings extends Component {
this.state = {
formValues: { ...values },
originalValues: { ...values },
formClicked: false
formClicked: false,
isPictureUrlValid: true
};
}
@ -69,18 +72,25 @@ class AboutSettings extends Component {
isFormPristine = () => {
const { formValues, originalValues } = this.state;
return Object.keys(originalValues)
.map(key => originalValues[key] === formValues[key])
.every(bool => bool);
return (
this.state.isPictureUrlValid === false ||
Object.keys(originalValues)
.map(key => originalValues[key] === formValues[key])
.every(bool => bool)
);
};
handleSubmit = e => {
e.preventDefault();
const { formValues } = this.state;
const { submitNewAbout } = this.props;
return this.setState({ formClicked: true }, () =>
submitNewAbout(formValues)
);
if (this.state.isPictureUrlValid === true) {
return this.setState({ formClicked: true }, () =>
submitNewAbout(formValues)
);
} else {
return false;
}
};
handleNameChange = e => {
@ -103,8 +113,22 @@ class AboutSettings extends Component {
}));
};
componentDidMount() {
this.validationImage.addEventListener('error', this.errorEvent);
this.validationImage.addEventListener('load', this.loadEvent);
}
componentWillUnmount() {
this.validationImage.removeEventListener('load', this.loadEvent);
this.validationImage.removeEventListener('error', this.errorEvent);
}
loadEvent = () => this.setState({ isPictureUrlValid: true });
errorEvent = () => this.setState({ isPictureUrlValid: false });
handlePictureChange = e => {
const value = e.target.value.slice(0);
this.validationImage.src = value;
return this.setState(state => ({
formValues: {
...state.formValues,
@ -113,6 +137,19 @@ class AboutSettings extends Component {
}));
};
showImageValidationWarning = () => {
const { t } = this.props;
if (this.state.isPictureUrlValid === false) {
return (
<HelpBlock>
<Alert bsStyle='info'>{t('validation.url-not-image')}</Alert>
</HelpBlock>
);
} else {
return true;
}
};
handleAboutChange = e => {
const value = e.target.value.slice(0);
return this.setState(state => ({
@ -164,6 +201,7 @@ class AboutSettings extends Component {
type='url'
value={picture}
/>
{this.showImageValidationWarning()}
</FormGroup>
<FormGroup controlId='about-about'>
<ControlLabel>

View File

@ -0,0 +1,39 @@
/* global cy */
describe('Picture input field', () => {
beforeEach(() => {
cy.login();
cy.visit('/settings');
// Setting aliases here
cy.get('input#about-picture').as('pictureInput');
});
it('Should be possible to type', () => {
cy.get('@pictureInput')
.clear({ force: true })
.type('twaha', { force: true })
.should('have.attr', 'value', 'twaha');
});
it('Show an error message if an incorrect url was submitted', () => {
cy.get('@pictureInput')
.clear({ force: true })
.type('https://s3.amazonaws.com/freecodecamp/camper-image', {
force: true
})
.then(() => {
cy.contains('URL must link directly to an image file');
});
});
it('Can submit a correct URL', () => {
cy.get('@pictureInput')
.clear({ force: true })
.type(
'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png',
{
force: true
}
);
cy.wait(500);
cy.get('#camper-identity > .btn').should('not.be.disabled');
});
});