From 37a10857df1d979e15925c09797ed3885f98bd7a Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Fri, 1 Mar 2024 17:35:51 +0000 Subject: [PATCH] Migrate ViewV2API --- .../src/api/routes/tests/permissions.spec.ts | 18 ++-- .../server/src/api/routes/tests/row.spec.ts | 58 ++++++------ .../src/api/routes/tests/viewV2.spec.ts | 18 ++-- .../server/src/tests/utilities/api/base.ts | 7 +- .../server/src/tests/utilities/api/viewV2.ts | 89 +++++++++---------- packages/types/src/api/web/app/rows.ts | 6 +- 6 files changed, 90 insertions(+), 106 deletions(-) diff --git a/packages/server/src/api/routes/tests/permissions.spec.ts b/packages/server/src/api/routes/tests/permissions.spec.ts index b9c9ba0359..edaa73fd1a 100644 --- a/packages/server/src/api/routes/tests/permissions.spec.ts +++ b/packages/server/src/api/routes/tests/permissions.spec.ts @@ -187,9 +187,7 @@ describe("/permission", () => { // replicate changes before checking permissions await config.publish() - const res = await config.api.viewV2.search(view.id, undefined, { - usePublicUser: true, - }) + const res = await config.api.viewV2.publicSearch(view.id) expect(res.body.rows[0]._id).toEqual(row._id) }) @@ -202,10 +200,7 @@ describe("/permission", () => { // replicate changes before checking permissions await config.publish() - await config.api.viewV2.search(view.id, undefined, { - expectStatus: 403, - usePublicUser: true, - }) + await config.api.viewV2.publicSearch(view.id, undefined, { status: 403 }) }) it("should ignore the view permissions if the flag is not on", async () => { @@ -222,9 +217,8 @@ describe("/permission", () => { // replicate changes before checking permissions await config.publish() - await config.api.viewV2.search(view.id, undefined, { - expectStatus: 403, - usePublicUser: true, + await config.api.viewV2.publicSearch(view.id, undefined, { + status: 403, }) }) @@ -243,9 +237,7 @@ describe("/permission", () => { // replicate changes before checking permissions await config.publish() - const res = await config.api.viewV2.search(view.id, undefined, { - usePublicUser: true, - }) + const res = await config.api.viewV2.publicSearch(view.id) expect(res.body.rows[0]._id).toEqual(row._id) }) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 027a7fff58..c02159bb42 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -1156,8 +1156,8 @@ describe.each([ const createViewResponse = await config.createView() const response = await config.api.viewV2.search(createViewResponse.id) - expect(response.body.rows).toHaveLength(10) - expect(response.body).toEqual({ + expect(response.rows).toHaveLength(10) + expect(response).toEqual({ rows: expect.arrayContaining( rows.map(r => ({ _viewId: createViewResponse.id, @@ -1208,8 +1208,8 @@ describe.each([ const response = await config.api.viewV2.search(createViewResponse.id) - expect(response.body.rows).toHaveLength(5) - expect(response.body).toEqual({ + expect(response.rows).toHaveLength(5) + expect(response).toEqual({ rows: expect.arrayContaining( expectedRows.map(r => ({ _viewId: createViewResponse.id, @@ -1330,8 +1330,8 @@ describe.each([ createViewResponse.id ) - expect(response.body.rows).toHaveLength(4) - expect(response.body.rows).toEqual( + expect(response.rows).toHaveLength(4) + expect(response.rows).toEqual( expected.map(name => expect.objectContaining({ name })) ) } @@ -1359,8 +1359,8 @@ describe.each([ } ) - expect(response.body.rows).toHaveLength(4) - expect(response.body.rows).toEqual( + expect(response.rows).toHaveLength(4) + expect(response.rows).toEqual( expected.map(name => expect.objectContaining({ name })) ) } @@ -1384,8 +1384,8 @@ describe.each([ }) const response = await config.api.viewV2.search(view.id) - expect(response.body.rows).toHaveLength(10) - expect(response.body.rows).toEqual( + expect(response.rows).toHaveLength(10) + expect(response.rows).toEqual( expect.arrayContaining( rows.map(r => ({ ...(isInternal @@ -1404,7 +1404,7 @@ describe.each([ const createViewResponse = await config.createView() const response = await config.api.viewV2.search(createViewResponse.id) - expect(response.body.rows).toHaveLength(0) + expect(response.rows).toHaveLength(0) }) it("respects the limit parameter", async () => { @@ -1419,7 +1419,7 @@ describe.each([ query: {}, }) - expect(response.body.rows).toHaveLength(limit) + expect(response.rows).toHaveLength(limit) }) it("can handle pagination", async () => { @@ -1428,7 +1428,7 @@ describe.each([ const createViewResponse = await config.createView() const allRows = (await config.api.viewV2.search(createViewResponse.id)) - .body.rows + .rows const firstPageResponse = await config.api.viewV2.search( createViewResponse.id, @@ -1438,7 +1438,7 @@ describe.each([ query: {}, } ) - expect(firstPageResponse.body).toEqual({ + expect(firstPageResponse).toEqual({ rows: expect.arrayContaining(allRows.slice(0, 4)), totalRows: isInternal ? 10 : undefined, hasNextPage: true, @@ -1450,12 +1450,12 @@ describe.each([ { paginate: true, limit: 4, - bookmark: firstPageResponse.body.bookmark, + bookmark: firstPageResponse.bookmark, query: {}, } ) - expect(secondPageResponse.body).toEqual({ + expect(secondPageResponse).toEqual({ rows: expect.arrayContaining(allRows.slice(4, 8)), totalRows: isInternal ? 10 : undefined, hasNextPage: true, @@ -1467,11 +1467,11 @@ describe.each([ { paginate: true, limit: 4, - bookmark: secondPageResponse.body.bookmark, + bookmark: secondPageResponse.bookmark, query: {}, } ) - expect(lastPageResponse.body).toEqual({ + expect(lastPageResponse).toEqual({ rows: expect.arrayContaining(allRows.slice(8)), totalRows: isInternal ? 10 : undefined, hasNextPage: false, @@ -1518,9 +1518,8 @@ describe.each([ it("does not allow public users to fetch by default", async () => { await config.publish() - await config.api.viewV2.search(viewId, undefined, { - expectStatus: 403, - usePublicUser: true, + await config.api.viewV2.publicSearch(viewId, undefined, { + status: 403, }) }) @@ -1532,11 +1531,9 @@ describe.each([ }) await config.publish() - const response = await config.api.viewV2.search(viewId, undefined, { - usePublicUser: true, - }) + const response = await config.api.viewV2.publicSearch(viewId) - expect(response.body.rows).toHaveLength(10) + expect(response.rows).toHaveLength(10) }) it("allow public users to fetch when permissions are inherited", async () => { @@ -1547,11 +1544,9 @@ describe.each([ }) await config.publish() - const response = await config.api.viewV2.search(viewId, undefined, { - usePublicUser: true, - }) + const response = await config.api.viewV2.publicSearch(viewId) - expect(response.body.rows).toHaveLength(10) + expect(response.rows).toHaveLength(10) }) it("respects inherited permissions, not allowing not public views from public tables", async () => { @@ -1567,9 +1562,8 @@ describe.each([ }) await config.publish() - await config.api.viewV2.search(viewId, undefined, { - usePublicUser: true, - expectStatus: 403, + await config.api.viewV2.publicSearch(viewId, undefined, { + status: 403, }) }) }) diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index b03a73ddda..5198e63338 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -177,7 +177,7 @@ describe.each([ } await config.api.viewV2.create(newView, { - expectStatus: 201, + status: 201, }) }) }) @@ -275,7 +275,7 @@ describe.each([ const tableId = table._id! await config.api.viewV2.update( { ...view, id: generator.guid() }, - { expectStatus: 404 } + { status: 404 } ) expect(await config.api.table.get(tableId)).toEqual( @@ -304,7 +304,7 @@ describe.each([ }, ], }, - { expectStatus: 404 } + { status: 404 } ) expect(await config.api.table.get(tableId)).toEqual( @@ -326,12 +326,10 @@ describe.each([ ...viewV1, }, { - expectStatus: 400, - handleResponse: r => { - expect(r.body).toEqual({ - message: "Only views V2 can be updated", - status: 400, - }) + status: 400, + body: { + message: "Only views V2 can be updated", + status: 400, }, } ) @@ -403,7 +401,7 @@ describe.each([ } as Record, }, { - expectStatus: 200, + status: 200, } ) }) diff --git a/packages/server/src/tests/utilities/api/base.ts b/packages/server/src/tests/utilities/api/base.ts index d69a254f16..3f534fba86 100644 --- a/packages/server/src/tests/utilities/api/base.ts +++ b/packages/server/src/tests/utilities/api/base.ts @@ -38,6 +38,7 @@ export interface RequestOpts { Buffer | ReadStream | string | AttachedFile | undefined > expectations?: Expectations + publicUser?: boolean } export abstract class TestAPI { @@ -84,6 +85,7 @@ export abstract class TestAPI { fields = {}, files = {}, expectations, + publicUser = false, } = opts || {} const { status = 200 } = expectations || {} const expectHeaders = expectations?.headers || {} @@ -102,8 +104,11 @@ export abstract class TestAPI { url += `?${queryParams.join("&")}` } + const headersFn = publicUser + ? this.config.publicHeaders.bind(this.config) + : this.config.defaultHeaders.bind(this.config) let request = this.request[method](url).set( - this.config.defaultHeaders({ + headersFn({ "x-budibase-include-stacktrace": "true", }) ) diff --git a/packages/server/src/tests/utilities/api/viewV2.ts b/packages/server/src/tests/utilities/api/viewV2.ts index 92a6d394bf..dd49360aa8 100644 --- a/packages/server/src/tests/utilities/api/viewV2.ts +++ b/packages/server/src/tests/utilities/api/viewV2.ts @@ -3,21 +3,16 @@ import { UpdateViewRequest, ViewV2, SearchViewRowRequest, + PaginatedSearchRowResponse, } from "@budibase/types" -import TestConfiguration from "../TestConfiguration" -import { TestAPI } from "./base" +import { Expectations, TestAPI } from "./base" import { generator } from "@budibase/backend-core/tests" -import { Response } from "superagent" import sdk from "../../../sdk" export class ViewV2API extends TestAPI { - constructor(config: TestConfiguration) { - super(config) - } - create = async ( viewData?: Partial, - { expectStatus } = { expectStatus: 201 } + expectations?: Expectations ): Promise => { let tableId = viewData?.tableId if (!tableId && !this.config.table) { @@ -30,43 +25,27 @@ export class ViewV2API extends TestAPI { name: generator.guid(), ...viewData, } - const result = await this.request - .post(`/api/v2/views`) - .send(view) - .set(this.config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(expectStatus) - return result.body.data as ViewV2 + + const resp = await this._post<{ data: ViewV2 }>("/api/v2/views", { + body: view, + expectations, + }) + return resp.data } update = async ( view: UpdateViewRequest, - { - expectStatus, - handleResponse, - }: { - expectStatus: number - handleResponse?: (response: Response) => void - } = { expectStatus: 200 } + expectations?: Expectations ): Promise => { - const result = await this.request - .put(`/api/v2/views/${view.id}`) - .send(view) - .set(this.config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(expectStatus) - - if (handleResponse) { - handleResponse(result) - } - return result.body.data as ViewV2 + const resp = await this._put<{ data: ViewV2 }>(`/api/v2/views/${view.id}`, { + body: view, + expectations, + }) + return resp.data } - delete = async (viewId: string, { expectStatus } = { expectStatus: 204 }) => { - return this.request - .delete(`/api/v2/views/${viewId}`) - .set(this.config.defaultHeaders()) - .expect(expectStatus) + delete = async (viewId: string, expectations?: Expectations) => { + return await this._delete(`/api/v2/views/${viewId}`, { expectations }) } get = async (viewId: string) => { @@ -78,17 +57,29 @@ export class ViewV2API extends TestAPI { search = async ( viewId: string, params?: SearchViewRowRequest, - { expectStatus = 200, usePublicUser = false } = {} + expectations?: Expectations ) => { - return this.request - .post(`/api/v2/views/${viewId}/search`) - .send(params) - .set( - usePublicUser - ? this.config.publicHeaders() - : this.config.defaultHeaders() - ) - .expect("Content-Type", /json/) - .expect(expectStatus) + return await this._post( + `/api/v2/views/${viewId}/search`, + { + body: params, + expectations, + } + ) + } + + publicSearch = async ( + viewId: string, + params?: SearchViewRowRequest, + expectations?: Expectations + ) => { + return await this._post( + `/api/v2/views/${viewId}/search`, + { + body: params, + expectations, + publicUser: true, + } + ) } } diff --git a/packages/types/src/api/web/app/rows.ts b/packages/types/src/api/web/app/rows.ts index 14e28e4a01..0a43182dfd 100644 --- a/packages/types/src/api/web/app/rows.ts +++ b/packages/types/src/api/web/app/rows.ts @@ -1,6 +1,6 @@ import { SearchFilters, SearchParams } from "../../../sdk" import { Row } from "../../../documents" -import { SortOrder } from "../../../api" +import { PaginationResponse, SortOrder } from "../../../api" import { ReadStream } from "fs" export interface SaveRowRequest extends Row {} @@ -31,6 +31,10 @@ export interface SearchRowResponse { rows: any[] } +export interface PaginatedSearchRowResponse + extends SearchRowResponse, + PaginationResponse {} + export interface ExportRowsRequest { rows: string[] columns?: string[]