fix(Webflow Node): Fix issue with pagination in v2 node (#11934)

This commit is contained in:
Jon 2024-11-29 14:04:12 +00:00 committed by GitHub
parent af0398a5e3
commit 1eb94bcaf5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 84 additions and 11 deletions

View file

@ -5,7 +5,7 @@ import type {
ILoadOptionsFunctions, ILoadOptionsFunctions,
IWebhookFunctions, IWebhookFunctions,
IHttpRequestMethods, IHttpRequestMethods,
IRequestOptions, IHttpRequestOptions,
INodePropertyOptions, INodePropertyOptions,
} from 'n8n-workflow'; } from 'n8n-workflow';
@ -20,11 +20,11 @@ export async function webflowApiRequest(
) { ) {
let credentialsType = 'webflowOAuth2Api'; let credentialsType = 'webflowOAuth2Api';
let options: IRequestOptions = { let options: IHttpRequestOptions = {
method, method,
qs, qs,
body, body,
uri: uri || `https://api.webflow.com${resource}`, url: uri || `https://api.webflow.com${resource}`,
json: true, json: true,
}; };
options = Object.assign({}, options, option); options = Object.assign({}, options, option);
@ -37,8 +37,8 @@ export async function webflowApiRequest(
} }
options.headers = { 'accept-version': '1.0.0' }; options.headers = { 'accept-version': '1.0.0' };
} else { } else {
options.resolveWithFullResponse = true; options.returnFullResponse = true;
options.uri = `https://api.webflow.com/v2${resource}`; options.url = `https://api.webflow.com/v2${resource}`;
} }
if (Object.keys(options.qs as IDataObject).length === 0) { if (Object.keys(options.qs as IDataObject).length === 0) {
@ -48,7 +48,7 @@ export async function webflowApiRequest(
if (Object.keys(options.body as IDataObject).length === 0) { if (Object.keys(options.body as IDataObject).length === 0) {
delete options.body; delete options.body;
} }
return await this.helpers.requestWithAuthentication.call(this, credentialsType, options); return await this.helpers.httpRequestWithAuthentication.call(this, credentialsType, options);
} }
export async function webflowApiRequestAllItems( export async function webflowApiRequestAllItems(
@ -57,21 +57,28 @@ export async function webflowApiRequestAllItems(
endpoint: string, endpoint: string,
body: IDataObject = {}, body: IDataObject = {},
query: IDataObject = {}, query: IDataObject = {},
) { ): Promise<IDataObject[]> {
const returnData: IDataObject[] = []; const returnData: IDataObject[] = [];
let responseData; let responseData;
query.limit = 100; query.limit = 100;
query.offset = 0; query.offset = 0;
const isTypeVersion1 = this.getNode().typeVersion === 1;
do { do {
responseData = await webflowApiRequest.call(this, method, endpoint, body, query); responseData = await webflowApiRequest.call(this, method, endpoint, body, query);
if (responseData.offset !== undefined) { const items = isTypeVersion1 ? responseData.items : responseData.body.items;
returnData.push(...(items as IDataObject[]));
if (responseData.offset !== undefined || responseData?.body?.pagination?.offset !== undefined) {
query.offset += query.limit; query.offset += query.limit;
} }
returnData.push.apply(returnData, responseData.items as IDataObject[]); } while (
} while (returnData.length < responseData.total); isTypeVersion1
? returnData.length < responseData.total
: returnData.length < responseData.body.pagination.total
);
return returnData; return returnData;
} }

View file

@ -0,0 +1,66 @@
import type { IExecuteFunctions, ILoadOptionsFunctions } from 'n8n-workflow';
import { webflowApiRequestAllItems } from '../GenericFunctions';
describe('Webflow -> webflowApiRequestAllItems', () => {
let mockExecuteFunctions: IExecuteFunctions | ILoadOptionsFunctions;
const v1Response = {
items: [
{ id: '1', name: 'Item 1' },
{ id: '2', name: 'Item 2' },
],
total: 2,
};
const v2Response = {
body: {
items: [
{ id: '1', name: 'Item 1' },
{ id: '2', name: 'Item 2' },
],
pagination: {
total: 2,
},
},
};
const setupMockFunctions = (typeVersion: number) => {
mockExecuteFunctions = {
getNode: jest.fn().mockReturnValue({ typeVersion }),
getNodeParameter: jest.fn(),
helpers: {
httpRequestWithAuthentication: jest
.fn()
.mockResolvedValue(typeVersion === 1 ? v1Response : v2Response),
},
} as unknown as IExecuteFunctions | ILoadOptionsFunctions;
jest.clearAllMocks();
};
beforeEach(() => {
setupMockFunctions(1);
});
it('should return all items for type version 1', async () => {
const result = await webflowApiRequestAllItems.call(
mockExecuteFunctions,
'GET',
'/collections/collection_id/items',
);
expect(result).toEqual(v1Response.items);
});
it('should return all items for type version 2', async () => {
setupMockFunctions(2);
const result = await webflowApiRequestAllItems.call(
mockExecuteFunctions,
'GET',
'/collections/collection_id/items',
);
expect(result).toEqual(v2Response.body.items);
});
});