From 9cb84c48b9d73f9f5d48c1d82d9bea861b51bc00 Mon Sep 17 00:00:00 2001 From: Patrik Date: Tue, 13 Aug 2024 10:24:30 -0400 Subject: [PATCH] fix(live-preview): encode query string url (#7635) ## Description Fixes #7529 - [x] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## Checklist: - [x] I have added tests that prove my fix is effective or that my feature works - [x] Existing test suite passes locally with my changes --- packages/live-preview/src/mergeData.ts | 4 +- test/live-preview/int.spec.ts | 91 ++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/packages/live-preview/src/mergeData.ts b/packages/live-preview/src/mergeData.ts index fe099355ad..b95ed5d3cb 100644 --- a/packages/live-preview/src/mergeData.ts +++ b/packages/live-preview/src/mergeData.ts @@ -71,7 +71,9 @@ export const mergeData = async (args: { try { res = await requestHandler({ apiPath: apiRoute || '/api', - endpoint: `${collection}?depth=${depth}&where[id][in]=${Array.from(ids).join(',')}`, + endpoint: encodeURI( + `${collection}?depth=${depth}&where[id][in]=${Array.from(ids).join(',')}`, + ), serverURL, }).then((res) => res.json()) diff --git a/test/live-preview/int.spec.ts b/test/live-preview/int.spec.ts index 3127b1b1aa..df893647e6 100644 --- a/test/live-preview/int.spec.ts +++ b/test/live-preview/int.spec.ts @@ -31,6 +31,7 @@ describe('Collections - Live Preview', () => { let serverURL let testPost: Post + let testPostTwo: Post let tenant: Tenant let media: Media @@ -54,6 +55,15 @@ describe('Collections - Live Preview', () => { }, }) + testPostTwo = await payload.create({ + collection: postsSlug, + data: { + slug: 'post-2', + title: 'Test Post 2', + tenant: tenant.id, + }, + }) + // Create image const filePath = path.resolve(dirname, './seed/image-1.jpg') const file = await getFileByPath(filePath) @@ -1280,4 +1290,85 @@ describe('Collections - Live Preview', () => { expect(merge3.layout).toHaveLength(0) expect(merge3._numberOfRequests).toEqual(0) }) + + it('properly encodes URLs in requests', async () => { + const initialData: Partial = { + title: 'Test Page', + } + + let capturedEndpoint: string | undefined + + const customRequestHandler = async ({ apiPath, endpoint, serverURL }) => { + capturedEndpoint = `${serverURL}${apiPath}/${endpoint}` + + const mockResponse = { + ok: true, + status: 200, + headers: new Headers({ 'Content-Type': 'application/json' }), + json: () => ({ + docs: [ + { + id: testPost.id, + slug: 'post-1', + tenant: { id: 'tenant-id', title: 'Tenant 1' }, + title: 'Test Post', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }, + { + id: testPostTwo.id, + slug: 'post-2', + tenant: { id: 'tenant-id', title: 'Tenant 1' }, + title: 'Test Post 2', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }, + ], + }), + } + + return Promise.resolve(mockResponse as unknown as Response) + } + + const mergedData = await mergeData({ + depth: 1, + fieldSchema: schemaJSON, + incomingData: { + ...initialData, + relationshipPolyHasMany: [ + { value: testPost.id, relationTo: postsSlug }, + { value: testPostTwo.id, relationTo: postsSlug }, + ], + }, + initialData, + serverURL, + returnNumberOfRequests: true, + collectionPopulationRequestHandler: customRequestHandler, + }) + + expect(mergedData.relationshipPolyHasMany).toMatchObject([ + { + value: { + id: testPost.id, + slug: 'post-1', + title: 'Test Post', + }, + relationTo: postsSlug, + }, + { + value: { + id: testPostTwo.id, + slug: 'post-2', + title: 'Test Post 2', + }, + relationTo: postsSlug, + }, + ]) + + // Verify that the request was made to the properly encoded URL + // Without encodeURI wrapper the request URL - would receive string: "undefined/api/posts?depth=1&where[id][in]=66ba7ab6a60a945d10c8b976,66ba7ab6a60a945d10c8b979 + expect(capturedEndpoint).toContain( + encodeURI(`posts?depth=1&where[id][in]=${testPost.id},${testPostTwo.id}`), + ) + }) })