diff --git a/src/gen/api/accountingApi.ts b/src/gen/api/accountingApi.ts index c7503937c..29d15bda1 100644 --- a/src/gen/api/accountingApi.ts +++ b/src/gen/api/accountingApi.ts @@ -2142,9 +2142,10 @@ export class AccountingApi { * @param idempotencyKey This allows you to safely retry requests without the risk of duplicate processing. 128 character max. */ public async createInvoiceAttachmentByFileName (xeroTenantId: string, invoiceID: string, fileName: string, body: fs.ReadStream | Readable | Buffer , includeOnline?: boolean, idempotencyKey?: string, options: {headers: {[name: string]: string}} = {headers: {}}) : Promise<{ response: AxiosResponse; body: Attachments; }> { + const normalizedFileName = String(fileName).trimEnd(); const localVarPath = this.basePath + '/Invoices/{InvoiceID}/Attachments/{FileName}' .replace('{' + 'InvoiceID' + '}', encodeURIComponent(String(invoiceID))) - .replace('{' + 'FileName' + '}', encodeURIComponent(String(fileName))); + .replace('{' + 'FileName' + '}', encodeURIComponent(normalizedFileName)); let localVarQueryParameters: any = {}; let localVarHeaderParams: any = (Object).assign({}, this.defaultHeaders); let localVarFormParams: any = {}; @@ -17337,9 +17338,10 @@ export class AccountingApi { * @param idempotencyKey This allows you to safely retry requests without the risk of duplicate processing. 128 character max. */ public async updateInvoiceAttachmentByFileName (xeroTenantId: string, invoiceID: string, fileName: string, body: fs.ReadStream | Readable | Buffer , idempotencyKey?: string, options: {headers: {[name: string]: string}} = {headers: {}}) : Promise<{ response: AxiosResponse; body: Attachments; }> { + const normalizedFileName = String(fileName).trimEnd(); const localVarPath = this.basePath + '/Invoices/{InvoiceID}/Attachments/{FileName}' .replace('{' + 'InvoiceID' + '}', encodeURIComponent(String(invoiceID))) - .replace('{' + 'FileName' + '}', encodeURIComponent(String(fileName))); + .replace('{' + 'FileName' + '}', encodeURIComponent(normalizedFileName)); let localVarQueryParameters: any = {}; let localVarHeaderParams: any = (Object).assign({}, this.defaultHeaders); let localVarFormParams: any = {}; diff --git a/src/test/accountingApi.spec.ts b/src/test/accountingApi.spec.ts new file mode 100644 index 000000000..a9ddf1414 --- /dev/null +++ b/src/test/accountingApi.spec.ts @@ -0,0 +1,48 @@ +jest.mock('axios', () => jest.fn()); + +import axios from 'axios'; +import { AccountingApi } from '../gen/api/accountingApi'; + +describe('AccountingApi invoice attachment filenames', () => { + beforeEach(() => { + jest.clearAllMocks(); + (axios as unknown as jest.Mock).mockResolvedValue({ + status: 200, + data: {}, + }); + }); + + it('trims trailing spaces when creating an invoice attachment by filename', async () => { + const api = new AccountingApi(); + + await api.createInvoiceAttachmentByFileName( + 'tenant-123', + 'invoice-123', + 'invoice copy.pdf ', + Buffer.from('hello'), + ); + + expect(axios).toHaveBeenCalledWith( + expect.objectContaining({ + url: 'https://api.xero.com/api.xro/2.0/Invoices/invoice-123/Attachments/invoice%20copy.pdf', + }), + ); + }); + + it('trims trailing spaces when updating an invoice attachment by filename', async () => { + const api = new AccountingApi(); + + await api.updateInvoiceAttachmentByFileName( + 'tenant-123', + 'invoice-123', + 'invoice copy.pdf ', + Buffer.from('hello'), + ); + + expect(axios).toHaveBeenCalledWith( + expect.objectContaining({ + url: 'https://api.xero.com/api.xro/2.0/Invoices/invoice-123/Attachments/invoice%20copy.pdf', + }), + ); + }); +});