diff --git a/client/src/components/LinkField/tests/LinkField-test.js b/client/src/components/LinkField/tests/LinkField-test.js
index 96c3c4a7..b4140581 100644
--- a/client/src/components/LinkField/tests/LinkField-test.js
+++ b/client/src/components/LinkField/tests/LinkField-test.js
@@ -1,6 +1,6 @@
/* global jest, test, expect, document */
import React from 'react';
-import { render, act, screen } from '@testing-library/react';
+import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { Component as LinkField } from '../LinkField';
@@ -57,6 +57,57 @@ function makeProps(obj = {}) {
};
}
+test('LinkField returns list of links if they exist', async () => {
+ const { container } = render();
+
+ await doResolve({ json: () => ({
+ 1: {
+ Title: 'Page title',
+ typeKey: 'sitetree',
+ },
+ 2: {
+ Title: 'Email title',
+ typeKey: 'email',
+ },
+ }) });
+ await screen.findByText('Page title');
+ expect(container.querySelectorAll('.link-picker__button')).toHaveLength(2);
+ expect(container.querySelectorAll('.link-picker__button.font-icon-page')[0]).toHaveTextContent('Page title');
+ expect(container.querySelectorAll('.link-picker__button.font-icon-email')[0]).toHaveTextContent('Email title');
+});
+
+test('LinkField will render disabled state if disabled is true', async () => {
+ const { container } = render();
+ doResolve();
+ await screen.findByText('Cannot create link');
+ expect(container.querySelectorAll('.link-picker')).toHaveLength(1);
+ expect(container.querySelectorAll('.link-picker')[0]).toHaveTextContent('Cannot create link');
+});
+
+test('LinkField will render readonly state if readonly is true', async () => {
+ const { container } = render();
+ doResolve();
+ await screen.findByText('Cannot create link');
+ expect(container.querySelectorAll('.link-picker')).toHaveLength(1);
+ expect(container.querySelectorAll('.link-picker')[0]).toHaveTextContent('Cannot create link');
+});
+
test('LinkField tab order', async () => {
const user = userEvent.setup();
const { container } = render();
doResolve();
- // Short wait - we can't use screen.find* because we're waiting for something to be removed, not added to the DOM
- await act(async () => {
- await new Promise((resolve) => setTimeout(resolve, 100));
- });
- expect(container.querySelectorAll('.link-field__save-record-first')).toHaveLength(0);
- expect(container.querySelectorAll('.link-field__loading')).toHaveLength(0);
- expect(container.querySelectorAll('.link-picker')).toHaveLength(1);
+ await waitFor(() => {
+ expect(container.querySelectorAll('.link-field__save-record-first')).toHaveLength(0);
+ expect(container.querySelectorAll('.link-field__loading')).toHaveLength(0);
+ expect(container.querySelectorAll('.link-picker')).toHaveLength(1);
+ }, { timeout: 100 });
});
diff --git a/client/src/components/LinkPicker/tests/LinkPicker-test.js b/client/src/components/LinkPicker/tests/LinkPicker-test.js
index f9a0e59c..390c6a27 100644
--- a/client/src/components/LinkPicker/tests/LinkPicker-test.js
+++ b/client/src/components/LinkPicker/tests/LinkPicker-test.js
@@ -1,6 +1,8 @@
/* global jest, test */
import React from 'react';
-import { render, fireEvent, act } from '@testing-library/react';
+import { render, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import '@testing-library/jest-dom';
import { LinkFieldContext } from 'components/LinkField/LinkField';
import LinkPicker from '../LinkPicker';
@@ -22,6 +24,7 @@ test('LinkPickerMenu render() should display toggle if can create', () => {
);
expect(container.querySelectorAll('.link-picker__menu-toggle')).toHaveLength(1);
+ expect(container.querySelector('.link-picker__menu-toggle')).toHaveTextContent('Add Link');
expect(container.querySelectorAll('.link-picker__cannot-create')).toHaveLength(0);
});
@@ -31,6 +34,7 @@ test('LinkPickerMenu render() should display cannot create message if cannot cre
);
expect(container.querySelectorAll('.link-picker__menu-toggle')).toHaveLength(0);
expect(container.querySelectorAll('.link-picker__cannot-create')).toHaveLength(1);
+ expect(container.querySelector('.link-picker__cannot-create')).toHaveTextContent('Cannot create link');
});
test('LinkPickerMenu render() should display cannot create message if types is empty', () => {
@@ -60,18 +64,18 @@ test('LinkPickerMenu should open dropdown on click when not loading', async () =
const { container } = render(
);
- await act(async () => {
- await fireEvent.click(container.querySelector('button.link-picker__menu-toggle'));
+ userEvent.click(container.querySelector('button.link-picker__menu-toggle'));
+ await waitFor(() => {
+ expect(container.querySelectorAll('.dropdown-menu.show')).toHaveLength(1);
});
- expect(container.querySelectorAll('.dropdown-menu.show')).toHaveLength(1);
});
test('LinkPickerMenu should not open dropdown on click while loading', async () => {
const { container } = render(
);
- await act(async () => {
- await fireEvent.click(container.querySelector('button.link-picker__menu-toggle'));
+ userEvent.click(container.querySelector('button.link-picker__menu-toggle'));
+ await waitFor(() => {
+ expect(container.querySelectorAll('.dropdown-menu.show')).toHaveLength(0);
});
- expect(container.querySelectorAll('.dropdown-menu.show')).toHaveLength(0);
});
diff --git a/client/src/components/LinkPicker/tests/LinkPickerMenu-test.js b/client/src/components/LinkPicker/tests/LinkPickerMenu-test.js
new file mode 100644
index 00000000..958af61b
--- /dev/null
+++ b/client/src/components/LinkPicker/tests/LinkPickerMenu-test.js
@@ -0,0 +1,73 @@
+/* global jest, test */
+
+import React from 'react';
+import { render, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import '@testing-library/jest-dom';
+import { LinkFieldContext } from 'components/LinkField/LinkField';
+import LinkPickerMenu from '../LinkPickerMenu';
+
+function makeProps(obj = {}) {
+ return {
+ types: [
+ { key: 'sitetree', title: 'Page', icon: 'font-icon-page', allowed: true },
+ { key: 'external', title: 'External URL', icon: 'font-icon-link', allowed: true },
+ { key: 'email', title: 'Email', icon: 'font-icon-email', allowed: true },
+ { key: 'phone', title: 'Phone', icon: 'font-icon-phone', allowed: true },
+ ],
+ onSelect: jest.fn(),
+ onKeyDownEdit: jest.fn(),
+ ...obj
+ };
+}
+
+test('LinkPickerMenu render() should display link list', () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.dropdown-item')).toHaveLength(4);
+ expect(container.querySelectorAll('.dropdown-item')[0]).toHaveTextContent('Page');
+ expect(container.querySelectorAll('.dropdown-item')[1]).toHaveTextContent('External URL');
+ expect(container.querySelectorAll('.dropdown-item')[2]).toHaveTextContent('Email');
+ expect(container.querySelectorAll('.dropdown-item')[3]).toHaveTextContent('Phone');
+});
+
+test('LinkPickerMenu render() should display link list with allowed SiteTreeLink and EmailLink', () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.dropdown-item')).toHaveLength(2);
+ expect(container.querySelectorAll('.dropdown-item')[0]).toHaveTextContent('Page');
+ expect(container.querySelectorAll('.dropdown-item')[0].firstChild).toHaveClass('font-icon-page');
+ expect(container.querySelectorAll('.dropdown-item')[1]).toHaveTextContent('Email');
+ expect(container.querySelectorAll('.dropdown-item')[1].firstChild).toHaveClass('font-icon-email');
+});
+
+test('LinkPickerMenu onSelect() should call onSelect with selected type', async () => {
+ const onSelect = jest.fn();
+ const { container } = render(
+
+ );
+ userEvent.click(container.querySelectorAll('.dropdown-item')[1]);
+ await waitFor(() => {
+ expect(onSelect).toHaveBeenCalledTimes(1);
+ expect(onSelect).toHaveBeenCalledWith('external');
+ });
+});
+
+test('LinkPickerMenu onKeyDownEdit() should call onKeyDownEdit with selected type', async () => {
+ const onKeyDownEdit = jest.fn();
+ const { container } = render(
+
+ );
+ container.querySelector('.dropdown-item').focus();
+ userEvent.keyboard('{enter}');
+ await waitFor(() => expect(onKeyDownEdit).toHaveBeenCalledTimes(1));
+});
diff --git a/client/src/components/LinkPicker/tests/LinkPickerTitle-test.js b/client/src/components/LinkPicker/tests/LinkPickerTitle-test.js
index 03e74c7b..f7083e9f 100644
--- a/client/src/components/LinkPicker/tests/LinkPickerTitle-test.js
+++ b/client/src/components/LinkPicker/tests/LinkPickerTitle-test.js
@@ -1,7 +1,9 @@
/* global jest, test */
import React, { createRef } from 'react';
-import { render, fireEvent } from '@testing-library/react';
+import { render, fireEvent, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import '@testing-library/jest-dom';
import { LinkFieldContext } from 'components/LinkField/LinkField';
import LinkPickerTitle from '../LinkPickerTitle';
@@ -30,11 +32,26 @@ function makeProps(obj = {}) {
};
}
+test('LinkPickerTitle render() should display link type title and link type icon', () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.link-picker__title')).toHaveLength(1);
+ expect(container.querySelector('.link-picker__title')).toHaveTextContent('My title');
+ expect(container.querySelectorAll('.font-icon-phone')).toHaveLength(1);
+ expect(container.querySelector('.link-picker__type')).toHaveTextContent('Phone');
+ expect(container.querySelector('.link-picker__url')).toHaveTextContent('My description');
+ expect(container.querySelector('.link-picker__title > .badge')).toHaveTextContent('Draft');
+ expect(container.querySelectorAll('.link-picker__title > .status-draft')).toHaveLength(1);
+});
+
test('LinkPickerTitle render() should display clear button if can delete', () => {
const { container } = render(
);
expect(container.querySelectorAll('.link-picker__delete')).toHaveLength(1);
+ expect(container.querySelector('.link-picker__delete')).toHaveTextContent('Archive');
+ expect(container.querySelector('.link-picker__delete').getAttribute('aria-label')).toBe('Archive');
expect(container.querySelectorAll('.font-icon-phone')).toHaveLength(1);
});
@@ -59,13 +76,6 @@ test('LinkPickerTitle render() should not display clear button if disabled', ()
expect(container.querySelectorAll('.link-picker__delete')).toHaveLength(0);
});
-test('LinkPickerTitle render() should display link type icon', () => {
- const { container } = render(
-
- );
- expect(container.querySelectorAll('.font-icon-phone')).toHaveLength(1);
-});
-
test('LinkPickerTitle delete button should fire the onDelete callback when not loading', async () => {
const mockOnDelete = jest.fn();
const { container } = render(
@@ -75,11 +85,13 @@ test('LinkPickerTitle delete button should fire the onDelete callback when not l
})}
/>
);
- fireEvent.click(container.querySelector('.link-picker__delete'));
- expect(mockOnDelete).toHaveBeenCalledTimes(1);
+ userEvent.click(container.querySelector('.link-picker__delete'));
+ await waitFor(() => {
+ expect(mockOnDelete).toHaveBeenCalledTimes(1);
+ });
});
-test('LinkPickerTitle delete button should not fire the onDelete callback while loading', () => {
+test('LinkPickerTitle delete button should not fire the onDelete callback while loading', async () => {
const mockOnDelete = jest.fn();
const { container } = render(
);
- fireEvent.click(container.querySelector('.link-picker__delete'));
- expect(mockOnDelete).toHaveBeenCalledTimes(0);
+ userEvent.click(container.querySelector('.link-picker__delete'));
+ await waitFor(() => {
+ expect(mockOnDelete).toHaveBeenCalledTimes(0);
+ });
});
test('LinkPickerTitle main button should fire the onClick callback when not loading', async () => {
@@ -97,8 +111,10 @@ test('LinkPickerTitle main button should fire the onClick callback when not load
const { container } = render(
);
- fireEvent.click(container.querySelector('.link-picker__button'));
- expect(mockOnClick).toHaveBeenCalledTimes(1);
+ userEvent.click(container.querySelector('.link-picker__button'));
+ await waitFor(() => {
+ expect(mockOnClick).toHaveBeenCalledTimes(1);
+ });
});
test('LinkPickerTitle main button should not fire the onClick callback while loading', async () => {
@@ -106,8 +122,10 @@ test('LinkPickerTitle main button should not fire the onClick callback while loa
const { container } = render(
);
- fireEvent.click(container.querySelector('.link-picker__button'));
- expect(mockOnClick).toHaveBeenCalledTimes(0);
+ userEvent.click(container.querySelector('.link-picker__button'));
+ await waitFor(() => {
+ expect(mockOnClick).toHaveBeenCalledTimes(0);
+ });
});
test('LinkPickerTitle render() should have readonly class if set to readonly', () => {
@@ -137,3 +155,42 @@ test('LinkPickerTitle render() should not have disabled class if set to disabled
);
expect(container.querySelectorAll('.link-picker__link--disabled')).toHaveLength(0);
});
+
+test('dnd handler is displayed on LinkPickerTitle on MultiLinkField', () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.link-picker__drag-handle')).toHaveLength(1);
+});
+
+test('dnd handler is not displayed if link field is disabled', () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.link-picker__drag-handle')).toHaveLength(0);
+});
+
+test('dnd handler is not displayed if link field is readonly', () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.link-picker__drag-handle')).toHaveLength(0);
+});
+
+test('dnd handler is not displayed if link field is not MultiLinkField', () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.link-picker__drag-handle')).toHaveLength(0);
+});
+
+test('keydown on dnd handler', async () => {
+ const { container } = render(
+
+ );
+ expect(container.querySelectorAll('.link-picker__drag-handle')).toHaveLength(1);
+ container.querySelector('.link-picker__drag-handle').focus();
+ fireEvent.keyDown(document.activeElement || document.body, { key: 'Enter', code: 'Enter', charCode: 13 });
+ expect(container.querySelector('.link-picker__drag-handle').getAttribute('aria-pressed')).toBe('true');
+ expect(container.querySelector('.link-picker__drag-handle').getAttribute('aria-label')).toBe('Sort Links');
+});
diff --git a/client/src/tests/sample-test.js b/client/src/tests/sample-test.js
deleted file mode 100644
index 47bc3714..00000000
--- a/client/src/tests/sample-test.js
+++ /dev/null
@@ -1,9 +0,0 @@
-/* global jest, describe, it, expect */
-/* eslint-disable */
-
-describe('sample tests', () => {
- it('sample test', () => {
- const css = 'sample css';
- expect(css).toBe('sample css');
- });
-});