From 729dd41d9842714728fb4a48fae74cecbd90216f Mon Sep 17 00:00:00 2001 From: Sabina Talipova Date: Tue, 13 Feb 2024 13:21:01 +1300 Subject: [PATCH] ENH LinkField Jest tests --- .../LinkField/tests/LinkField-test.js | 55 +++++++++++++- .../LinkPicker/tests/LinkPicker-test.js | 3 + .../LinkPicker/tests/LinkPickerMenu-test.js | 73 +++++++++++++++++++ .../LinkPicker/tests/LinkPickerTitle-test.js | 62 ++++++++++++++-- client/src/tests/sample-test.js | 9 --- 5 files changed, 185 insertions(+), 17 deletions(-) create mode 100644 client/src/components/LinkPicker/tests/LinkPickerMenu-test.js delete mode 100644 client/src/tests/sample-test.js diff --git a/client/src/components/LinkField/tests/LinkField-test.js b/client/src/components/LinkField/tests/LinkField-test.js index 96c3c4a7..8c306343 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, act } 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,59 @@ 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( { ); 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 +33,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', () => { 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..91b33595 --- /dev/null +++ b/client/src/components/LinkPicker/tests/LinkPickerMenu-test.js @@ -0,0 +1,73 @@ +/* global jest, test */ + +import React from 'react'; +import { render, fireEvent, act } from '@testing-library/react'; +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( + + ); + await act(async () => { + await fireEvent.click(container.querySelectorAll('.dropdown-item')[1]); + }); + 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( + + ); + await act(async () => { + await fireEvent.keyDown(container.querySelector('.dropdown-item'), { key: 'Enter', code: 'Enter', charCode: 13 }); + }); + 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..a3bb113f 100644 --- a/client/src/components/LinkPicker/tests/LinkPickerTitle-test.js +++ b/client/src/components/LinkPicker/tests/LinkPickerTitle-test.js @@ -2,6 +2,7 @@ import React, { createRef } from 'react'; import { render, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom'; import { LinkFieldContext } from 'components/LinkField/LinkField'; import LinkPickerTitle from '../LinkPickerTitle'; @@ -30,11 +31,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 +75,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( @@ -137,3 +146,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'); - }); -});