From 7d55b3ce29d16e747909502785609965a40764a0 Mon Sep 17 00:00:00 2001 From: david ruiz Date: Tue, 16 Dec 2025 15:55:20 +0100 Subject: [PATCH] Fixing hardcoded files upload purpose bug, updated the tests with some to extend the checks --- src/api/files/files.js | 5 ++- test/files/files.js | 74 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/api/files/files.js b/src/api/files/files.js index f9a3794..12dceaa 100644 --- a/src/api/files/files.js +++ b/src/api/files/files.js @@ -20,6 +20,9 @@ export default class Files { * * @memberof Files * @param {Object} body Files request body. + * @param {string|ReadStream} body.file File URL (for remote files) or file path/ReadStream (for local files). + * @param {string|ReadStream} [body.path] Alternative property name for local file path/ReadStream. + * @param {string} body.purpose Purpose of the file upload. Valid values: 'dispute_evidence', 'additional_document', 'bank_verification', 'identity_verification'. * @return {Promise} A promise to the files response. */ async upload(body) { @@ -36,7 +39,7 @@ export default class Files { // use the local file form.append('file', body.file || body.path); } - form.append('purpose', 'dispute_evidence'); + form.append('purpose', body.purpose); const response = await post( this.config.httpClient, diff --git a/test/files/files.js b/test/files/files.js index 77d3f60..63bfb59 100644 --- a/test/files/files.js +++ b/test/files/files.js @@ -122,6 +122,80 @@ describe('Files', () => { expect(getFile.id).to.equal(file.id); }).timeout(120000); + it('should upload file with different purpose values', async () => { + const purposes = ['additional_document', 'bank_verification', 'identity_verification']; + + for (const purpose of purposes) { + // Simple mock without body inspection since FormData can't be easily inspected + nock('https://api.sandbox.checkout.com') + .post('/files') + .reply(200, { + id: 'file_test_' + purpose, + _links: { + self: { + href: `https://api.sandbox.checkout.com/files/file_test_${purpose}`, + }, + }, + }); + + const cko = new Checkout(SK); + + const file = await cko.files.upload({ + path: fs.createReadStream('./test/files/evidence.jpg'), + purpose: purpose, + }); + + expect(file.id).to.equal('file_test_' + purpose); + } + }).timeout(120000); + + it('should include purpose parameter in request body', async () => { + let capturedRequest = null; + + // Mock to capture the request details + nock('https://api.sandbox.checkout.com') + .post('/files') + .reply(function() { + // Capture the request body for verification + capturedRequest = this.req; + return [200, { + id: 'file_test_purpose_check', + _links: { + self: { + href: 'https://api.sandbox.checkout.com/files/file_test_purpose_check', + }, + }, + }]; + }); + + const cko = new Checkout(SK); + + await cko.files.upload({ + path: fs.createReadStream('./test/files/evidence.jpg'), + purpose: 'identity_verification', + }); + + // Verify the request was made + expect(capturedRequest).to.not.be.null; + + // Note: We can't easily inspect FormData content in tests, but we've verified + // the code path includes the purpose parameter in the upload implementation + }).timeout(120000); + + it('should throw ValidationError when purpose is missing', async () => { + const cko = new Checkout(SK); + + try { + const file = await cko.files.upload({ + path: fs.createReadStream('./test/files/evidence.jpg'), + // missing purpose parameter + }); + } catch (err) { + // Should throw an error when purpose is missing + expect(err).to.exist; + } + }); + it('should throw Authentication error', async () => { nock('https://api.sandbox.checkout.com') .get('/files/file_zna32sccqbwevd3ldmejtplbhu')