From ee52a48b63d501874db0e7747752ee970e374be7 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Wed, 26 Jul 2023 08:15:33 +0530 Subject: [PATCH 01/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- .changeset/nervous-suits-give.md | 5 +++++ plugins/shortcuts/src/AddShortcut.tsx | 19 +++++++++++++------ plugins/shortcuts/src/EditShortcut.tsx | 19 +++++++++++++------ 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 .changeset/nervous-suits-give.md diff --git a/.changeset/nervous-suits-give.md b/.changeset/nervous-suits-give.md new file mode 100644 index 0000000000..e08d8d89a2 --- /dev/null +++ b/.changeset/nervous-suits-give.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-shortcuts': patch +--- + +Limit the use of the duplicate shortcut name when adding a shortcut diff --git a/plugins/shortcuts/src/AddShortcut.tsx b/plugins/shortcuts/src/AddShortcut.tsx index 15850ab389..70988c49eb 100644 --- a/plugins/shortcuts/src/AddShortcut.tsx +++ b/plugins/shortcuts/src/AddShortcut.tsx @@ -67,12 +67,19 @@ export const AddShortcut = ({ const shortcut: Omit = { url, title }; try { - await api.add(shortcut); - alertApi.post({ - message: `Added shortcut '${title}' to your sidebar`, - severity: 'success', - display: 'transient', - }); + if (api.get().some(shortcutTitle => shortcutTitle.title === title)) { + alertApi.post({ + message: `Shortcut title already exist`, + severity: 'error', + }); + } else { + await api.add(shortcut); + alertApi.post({ + message: `Added shortcut '${title}' to your sidebar`, + severity: 'success', + display: 'transient', + }); + } } catch (error) { alertApi.post({ message: `Could not add shortcut: ${error.message}`, diff --git a/plugins/shortcuts/src/EditShortcut.tsx b/plugins/shortcuts/src/EditShortcut.tsx index 9f2ffe10be..ecc14d93d9 100644 --- a/plugins/shortcuts/src/EditShortcut.tsx +++ b/plugins/shortcuts/src/EditShortcut.tsx @@ -70,12 +70,19 @@ export const EditShortcut = ({ }; try { - await api.update(newShortcut); - alertApi.post({ - message: `Updated shortcut '${title}'`, - severity: 'success', - display: 'transient', - }); + if (api.get().some(shortcutTitle => shortcutTitle.title === title)) { + alertApi.post({ + message: `Shortcut title already exist`, + severity: 'error', + }); + } else { + await api.update(newShortcut); + alertApi.post({ + message: `Updated shortcut '${title}'`, + severity: 'success', + display: 'transient', + }); + } } catch (error) { alertApi.post({ message: `Could not update shortcut: ${error.message}`, From 5d99ca9350573b07eca710a9e6f461e258abb818 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Wed, 26 Jul 2023 09:48:50 +0530 Subject: [PATCH 02/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/EditShortcut.tsx | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/plugins/shortcuts/src/EditShortcut.tsx b/plugins/shortcuts/src/EditShortcut.tsx index ecc14d93d9..9f2ffe10be 100644 --- a/plugins/shortcuts/src/EditShortcut.tsx +++ b/plugins/shortcuts/src/EditShortcut.tsx @@ -70,19 +70,12 @@ export const EditShortcut = ({ }; try { - if (api.get().some(shortcutTitle => shortcutTitle.title === title)) { - alertApi.post({ - message: `Shortcut title already exist`, - severity: 'error', - }); - } else { - await api.update(newShortcut); - alertApi.post({ - message: `Updated shortcut '${title}'`, - severity: 'success', - display: 'transient', - }); - } + await api.update(newShortcut); + alertApi.post({ + message: `Updated shortcut '${title}'`, + severity: 'success', + display: 'transient', + }); } catch (error) { alertApi.post({ message: `Could not update shortcut: ${error.message}`, From d37b9c5aeeb9bc9925a63832a92d638aea5a04e5 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Wed, 26 Jul 2023 10:17:53 +0530 Subject: [PATCH 03/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.tsx | 7 +++++-- plugins/shortcuts/src/EditShortcut.tsx | 23 ++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.tsx b/plugins/shortcuts/src/AddShortcut.tsx index 70988c49eb..32a5aaa947 100644 --- a/plugins/shortcuts/src/AddShortcut.tsx +++ b/plugins/shortcuts/src/AddShortcut.tsx @@ -63,11 +63,14 @@ export const AddShortcut = ({ const analytics = useAnalytics(); const handleSave: SubmitHandler = async ({ url, title }) => { - analytics.captureEvent('click', `Clicked 'Save' in AddShortcut`); + if (!api.get().some(shortcutTitle => shortcutTitle.title === title)) { + analytics.captureEvent('click', `Clicked 'Save' in AddShortcut`); + } const shortcut: Omit = { url, title }; + const shortcutData = api.get(); try { - if (api.get().some(shortcutTitle => shortcutTitle.title === title)) { + if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) { alertApi.post({ message: `Shortcut title already exist`, severity: 'error', diff --git a/plugins/shortcuts/src/EditShortcut.tsx b/plugins/shortcuts/src/EditShortcut.tsx index 9f2ffe10be..df0476f5db 100644 --- a/plugins/shortcuts/src/EditShortcut.tsx +++ b/plugins/shortcuts/src/EditShortcut.tsx @@ -62,7 +62,9 @@ export const EditShortcut = ({ const analytics = useAnalytics(); const handleSave: SubmitHandler = async ({ url, title }) => { - analytics.captureEvent('click', `Clicked 'Save' in Edit Shortcut`); + if (!api.get().some(shortcutTitle => shortcutTitle.title === title)) { + analytics.captureEvent('click', `Clicked 'Save' in Edit Shortcut`); + } const newShortcut: Shortcut = { ...shortcut, url, @@ -70,12 +72,19 @@ export const EditShortcut = ({ }; try { - await api.update(newShortcut); - alertApi.post({ - message: `Updated shortcut '${title}'`, - severity: 'success', - display: 'transient', - }); + if (api.get().some(shortcutTitle => shortcutTitle.title === title)) { + alertApi.post({ + message: `Shortcut title already exist`, + severity: 'error', + }); + } else { + await api.update(newShortcut); + alertApi.post({ + message: `Updated shortcut '${title}'`, + severity: 'success', + display: 'transient', + }); + } } catch (error) { alertApi.post({ message: `Could not update shortcut: ${error.message}`, From ceee1c3ca25377bfac35d137795dc85455bf9fa1 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Wed, 26 Jul 2023 11:28:41 +0530 Subject: [PATCH 04/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.tsx | 7 ++----- plugins/shortcuts/src/EditShortcut.tsx | 8 +++----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.tsx b/plugins/shortcuts/src/AddShortcut.tsx index 32a5aaa947..e518a89934 100644 --- a/plugins/shortcuts/src/AddShortcut.tsx +++ b/plugins/shortcuts/src/AddShortcut.tsx @@ -61,20 +61,17 @@ export const AddShortcut = ({ const [formValues, setFormValues] = useState(); const open = Boolean(anchorEl); const analytics = useAnalytics(); + const shortcutData = api.get(); const handleSave: SubmitHandler = async ({ url, title }) => { if (!api.get().some(shortcutTitle => shortcutTitle.title === title)) { analytics.captureEvent('click', `Clicked 'Save' in AddShortcut`); } const shortcut: Omit = { url, title }; - const shortcutData = api.get(); try { if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) { - alertApi.post({ - message: `Shortcut title already exist`, - severity: 'error', - }); + throw new Error(`Shortcut Title '${title}' already Exist`); } else { await api.add(shortcut); alertApi.post({ diff --git a/plugins/shortcuts/src/EditShortcut.tsx b/plugins/shortcuts/src/EditShortcut.tsx index df0476f5db..5f1125e37a 100644 --- a/plugins/shortcuts/src/EditShortcut.tsx +++ b/plugins/shortcuts/src/EditShortcut.tsx @@ -60,6 +60,7 @@ export const EditShortcut = ({ const alertApi = useApi(alertApiRef); const open = Boolean(anchorEl); const analytics = useAnalytics(); + const shortcutData = api.get(); const handleSave: SubmitHandler = async ({ url, title }) => { if (!api.get().some(shortcutTitle => shortcutTitle.title === title)) { @@ -72,11 +73,8 @@ export const EditShortcut = ({ }; try { - if (api.get().some(shortcutTitle => shortcutTitle.title === title)) { - alertApi.post({ - message: `Shortcut title already exist`, - severity: 'error', - }); + if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) { + throw new Error(`Shortcut Title '${title}' already Exist`); } else { await api.update(newShortcut); alertApi.post({ From b0d9047894644a97d171dd7331c43d0c4c69e872 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Thu, 27 Jul 2023 12:02:13 +0530 Subject: [PATCH 05/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.tsx | 4 +--- plugins/shortcuts/src/EditShortcut.tsx | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.tsx b/plugins/shortcuts/src/AddShortcut.tsx index e518a89934..d1a17f267f 100644 --- a/plugins/shortcuts/src/AddShortcut.tsx +++ b/plugins/shortcuts/src/AddShortcut.tsx @@ -64,9 +64,7 @@ export const AddShortcut = ({ const shortcutData = api.get(); const handleSave: SubmitHandler = async ({ url, title }) => { - if (!api.get().some(shortcutTitle => shortcutTitle.title === title)) { - analytics.captureEvent('click', `Clicked 'Save' in AddShortcut`); - } + analytics.captureEvent('click', `Clicked 'Save' in AddShortcut`); const shortcut: Omit = { url, title }; try { diff --git a/plugins/shortcuts/src/EditShortcut.tsx b/plugins/shortcuts/src/EditShortcut.tsx index 5f1125e37a..288b35d9f0 100644 --- a/plugins/shortcuts/src/EditShortcut.tsx +++ b/plugins/shortcuts/src/EditShortcut.tsx @@ -63,9 +63,7 @@ export const EditShortcut = ({ const shortcutData = api.get(); const handleSave: SubmitHandler = async ({ url, title }) => { - if (!api.get().some(shortcutTitle => shortcutTitle.title === title)) { - analytics.captureEvent('click', `Clicked 'Save' in Edit Shortcut`); - } + analytics.captureEvent('click', `Clicked 'Save' in Edit Shortcut`); const newShortcut: Shortcut = { ...shortcut, url, From 2ec7d0cdf8c7a8eb14b1528ad3708170679fd6ac Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Thu, 27 Jul 2023 15:38:43 +0530 Subject: [PATCH 06/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.tsx | 17 ++++++----------- plugins/shortcuts/src/EditShortcut.tsx | 17 ++++++----------- plugins/shortcuts/src/ShortcutForm.tsx | 11 +++++++++++ 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.tsx b/plugins/shortcuts/src/AddShortcut.tsx index d1a17f267f..15850ab389 100644 --- a/plugins/shortcuts/src/AddShortcut.tsx +++ b/plugins/shortcuts/src/AddShortcut.tsx @@ -61,23 +61,18 @@ export const AddShortcut = ({ const [formValues, setFormValues] = useState(); const open = Boolean(anchorEl); const analytics = useAnalytics(); - const shortcutData = api.get(); const handleSave: SubmitHandler = async ({ url, title }) => { analytics.captureEvent('click', `Clicked 'Save' in AddShortcut`); const shortcut: Omit = { url, title }; try { - if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) { - throw new Error(`Shortcut Title '${title}' already Exist`); - } else { - await api.add(shortcut); - alertApi.post({ - message: `Added shortcut '${title}' to your sidebar`, - severity: 'success', - display: 'transient', - }); - } + await api.add(shortcut); + alertApi.post({ + message: `Added shortcut '${title}' to your sidebar`, + severity: 'success', + display: 'transient', + }); } catch (error) { alertApi.post({ message: `Could not add shortcut: ${error.message}`, diff --git a/plugins/shortcuts/src/EditShortcut.tsx b/plugins/shortcuts/src/EditShortcut.tsx index 288b35d9f0..9f2ffe10be 100644 --- a/plugins/shortcuts/src/EditShortcut.tsx +++ b/plugins/shortcuts/src/EditShortcut.tsx @@ -60,7 +60,6 @@ export const EditShortcut = ({ const alertApi = useApi(alertApiRef); const open = Boolean(anchorEl); const analytics = useAnalytics(); - const shortcutData = api.get(); const handleSave: SubmitHandler = async ({ url, title }) => { analytics.captureEvent('click', `Clicked 'Save' in Edit Shortcut`); @@ -71,16 +70,12 @@ export const EditShortcut = ({ }; try { - if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) { - throw new Error(`Shortcut Title '${title}' already Exist`); - } else { - await api.update(newShortcut); - alertApi.post({ - message: `Updated shortcut '${title}'`, - severity: 'success', - display: 'transient', - }); - } + await api.update(newShortcut); + alertApi.post({ + message: `Updated shortcut '${title}'`, + severity: 'success', + display: 'transient', + }); } catch (error) { alertApi.post({ message: `Could not update shortcut: ${error.message}`, diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index 99aa0d29b7..2b5aae52d9 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -24,6 +24,7 @@ import { TextField, } from '@material-ui/core'; import { FormValues } from './types'; +import { ShortcutApi } from './api'; const useStyles = makeStyles(theme => ({ field: { @@ -39,6 +40,7 @@ const useStyles = makeStyles(theme => ({ type Props = { formValues?: FormValues; onSave: SubmitHandler; + api: ShortcutApi; onClose: () => void; allowExternalLinks?: boolean; }; @@ -46,10 +48,12 @@ type Props = { export const ShortcutForm = ({ formValues, onSave, + api, onClose, allowExternalLinks, }: Props) => { const classes = useStyles(); + const shortcutData = api.get(); const { handleSubmit, reset, @@ -63,6 +67,12 @@ export const ShortcutForm = ({ }, }); + const titleIsUnique = async (title: string) => { + if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) + return 'This title name is already exist'; + return true; + }; + useEffect(() => { reset(formValues); }, [reset, formValues]); @@ -112,6 +122,7 @@ export const ShortcutForm = ({ control={control} rules={{ required: true, + validate: titleIsUnique, minLength: { value: 2, message: 'Must be at least 2 characters', From 788afefcf332ea2817c8f2859599894a58d6de5f Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Thu, 27 Jul 2023 15:54:27 +0530 Subject: [PATCH 07/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index 2b5aae52d9..891739f299 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -24,7 +24,8 @@ import { TextField, } from '@material-ui/core'; import { FormValues } from './types'; -import { ShortcutApi } from './api'; +import { shortcutsApiRef } from './api'; +import { useApi } from '@backstage/core-plugin-api'; const useStyles = makeStyles(theme => ({ field: { @@ -40,7 +41,7 @@ const useStyles = makeStyles(theme => ({ type Props = { formValues?: FormValues; onSave: SubmitHandler; - api: ShortcutApi; + // api: ShortcutApi; onClose: () => void; allowExternalLinks?: boolean; }; @@ -48,12 +49,13 @@ type Props = { export const ShortcutForm = ({ formValues, onSave, - api, + // api, onClose, allowExternalLinks, }: Props) => { const classes = useStyles(); - const shortcutData = api.get(); + const shortcutApi = useApi(shortcutsApiRef); + const shortcutData = shortcutApi.get(); const { handleSubmit, reset, From 3ed5a3fdb996f84156d0ed65c6cb3d1236219094 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Thu, 27 Jul 2023 15:56:06 +0530 Subject: [PATCH 08/24] Limit the use of the same shortcut name when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index 891739f299..f8a53620ee 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -41,7 +41,6 @@ const useStyles = makeStyles(theme => ({ type Props = { formValues?: FormValues; onSave: SubmitHandler; - // api: ShortcutApi; onClose: () => void; allowExternalLinks?: boolean; }; @@ -49,7 +48,6 @@ type Props = { export const ShortcutForm = ({ formValues, onSave, - // api, onClose, allowExternalLinks, }: Props) => { From e8fa09e881ef60d68daead5cd75c14d207066600 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Thu, 27 Jul 2023 16:08:16 +0530 Subject: [PATCH 09/24] Limit the use of the same shortcut name when adding a shortcut- added test cases Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.test.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 3a52356b5d..0e878c1fa4 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -40,6 +40,9 @@ describe('ShortcutForm', () => { expect( screen.getByText('Must be at least 2 characters'), ).toBeInTheDocument(); + expect( + screen.getByText('This title name is already exist'), + ).toBeInTheDocument(); }); }); From 33526cdb9e2ea026eb46103b6d0cbfe995cc3533 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Fri, 28 Jul 2023 20:11:22 +0530 Subject: [PATCH 10/24] Limit the use of the same shortcut name when adding a shortcut- error message changed Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index f8a53620ee..f5c5152ff7 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -69,7 +69,7 @@ export const ShortcutForm = ({ const titleIsUnique = async (title: string) => { if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) - return 'This title name is already exist'; + return 'A shortcut with this title already exists'; return true; }; From d2be7f636653341a1ef3e287834e560cd4befb1c Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Fri, 28 Jul 2023 20:13:09 +0530 Subject: [PATCH 11/24] Limit the use of the same shortcut name when adding a shortcut- error message changed Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 0e878c1fa4..511c1842c3 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -41,7 +41,7 @@ describe('ShortcutForm', () => { screen.getByText('Must be at least 2 characters'), ).toBeInTheDocument(); expect( - screen.getByText('This title name is already exist'), + screen.getByText('A shortcut with this title already exists'), ).toBeInTheDocument(); }); }); From adff62590f5c4feec2cfad68dbcafc8d6c6241fe Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Fri, 28 Jul 2023 20:34:22 +0530 Subject: [PATCH 12/24] Limit the use of the same shortcut name when adding a shortcut- test file changes Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.test.tsx | 5 ++++- plugins/shortcuts/src/EditShortcut.test.tsx | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.test.tsx b/plugins/shortcuts/src/AddShortcut.test.tsx index f8786e2b24..10ed59503b 100644 --- a/plugins/shortcuts/src/AddShortcut.test.tsx +++ b/plugins/shortcuts/src/AddShortcut.test.tsx @@ -26,6 +26,7 @@ import { import { AlertDisplay } from '@backstage/core-components'; import { TestApiProvider } from '@backstage/test-utils'; import { analyticsApiRef } from '@backstage/core-plugin-api'; +import { shortcutsApiRef } from './api'; describe('AddShortcut', () => { const api = new DefaultShortcutsApi(MockStorageApi.create()); @@ -78,7 +79,9 @@ describe('AddShortcut', () => { const spy = jest.spyOn(api, 'add'); await renderInTestApp( - + , ); diff --git a/plugins/shortcuts/src/EditShortcut.test.tsx b/plugins/shortcuts/src/EditShortcut.test.tsx index 72a89c13b6..618e3c784d 100644 --- a/plugins/shortcuts/src/EditShortcut.test.tsx +++ b/plugins/shortcuts/src/EditShortcut.test.tsx @@ -27,6 +27,7 @@ import { } from '@backstage/test-utils'; import { AlertDisplay } from '@backstage/core-components'; import { analyticsApiRef } from '@backstage/core-plugin-api'; +import { shortcutsApiRef } from './api'; describe('EditShortcut', () => { const shortcut: Shortcut = { @@ -86,7 +87,9 @@ describe('EditShortcut', () => { const spy = jest.spyOn(api, 'update'); await renderInTestApp( - + , ); From 831c28e3fcd1a2c8ad66c8b4c1d87a85df16cb69 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Fri, 28 Jul 2023 20:52:29 +0530 Subject: [PATCH 13/24] Limit the use of the same shortcut name when adding a shortcut- test file changes added Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.test.tsx | 7 +++++-- plugins/shortcuts/src/EditShortcut.test.tsx | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.test.tsx b/plugins/shortcuts/src/AddShortcut.test.tsx index 10ed59503b..1fcbacb8e6 100644 --- a/plugins/shortcuts/src/AddShortcut.test.tsx +++ b/plugins/shortcuts/src/AddShortcut.test.tsx @@ -26,7 +26,7 @@ import { import { AlertDisplay } from '@backstage/core-components'; import { TestApiProvider } from '@backstage/test-utils'; import { analyticsApiRef } from '@backstage/core-plugin-api'; -import { shortcutsApiRef } from './api'; +import { shortcutsApiRef, shortcutApi } from './api'; describe('AddShortcut', () => { const api = new DefaultShortcutsApi(MockStorageApi.create()); @@ -80,7 +80,10 @@ describe('AddShortcut', () => { await renderInTestApp( , diff --git a/plugins/shortcuts/src/EditShortcut.test.tsx b/plugins/shortcuts/src/EditShortcut.test.tsx index 618e3c784d..fcd20951dc 100644 --- a/plugins/shortcuts/src/EditShortcut.test.tsx +++ b/plugins/shortcuts/src/EditShortcut.test.tsx @@ -27,7 +27,7 @@ import { } from '@backstage/test-utils'; import { AlertDisplay } from '@backstage/core-components'; import { analyticsApiRef } from '@backstage/core-plugin-api'; -import { shortcutsApiRef } from './api'; +import { shortcutsApiRef, shortcutApi } from './api'; describe('EditShortcut', () => { const shortcut: Shortcut = { @@ -88,7 +88,10 @@ describe('EditShortcut', () => { await renderInTestApp( , From caaa5c8a558e975cf70f8b3152f653dc6f222db1 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Fri, 28 Jul 2023 21:05:57 +0530 Subject: [PATCH 14/24] Limit the use of the same shortcut name when adding a shortcut- test file changes removed Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.test.tsx | 8 +------- plugins/shortcuts/src/EditShortcut.test.tsx | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.test.tsx b/plugins/shortcuts/src/AddShortcut.test.tsx index 1fcbacb8e6..f8786e2b24 100644 --- a/plugins/shortcuts/src/AddShortcut.test.tsx +++ b/plugins/shortcuts/src/AddShortcut.test.tsx @@ -26,7 +26,6 @@ import { import { AlertDisplay } from '@backstage/core-components'; import { TestApiProvider } from '@backstage/test-utils'; import { analyticsApiRef } from '@backstage/core-plugin-api'; -import { shortcutsApiRef, shortcutApi } from './api'; describe('AddShortcut', () => { const api = new DefaultShortcutsApi(MockStorageApi.create()); @@ -79,12 +78,7 @@ describe('AddShortcut', () => { const spy = jest.spyOn(api, 'add'); await renderInTestApp( - + , ); diff --git a/plugins/shortcuts/src/EditShortcut.test.tsx b/plugins/shortcuts/src/EditShortcut.test.tsx index fcd20951dc..72a89c13b6 100644 --- a/plugins/shortcuts/src/EditShortcut.test.tsx +++ b/plugins/shortcuts/src/EditShortcut.test.tsx @@ -27,7 +27,6 @@ import { } from '@backstage/test-utils'; import { AlertDisplay } from '@backstage/core-components'; import { analyticsApiRef } from '@backstage/core-plugin-api'; -import { shortcutsApiRef, shortcutApi } from './api'; describe('EditShortcut', () => { const shortcut: Shortcut = { @@ -87,12 +86,7 @@ describe('EditShortcut', () => { const spy = jest.spyOn(api, 'update'); await renderInTestApp( - + , ); From fab2acc5c393bffb6d6be5f992a74de778540d95 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Sun, 30 Jul 2023 20:26:28 +0530 Subject: [PATCH 15/24] Limit the use of the same shortcut name and url when adding a shortcut with test cases Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.test.tsx | 66 +++++++++++++++++---- plugins/shortcuts/src/EditShortcut.test.tsx | 59 +++++++++++++++--- plugins/shortcuts/src/ShortcutForm.test.tsx | 62 ++++++++++++++++--- plugins/shortcuts/src/ShortcutForm.tsx | 7 +++ 4 files changed, 167 insertions(+), 27 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.test.tsx b/plugins/shortcuts/src/AddShortcut.test.tsx index f8786e2b24..958e963a3e 100644 --- a/plugins/shortcuts/src/AddShortcut.test.tsx +++ b/plugins/shortcuts/src/AddShortcut.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { screen, fireEvent, waitFor } from '@testing-library/react'; import { AddShortcut } from './AddShortcut'; -import { DefaultShortcutsApi } from './api'; +import { DefaultShortcutsApi, shortcutsApiRef } from './api'; import { MockAnalyticsApi, MockStorageApi, @@ -42,13 +42,29 @@ describe('AddShortcut', () => { }); it('displays the title', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); expect(screen.getByText('Add Shortcut')).toBeInTheDocument(); }); it('closes the popup', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); fireEvent.click(screen.getByText('Cancel')); expect(props.onClose).toHaveBeenCalledTimes(1); @@ -57,7 +73,17 @@ describe('AddShortcut', () => { it('saves the input', async () => { const spy = jest.spyOn(api, 'add'); - await renderInTestApp(); + await renderInTestApp( + await renderInTestApp( + + + , + ), + ); const urlInput = screen.getByPlaceholderText('Enter a URL'); const titleInput = screen.getByPlaceholderText('Enter a display name'); @@ -78,7 +104,12 @@ describe('AddShortcut', () => { const spy = jest.spyOn(api, 'add'); await renderInTestApp( - + , ); @@ -106,9 +137,18 @@ describe('AddShortcut', () => { it('pastes the values', async () => { const spy = jest.spyOn(api, 'add'); - await renderInTestApp(, { - routeEntries: ['/some-initial-url'], - }); + await renderInTestApp( + + , + , + { + routeEntries: ['/some-initial-url'], + }, + ); fireEvent.click(screen.getByText('Use current page')); fireEvent.click(screen.getByText('Save')); @@ -125,8 +165,14 @@ describe('AddShortcut', () => { await renderInTestApp( <> - - + + + + , ); diff --git a/plugins/shortcuts/src/EditShortcut.test.tsx b/plugins/shortcuts/src/EditShortcut.test.tsx index 72a89c13b6..3077168193 100644 --- a/plugins/shortcuts/src/EditShortcut.test.tsx +++ b/plugins/shortcuts/src/EditShortcut.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { screen, fireEvent, waitFor } from '@testing-library/react'; import { EditShortcut } from './EditShortcut'; import { Shortcut } from './types'; -import { DefaultShortcutsApi } from './api'; +import { DefaultShortcutsApi, shortcutsApiRef } from './api'; import { MockAnalyticsApi, MockStorageApi, @@ -48,13 +48,29 @@ describe('EditShortcut', () => { }); it('displays the title', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); expect(screen.getByText('Edit Shortcut')).toBeInTheDocument(); }); it('closes the popup', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); fireEvent.click(screen.getByText('Cancel')); expect(props.onClose).toHaveBeenCalledTimes(1); @@ -63,7 +79,15 @@ describe('EditShortcut', () => { it('updates the shortcut', async () => { const spy = jest.spyOn(api, 'update'); - await renderInTestApp(); + await renderInTestApp( + + + , + ); const urlInput = screen.getByPlaceholderText('Enter a URL'); const titleInput = screen.getByPlaceholderText('Enter a display name'); @@ -86,7 +110,12 @@ describe('EditShortcut', () => { const spy = jest.spyOn(api, 'update'); await renderInTestApp( - + , ); @@ -115,7 +144,15 @@ describe('EditShortcut', () => { it('removes the shortcut', async () => { const spy = jest.spyOn(api, 'remove'); - await renderInTestApp(); + await renderInTestApp( + + + , + ); fireEvent.click(screen.getByText('Remove')); expect(spy).toHaveBeenCalledWith('id'); @@ -132,8 +169,14 @@ describe('EditShortcut', () => { await renderInTestApp( <> - - + + + + , ); diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 511c1842c3..748f1ad022 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -16,7 +16,12 @@ import React from 'react'; import { screen, fireEvent, waitFor } from '@testing-library/react'; import { ShortcutForm } from './ShortcutForm'; -import { renderInTestApp } from '@backstage/test-utils'; +import { DefaultShortcutsApi, shortcutsApiRef } from './api'; +import { + renderInTestApp, + TestApiProvider, + MockStorageApi, +} from '@backstage/test-utils'; describe('ShortcutForm', () => { const props = { @@ -25,7 +30,15 @@ describe('ShortcutForm', () => { }; it('displays validation messages', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); const urlInput = screen.getByPlaceholderText('Enter a URL'); const titleInput = screen.getByPlaceholderText('Enter a display name'); @@ -47,7 +60,15 @@ describe('ShortcutForm', () => { }); it('allows external links', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); const urlInput = screen.getByPlaceholderText('Enter a URL'); const titleInput = screen.getByPlaceholderText('Enter a display name'); @@ -69,7 +90,15 @@ describe('ShortcutForm', () => { }); it('allows relative links when external links are enabled', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); const urlInput = screen.getByPlaceholderText('Enter a URL'); const titleInput = screen.getByPlaceholderText('Enter a display name'); @@ -92,10 +121,17 @@ describe('ShortcutForm', () => { it('calls the save handler', async () => { await renderInTestApp( - , + + + , + , ); fireEvent.click(screen.getByText('Save')); @@ -108,7 +144,15 @@ describe('ShortcutForm', () => { }); it('calls the close handler', async () => { - await renderInTestApp(); + await renderInTestApp( + + + , + ); fireEvent.click(screen.getByText('Cancel')); await waitFor(() => { diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index f5c5152ff7..388d22596e 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -73,6 +73,12 @@ export const ShortcutForm = ({ return true; }; + const urlIsUnique = async (url: string) => { + if (shortcutApi.get().some(shortcutUrl => shortcutUrl.url === url)) + return 'A shortcut with this url already exists'; + return true; + }; + useEffect(() => { reset(formValues); }, [reset, formValues]); @@ -85,6 +91,7 @@ export const ShortcutForm = ({ control={control} rules={{ required: true, + validate: urlIsUnique, ...(allowExternalLinks ? { pattern: { From 3fec69363ba58c98df276a37bd082c2247790d73 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Sun, 30 Jul 2023 20:38:25 +0530 Subject: [PATCH 16/24] Limit the use of the same shortcut name and url when adding a shortcut with test cases Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.test.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 748f1ad022..773c5491da 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -53,9 +53,6 @@ describe('ShortcutForm', () => { expect( screen.getByText('Must be at least 2 characters'), ).toBeInTheDocument(); - expect( - screen.getByText('A shortcut with this title already exists'), - ).toBeInTheDocument(); }); }); From 38b272d1f4d494dacf12df38e7a354f221924277 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Mon, 31 Jul 2023 09:58:08 +0530 Subject: [PATCH 17/24] Limit the use of the same shortcut name and url when adding a shortcut with test cases Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index 388d22596e..a23951c939 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -74,7 +74,7 @@ export const ShortcutForm = ({ }; const urlIsUnique = async (url: string) => { - if (shortcutApi.get().some(shortcutUrl => shortcutUrl.url === url)) + if (shortcutData.get().some(shortcutUrl => shortcutUrl.url === url)) return 'A shortcut with this url already exists'; return true; }; From 900dbea7f7181cd1dddd724e7a68c1b6721ab8a8 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Mon, 31 Jul 2023 10:05:31 +0530 Subject: [PATCH 18/24] Limit the use of the same shortcut name and url when adding a shortcut with test cases Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index a23951c939..4384f1c061 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -74,7 +74,7 @@ export const ShortcutForm = ({ }; const urlIsUnique = async (url: string) => { - if (shortcutData.get().some(shortcutUrl => shortcutUrl.url === url)) + if (shortcutData.some(shortcutUrl => shortcutUrl.url === url)) return 'A shortcut with this url already exists'; return true; }; From 433288347d60d8703994f8da3d2b60a39c1715e7 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Mon, 31 Jul 2023 10:12:05 +0530 Subject: [PATCH 19/24] Limit the use of the same shortcut name and url when adding a shortcut with test case error message added Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/AddShortcut.test.tsx | 16 +++++++--------- plugins/shortcuts/src/ShortcutForm.test.tsx | 6 ++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/plugins/shortcuts/src/AddShortcut.test.tsx b/plugins/shortcuts/src/AddShortcut.test.tsx index 958e963a3e..35f37bc265 100644 --- a/plugins/shortcuts/src/AddShortcut.test.tsx +++ b/plugins/shortcuts/src/AddShortcut.test.tsx @@ -74,15 +74,13 @@ describe('AddShortcut', () => { const spy = jest.spyOn(api, 'add'); await renderInTestApp( - await renderInTestApp( - - - , - ), + + + , ); const urlInput = screen.getByPlaceholderText('Enter a URL'); diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 773c5491da..8eda30e1ae 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -53,6 +53,12 @@ describe('ShortcutForm', () => { expect( screen.getByText('Must be at least 2 characters'), ).toBeInTheDocument(); + expect( + screen.getByText('A shortcut with this title already exists'), + ).toBeInTheDocument(); + expect( + screen.getByText('A shortcut with this url already exists'), + ).toBeInTheDocument(); }); }); From b5321414b2045833387a308a381b3522e8bc7635 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Mon, 31 Jul 2023 11:44:53 +0530 Subject: [PATCH 20/24] Limit the use of the same shortcut name and url when adding a shortcut with test case error message removed Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.test.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 8eda30e1ae..773c5491da 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -53,12 +53,6 @@ describe('ShortcutForm', () => { expect( screen.getByText('Must be at least 2 characters'), ).toBeInTheDocument(); - expect( - screen.getByText('A shortcut with this title already exists'), - ).toBeInTheDocument(); - expect( - screen.getByText('A shortcut with this url already exists'), - ).toBeInTheDocument(); }); }); From cef344c45c0c2a0de6b955325f7758d6ade921c9 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Fri, 4 Aug 2023 09:40:23 +0530 Subject: [PATCH 21/24] Limit the use of the same shortcut name and url when adding a shortcut fixed review changes Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index 4384f1c061..6085c6c182 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -15,6 +15,7 @@ */ import React, { useEffect } from 'react'; +import useObservable from 'react-use/lib/useObservable'; import { useForm, SubmitHandler, Controller } from 'react-hook-form'; import { Button, @@ -53,7 +54,10 @@ export const ShortcutForm = ({ }: Props) => { const classes = useStyles(); const shortcutApi = useApi(shortcutsApiRef); - const shortcutData = shortcutApi.get(); + const shortcutData = useObservable( + shortcutApi.shortcut$(), + shortcutApi.get(), + ); const { handleSubmit, reset, @@ -67,13 +71,13 @@ export const ShortcutForm = ({ }, }); - const titleIsUnique = async (title: string) => { + const titleIsUnique = (title: string) => { if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) return 'A shortcut with this title already exists'; return true; }; - const urlIsUnique = async (url: string) => { + const urlIsUnique = (url: string) => { if (shortcutData.some(shortcutUrl => shortcutUrl.url === url)) return 'A shortcut with this url already exists'; return true; From 16e4c6bfb123208cca0a91f17316be5d5100edc2 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Fri, 4 Aug 2023 09:57:31 +0530 Subject: [PATCH 22/24] Limit the use of the same shortcut name and url when adding a shortcut fixed review changes Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/shortcuts/src/ShortcutForm.tsx b/plugins/shortcuts/src/ShortcutForm.tsx index 6085c6c182..e8cd8144d0 100644 --- a/plugins/shortcuts/src/ShortcutForm.tsx +++ b/plugins/shortcuts/src/ShortcutForm.tsx @@ -71,13 +71,13 @@ export const ShortcutForm = ({ }, }); - const titleIsUnique = (title: string) => { + const titleIsUnique = (title: string) => { if (shortcutData.some(shortcutTitle => shortcutTitle.title === title)) return 'A shortcut with this title already exists'; return true; }; - const urlIsUnique = (url: string) => { + const urlIsUnique = (url: string) => { if (shortcutData.some(shortcutUrl => shortcutUrl.url === url)) return 'A shortcut with this url already exists'; return true; From bba2d813679173eb47404cd9e4fa802cf1513934 Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Wed, 9 Aug 2023 14:07:35 +0530 Subject: [PATCH 23/24] Limit the use of the same shortcut title and url when adding a shortcut Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.test.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 773c5491da..56309b4a64 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -53,6 +53,12 @@ describe('ShortcutForm', () => { expect( screen.getByText('Must be at least 2 characters'), ).toBeInTheDocument(); + expect( + screen.queryByText('A shortcut with this title already exists'), + ).not.toBeInTheDocument(); + expect( + screen.queryByText('A shortcut with this url already exists'), + ).not.toBeInTheDocument(); }); }); From 3a1e7dc3c5f573493ff199a750bbaa04630c2adc Mon Sep 17 00:00:00 2001 From: AmbrishRamachandiran Date: Mon, 14 Aug 2023 16:36:39 +0530 Subject: [PATCH 24/24] Added test cases for duplicate url and title Signed-off-by: AmbrishRamachandiran --- plugins/shortcuts/src/ShortcutForm.test.tsx | 37 +++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/plugins/shortcuts/src/ShortcutForm.test.tsx b/plugins/shortcuts/src/ShortcutForm.test.tsx index 56309b4a64..388c072725 100644 --- a/plugins/shortcuts/src/ShortcutForm.test.tsx +++ b/plugins/shortcuts/src/ShortcutForm.test.tsx @@ -53,15 +53,40 @@ describe('ShortcutForm', () => { expect( screen.getByText('Must be at least 2 characters'), ).toBeInTheDocument(); - expect( - screen.queryByText('A shortcut with this title already exists'), - ).not.toBeInTheDocument(); - expect( - screen.queryByText('A shortcut with this url already exists'), - ).not.toBeInTheDocument(); }); }); + it('displays duplicate validation messages for title and URL', async () => { + const mockShortcutApi = new DefaultShortcutsApi(MockStorageApi.create()); + mockShortcutApi.add({ title: 'Existing Title', url: '/existing-url' }); + + await renderInTestApp( + + + , + ); + + const urlInput = screen.getByPlaceholderText('Enter a URL'); + const titleInput = screen.getByPlaceholderText('Enter a display name'); + + fireEvent.change(urlInput, { target: { value: '/existing-url' } }); + fireEvent.change(titleInput, { target: { value: 'Existing Title' } }); + + fireEvent.click(screen.getByText('Save')); + + await waitFor(() => { + expect( + screen.getByText('A shortcut with this title already exists'), + ).toBeInTheDocument(); + expect( + screen.getByText('A shortcut with this url already exists'), + ).toBeInTheDocument(); + }); + + expect(props.onSave).not.toHaveBeenCalled(); + expect(props.onClose).not.toHaveBeenCalled(); + }); + it('allows external links', async () => { await renderInTestApp(