From d21e1911b541a29a1716ffa95cf8f40f8cfaa6d5 Mon Sep 17 00:00:00 2001 From: manvendra-s-rathore Date: Wed, 24 Apr 2024 16:23:44 +0530 Subject: [PATCH] restrict save on invalid url n update test cases --- CHANGELOG.md | 1 + .../ExternalLinkModal/ExternalLinkModal.js | 31 +++++++------------ .../ExternalLinkModal.test.js | 4 ++- src/components/util/util.js | 11 +++++++ 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6237223da..60c22dc0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Fix incorrect translation key having count-disagreements in Pay fees/fines modal in Fees/Fines Page. Refs UIU-1097. * Trim input values and delete properties with empty string when user record save. Refs UIU-2049. * Update username field validation to trim leading and trailing spaces. Refs UIU-3099. +* Handle invalid image URLs when uploading profile photo via External URL. Refs UIU-3080. ## [10.1.0](https://github.com/folio-org/ui-users/tree/v10.1.0) (2024-03-20) [Full Changelog](https://github.com/folio-org/ui-users/compare/v10.0.4...v10.1.0) diff --git a/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.js b/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.js index fa3c8bce4..07a2e3549 100644 --- a/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.js +++ b/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.js @@ -12,7 +12,7 @@ import { TextField, } from '@folio/stripes/components'; import { FormattedMessage } from 'react-intl'; -import { isAValidURL } from '../../../../util'; +import { isAValidURL, isAValidImageUrl } from '../../../../util'; const ExternalLinkModal = ({ open, @@ -33,13 +33,14 @@ const ExternalLinkModal = ({ if (inputValue) { setDisabled(previousInputValue.current === inputValue); setExternalURLValidityError(null); - } else { - setDisabled(true); } }, [inputValue]); - const handleSave = () => { - onSave(inputValue); + const handleSave = async () => { + const isValidImgURL = await isAValidImageUrl(inputValue); + if (isValidImgURL) { + onSave(inputValue); + } }; const handleInputChange = (e) => { @@ -47,20 +48,6 @@ const ExternalLinkModal = ({ setInputValue(e.target.value); }; - async function isValidImageUrl(url) { - try { - const response = await fetch(url); - if (response.ok) { - const contentType = response.headers.get('content-type'); - return contentType && contentType.startsWith('image/'); - } else { - return false; - } - } catch (e) { - return false; - } - } - const handleBlur = async () => { if (!inputValue || !isAValidURL(inputValue)) { setExternalURLValidityError(); @@ -68,11 +55,15 @@ const ExternalLinkModal = ({ return; } - const isValidImgURL = await isValidImageUrl(inputValue); + const isValidImgURL = await isAValidImageUrl(inputValue); if (!isValidImgURL) { setExternalURLValidityError(); setDisabled(true); + return; } + + setExternalURLValidityError(null); + setDisabled(false); }; const renderModalFooter = () => { diff --git a/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.test.js b/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.test.js index 69d6dedeb..06e3cf5b6 100644 --- a/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.test.js +++ b/src/components/EditSections/EditUserInfo/components/ExternalLinkModal/ExternalLinkModal.test.js @@ -6,7 +6,7 @@ import { } from '@folio/jest-config-stripes/testing-library/react'; import userEvent from '@folio/jest-config-stripes/testing-library/user-event'; -import { isAValidURL } from '../../../../util'; +import { isAValidURL, isAValidImageUrl } from '../../../../util'; import '../../../../../../test/jest/__mock__'; @@ -43,6 +43,7 @@ describe('ExternalLinkModal', () => { beforeEach(() => { isAValidURL.mockReset(); + isAValidImageUrl.mockReset(); renderExternalLinkModal(props); }); @@ -53,6 +54,7 @@ describe('ExternalLinkModal', () => { expect(screen.getByText('ui-users.information.profilePicture.externalLink.modal.externalURL')).toBeInTheDocument(); }); it('should call onSave', async () => { + isAValidImageUrl.mockImplementationOnce(() => true); const saveButton = screen.getByRole('button', { name: 'ui-users.save' }); const inputElement = screen.getByLabelText('ui-users.information.profilePicture.externalLink.modal.externalURL'); diff --git a/src/components/util/util.js b/src/components/util/util.js index 5659c28a9..35ba9a7b5 100644 --- a/src/components/util/util.js +++ b/src/components/util/util.js @@ -222,3 +222,14 @@ export const isAValidURL = (str) => { return URL.canParse(str); }; +export const isAValidImageUrl = async (url) => { + try { + const response = await fetch(url); + if (!response.ok) return false; + + const contentType = response.headers.get('content-type'); + return contentType && contentType.startsWith('image/'); + } catch (e) { + return false; + } +};