diff --git a/src/index.js b/src/index.js index c7e8f3b..e5aa97c 100644 --- a/src/index.js +++ b/src/index.js @@ -314,8 +314,10 @@ async function send(control, action = '', method = 'GET', body = null, enctype = if (method === 'GET') { action.search = formDataToParams(body).toString() body = null - } else if (enctype !== 'multipart/form-data') { + } else if (enctype !== 'multipart/form-data' && (body instanceof FormData)) { body = formDataToParams(body) + } else { + enctype = null } } @@ -331,6 +333,8 @@ async function send(control, action = '', method = 'GET', body = null, enctype = }, settings.headers, control.headers), } + if (!request.enctype) { delete request.enctype } // Let browser set the correct multipart boundary + dispatch(control.el, 'ajax:send', request) let pending @@ -465,6 +469,13 @@ async function send(control, action = '', method = 'GET', body = null, enctype = function parseFormData(data) { if (data instanceof FormData) return data if (data instanceof HTMLFormElement) return new FormData(data) + if (typeof data === 'string') return data + if (data instanceof ArrayBuffer) return data + if (data instanceof DataView) return data + if (data instanceof Blob) return data + if (data instanceof File) return data + if (data instanceof URLSearchParams) return data + if (data instanceof ReadableStream) return data const formData = new FormData() for (let key in data) { diff --git a/tests/ajax.cy.js b/tests/ajax.cy.js index f380130..0776899 100644 --- a/tests/ajax.cy.js +++ b/tests/ajax.cy.js @@ -53,3 +53,65 @@ test('follows redirects by default', }) } ) + +test('can upload files with $ajax method', + html``, + ({ intercept, get, wait }) => { + intercept('POST', '/tests', { + statusCode: 200, + body: '

Success

File uploaded
' + }).as('response') + get('button').click() + wait('@response').then((interception) => { + // Verify the request body is a File + expect(interception.request.body).to.be.equal('test content') + }) +}) + +test('can upload string with $ajax method', + html``, + ({ intercept, get, wait }) => { + intercept('POST', '/tests', { + statusCode: 200, + body: '

Success

File uploaded
' + }).as('response') + get('button').click() + wait('@response').then((interception) => { + // Verify the request body is a File + expect(interception.request.body).to.be.equal('test content') + }) +}) + +test('can transform object to FormData with $ajax method', + html``, + ({ intercept, get, wait }) => { + intercept('POST', '/tests', { + statusCode: 200, + body: '

Success

File uploaded
' + }).as('response') + get('button').click() + wait('@response').then((interception) => { + // Verify the request body is a FormData with the correct entries + expect(interception.request.body).to.include('key=value') + expect(interception.request.body).to.include('arr='+encodeURIComponent(JSON.stringify([1,2]))) // arr=[1,2] + expect(interception.request.body).to.include('nested='+encodeURIComponent(JSON.stringify({ a: 'b' }))) // nested={"a":"b"} + }) +})