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: {