0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-11-29 09:33:54 +01:00

Added unit tests & JSDoc to initDissmisibles

- Fixes #9495
This commit is contained in:
Yekasumah 2022-11-03 22:07:17 +01:00 committed by LB (Ben Johnston)
parent 52937beea8
commit 119f288a3c
4 changed files with 117 additions and 6 deletions

View File

@ -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

View File

@ -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 = '<div>CONTENT</div>';
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 = `
<article>
<div data-wagtail-dismissible-id='test-id-1'>
<div data-wagtail-dismissible-toggle></div>
</div>
<div data-wagtail-dismissible-id='test-id-2'>
<div data-wagtail-dismissible-toggle></div>
</div>
<div data-wagtail-dismissible-id='test-id-3 data-wagtail-dismissible-toggle></div>
</article>`;
initDismissibles();
// check the classes are initially empty
expect(
document.querySelector('[data-wagtail-dismissible-id]').classList,
).toHaveLength(0);
// click all buttons
document
.querySelectorAll('[data-wagtail-dismissible-toggle]')
.forEach((item) => {
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 = `<div data-wagtail-dismissible-id='test-id-1' data-wagtail-dismissible-toggle></div>`;
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');
});
});

View File

@ -1,7 +1,24 @@
import { WAGTAIL_CONFIG } from '../config/wagtailConfig';
export function updateDismissibles(data: Record<string, boolean>) {
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<Response>}
*
* @example
* const data = { 'dismissible-1': true, 'dismissible-2': false };
* const wagtailConfig = {}
*
* updateDismissibles(data, wagtailConfig);
*/
export function updateDismissibles(
data: Record<string, boolean>,
): Promise<Response> {
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<string, boolean>) {
});
}
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<HTMLElement>(
'[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<HTMLElement>(
'[data-wagtail-dismissible-toggle]',
);
const id = dismissible.dataset.wagtailDismissibleId;
if (!(toggle && id)) return;

View File

@ -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