From 119f288a3cf91775687aafffe19ac4c92bb45e0a Mon Sep 17 00:00:00 2001 From: Yekasumah Date: Thu, 3 Nov 2022 22:07:17 +0100 Subject: [PATCH] Added unit tests & JSDoc to initDissmisibles - Fixes #9495 --- CHANGELOG.txt | 1 + client/src/includes/initDismissibles.test.js | 87 ++++++++++++++++++++ client/src/includes/initDismissibles.ts | 34 ++++++-- docs/releases/4.2.md | 1 + 4 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 client/src/includes/initDismissibles.test.js diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f91acd86bb..5224b9577f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -44,6 +44,7 @@ Changelog * Maintenance: Remove unnecessary box-sizing: border-box declarations in SCSS (Albina Starykova) * Maintenance: Migrated `initTooltips` to TypeScript add JSDoc and unit tests (Fatuma Abdullahi) * Maintenance: Migrated `initTagField` from core.js to own TypeScript file and add unit tests (Chisom Okeoma) + * Maintenance: Added unit tests & JSDoc to `initDissmisibles` (Yekasumah) 4.1.2 (xx.xx.xxxx) - IN DEVELOPMENT diff --git a/client/src/includes/initDismissibles.test.js b/client/src/includes/initDismissibles.test.js new file mode 100644 index 0000000000..84808e7c08 --- /dev/null +++ b/client/src/includes/initDismissibles.test.js @@ -0,0 +1,87 @@ +import { initDismissibles, updateDismissibles } from './initDismissibles'; + +jest.mock('../config/wagtailConfig.js', () => ({ + WAGTAIL_CONFIG: { + ADMIN_URLS: { DISMISSIBLES: '/admin/dismissibles/' }, + CSRF_HEADER_NAME: 'X-CSRFToken', + CSRF_TOKEN: 'test-token', + }, +})); + +describe('initDismissibles', () => { + it('should not error if there are no dismissibles', () => { + document.body.innerHTML = '
CONTENT
'; + + initDismissibles(); + + expect(document.body.innerHTML).toContain('CONTENT'); + }); + + describe('should initialise dismissibles', () => { + it('for data-wagtail-dismissible-id and data-wagtail-dismissible-toggle attribute in parent and child', () => { + document.body.innerHTML = ` +
+
+
+
+
+
+
+
{ + item.click(); + }); + + // check the classes are updated and data attribute removed + expect( + [...document.querySelectorAll('[data-wagtail-dismissible-id]')].every( + (item) => + item.classList.contains('w-dismissible--dismissed') && + item.getAttribute('data-wagtail-dismissed') === '', + ), + ).toBe(true); + }); + }); +}); + +describe('updateDismissibles', () => { + const data = { 'test-id-1': true }; + document.body.innerHTML = `
`; + + it('should update the dismissible ids', async () => { + expect.assertions(1); + + updateDismissibles(data); + + await expect(global.fetch).toHaveBeenCalledWith('/admin/dismissibles/', { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': 'test-token', + }, + body: JSON.stringify(data), + mode: 'same-origin', + }); + }); + + it('should not update the dismissible ids', async () => { + expect.assertions(1); + + updateDismissibles(data); + + global.fetch.mockRejectedValueOnce(new Error('error')); + await expect(updateDismissibles(data)).rejects.toThrowError('error'); + }); +}); diff --git a/client/src/includes/initDismissibles.ts b/client/src/includes/initDismissibles.ts index 358593d19d..6932499344 100644 --- a/client/src/includes/initDismissibles.ts +++ b/client/src/includes/initDismissibles.ts @@ -1,7 +1,24 @@ import { WAGTAIL_CONFIG } from '../config/wagtailConfig'; -export function updateDismissibles(data: Record) { - return fetch(WAGTAIL_CONFIG.ADMIN_URLS.DISMISSIBLES, { +/** + * Updates the server, using a PATCH request when the toggle is clicked on a dismissible + * element initialised by initDismissibles + * + * @param data - The dismissible represented as an object with keys as + * the id and its new state: whether it is dismissed (boolean) + * + * @return {Promise} + * + * @example + * const data = { 'dismissible-1': true, 'dismissible-2': false }; + * const wagtailConfig = {} + * + * updateDismissibles(data, wagtailConfig); + */ +export function updateDismissibles( + data: Record, +): Promise { + return fetch(WAGTAIL_CONFIG.ADMIN_URLS?.DISMISSIBLES, { method: 'PATCH', headers: { [WAGTAIL_CONFIG.CSRF_HEADER_NAME]: WAGTAIL_CONFIG.CSRF_TOKEN, @@ -12,7 +29,11 @@ export function updateDismissibles(data: Record) { }); } -export function initDismissibles() { +/** + * Initialise dismissibles fetched from server and add click event listeners to them. + * @return {void} + */ +export function initDismissibles(): void { // A dismissible element is marked by the data-wagtail-dismissible-id attribute. const dismissibles = document.querySelectorAll( '[data-wagtail-dismissible-id]', @@ -21,13 +42,14 @@ export function initDismissibles() { // Initialise such elements with a default handler that performs the dismissal. // This only initialises elements that are rendered by the server, so elements // that are rendered by the client (e.g. React) needs to be handled separately. - dismissibles.forEach((dismissible) => { + dismissibles.forEach((dismissible: HTMLElement) => { // The toggle is marked by the data-wagtail-dismissible-toggle attribute, // which can either be the dismissible itself or a descendant element. const toggle = dismissible.hasAttribute('data-wagtail-dismissible-toggle') ? dismissible - : dismissible.querySelector('[data-wagtail-dismissible-toggle]'); - + : dismissible.querySelector( + '[data-wagtail-dismissible-toggle]', + ); const id = dismissible.dataset.wagtailDismissibleId; if (!(toggle && id)) return; diff --git a/docs/releases/4.2.md b/docs/releases/4.2.md index 00fe0a5693..1fc1218ce4 100644 --- a/docs/releases/4.2.md +++ b/docs/releases/4.2.md @@ -61,6 +61,7 @@ depth: 1 * Remove unnecessary box-sizing: border-box declarations in SCSS (Albina Starykova) * Migrated `initTooltips` to TypeScript add JSDoc and unit tests (Fatuma Abdullahi) * Migrated `initTagField` from core.js to own TypeScript file and add unit tests (Chisom Okeoma) + * Added unit tests & JSDoc to `initDissmisibles` (Yekasumah) ## Upgrade considerations