Skip to content

Commit

Permalink
Reinstate modal-workflow self.ajaxifyForm & add unit tests
Browse files Browse the repository at this point in the history
- Fixes wagtail#12618
- Regression from wagtail#12380
  • Loading branch information
lb- authored and laymonage committed Nov 22, 2024
1 parent 9cacfe0 commit cc335ca
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Changelog
* Maintenance: Migrate jQuery class toggling & drag/drop event handling within the multiple upload views to the Stimulus ZoneController usage (Ayaan Qadri)
* Maintenance: Test project template for warnings when run against Django pre-release versions (Sage Abdullah)
* Maintenance: Refactor redirects create/delete views to use generic views (Sage Abdullah)
* Maintenance: Add JSDoc description, adopt linting recommendations, and add more unit tests for `ModalWorkflow` (LB (Ben) Johnston)


6.3.2 (xx.xx.xxxx) - IN DEVELOPMENT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ HTMLCollection [
>
path/to/endpoint
</div>
<form
action="/path/to/form/submit"
id="form"
method="post"
>
<input
name="key"
value="value"
/>
</form>
</div>
Expand Down
6 changes: 3 additions & 3 deletions client/src/entrypoints/admin/modal-workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ function ModalWorkflow(opts) {
};

self.ajaxifyForm = function ajaxifyForm(formSelector) {
$(formSelector).each(() => {
$(formSelector).each(function ajaxifyFormInner() {
const action = this.action;
if (this.method.toLowerCase() === 'get') {
$(this).on('submit', () => {
$(this).on('submit', function handleSubmit() {
self.loadUrl(action, $(this).serialize());
return false;
});
} else {
$(this).on('submit', () => {
$(this).on('submit', function handleSubmit() {
self.postForm(action, $(this).serialize());
return false;
});
Expand Down
52 changes: 48 additions & 4 deletions client/src/entrypoints/admin/modal-workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,29 @@ import './modal-workflow';

$.get = jest.fn().mockImplementation((url, data, cb) => {
cb(
JSON.stringify({ html: `<div id="url">${url}</div>`, data, step: 'start' }),
JSON.stringify({
data,
html: `<div id="url">${url}</div>
<form id="form" method="post" action="/path/to/form/submit"><input name="key" value="value"></input></form>`,
step: 'start',
}),
);
return { fail: jest.fn() };
});

$.post = jest.fn((url, data, cb) => {
cb(
JSON.stringify({
html: '<div id="response">response</div>',
}),
);
return { fail: jest.fn() };
});

describe('modal-workflow', () => {
beforeEach(() => {
jest.clearAllMocks();

document.body.innerHTML =
'<div id="content"><button data-chooser-action-choose id="trigger">Open</button></div>';
});
Expand Down Expand Up @@ -102,6 +118,31 @@ describe('modal-workflow', () => {
expect(triggerButton.disabled).toBe(false);
});

it('should expose a `ajaxifyForm` method that allows forms to be submitted async', () => {
expect($.post).toHaveBeenCalledTimes(0);
expect(document.querySelectorAll('.modal-body #response')).toHaveLength(0);

const modalWorkflow = window.ModalWorkflow({ url: 'path/to/endpoint' });

modalWorkflow.ajaxifyForm('#form');

const event = new Event('submit');
event.preventDefault = jest.fn();
document.getElementById('form').dispatchEvent(event);

expect(event.preventDefault).toHaveBeenCalled();

expect($.post).toHaveBeenCalledTimes(1);
expect($.post).toHaveBeenCalledWith(
'http://localhost/path/to/form/submit',
'key=value',
expect.any(Function),
'text',
);

expect(document.querySelectorAll('.modal-body #response')).toHaveLength(1);
});

it('should handle onload and URL param options', () => {
const onload = { start: jest.fn() };
const urlParams = { page: 23 };
Expand All @@ -125,12 +166,15 @@ describe('modal-workflow', () => {

expect(modalWorkflow).toBeInstanceOf(Object);

// important: see mock implementation above, returning a response with injected data to validate behaviour
// important: see mock implementation above, returning a response with injected data to validate behavior
const response = {
data: urlParams,
html: '<div id="url">path/to/endpoint</div>',
html: expect.stringContaining('<div id="url">path/to/endpoint</div>'),
step: 'start',
};
expect(onload.start).toHaveBeenCalledWith(modalWorkflow, response);
expect(onload.start).toHaveBeenCalledWith(
modalWorkflow,
expect.objectContaining(response),
);
});
});
1 change: 1 addition & 0 deletions docs/releases/6.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ depth: 1
* Migrate jQuery class toggling & drag/drop event handling within the multiple upload views to the Stimulus ZoneController usage (Ayaan Qadri)
* Test project template for warnings when run against Django pre-release versions (Sage Abdullah)
* Refactor redirects create/delete views to use generic views (Sage Abdullah)
* Add JSDoc description, adopt linting recommendations, and add more unit tests for `ModalWorkflow` (LB (Ben) Johnston)


## Upgrade considerations - changes affecting all projects
Expand Down

0 comments on commit cc335ca

Please sign in to comment.