Migrate ViewV2API

This commit is contained in:
Sam Rose 2024-03-01 17:35:51 +00:00
parent 7fa5dbeec9
commit 37a10857df
No known key found for this signature in database
6 changed files with 90 additions and 106 deletions

View File

@ -187,9 +187,7 @@ describe("/permission", () => {
// replicate changes before checking permissions // replicate changes before checking permissions
await config.publish() await config.publish()
const res = await config.api.viewV2.search(view.id, undefined, { const res = await config.api.viewV2.publicSearch(view.id)
usePublicUser: true,
})
expect(res.body.rows[0]._id).toEqual(row._id) expect(res.body.rows[0]._id).toEqual(row._id)
}) })
@ -202,10 +200,7 @@ describe("/permission", () => {
// replicate changes before checking permissions // replicate changes before checking permissions
await config.publish() await config.publish()
await config.api.viewV2.search(view.id, undefined, { await config.api.viewV2.publicSearch(view.id, undefined, { status: 403 })
expectStatus: 403,
usePublicUser: true,
})
}) })
it("should ignore the view permissions if the flag is not on", async () => { it("should ignore the view permissions if the flag is not on", async () => {
@ -222,9 +217,8 @@ describe("/permission", () => {
// replicate changes before checking permissions // replicate changes before checking permissions
await config.publish() await config.publish()
await config.api.viewV2.search(view.id, undefined, { await config.api.viewV2.publicSearch(view.id, undefined, {
expectStatus: 403, status: 403,
usePublicUser: true,
}) })
}) })
@ -243,9 +237,7 @@ describe("/permission", () => {
// replicate changes before checking permissions // replicate changes before checking permissions
await config.publish() await config.publish()
const res = await config.api.viewV2.search(view.id, undefined, { const res = await config.api.viewV2.publicSearch(view.id)
usePublicUser: true,
})
expect(res.body.rows[0]._id).toEqual(row._id) expect(res.body.rows[0]._id).toEqual(row._id)
}) })

View File

@ -1156,8 +1156,8 @@ describe.each([
const createViewResponse = await config.createView() const createViewResponse = await config.createView()
const response = await config.api.viewV2.search(createViewResponse.id) const response = await config.api.viewV2.search(createViewResponse.id)
expect(response.body.rows).toHaveLength(10) expect(response.rows).toHaveLength(10)
expect(response.body).toEqual({ expect(response).toEqual({
rows: expect.arrayContaining( rows: expect.arrayContaining(
rows.map(r => ({ rows.map(r => ({
_viewId: createViewResponse.id, _viewId: createViewResponse.id,
@ -1208,8 +1208,8 @@ describe.each([
const response = await config.api.viewV2.search(createViewResponse.id) const response = await config.api.viewV2.search(createViewResponse.id)
expect(response.body.rows).toHaveLength(5) expect(response.rows).toHaveLength(5)
expect(response.body).toEqual({ expect(response).toEqual({
rows: expect.arrayContaining( rows: expect.arrayContaining(
expectedRows.map(r => ({ expectedRows.map(r => ({
_viewId: createViewResponse.id, _viewId: createViewResponse.id,
@ -1330,8 +1330,8 @@ describe.each([
createViewResponse.id createViewResponse.id
) )
expect(response.body.rows).toHaveLength(4) expect(response.rows).toHaveLength(4)
expect(response.body.rows).toEqual( expect(response.rows).toEqual(
expected.map(name => expect.objectContaining({ name })) expected.map(name => expect.objectContaining({ name }))
) )
} }
@ -1359,8 +1359,8 @@ describe.each([
} }
) )
expect(response.body.rows).toHaveLength(4) expect(response.rows).toHaveLength(4)
expect(response.body.rows).toEqual( expect(response.rows).toEqual(
expected.map(name => expect.objectContaining({ name })) expected.map(name => expect.objectContaining({ name }))
) )
} }
@ -1384,8 +1384,8 @@ describe.each([
}) })
const response = await config.api.viewV2.search(view.id) const response = await config.api.viewV2.search(view.id)
expect(response.body.rows).toHaveLength(10) expect(response.rows).toHaveLength(10)
expect(response.body.rows).toEqual( expect(response.rows).toEqual(
expect.arrayContaining( expect.arrayContaining(
rows.map(r => ({ rows.map(r => ({
...(isInternal ...(isInternal
@ -1404,7 +1404,7 @@ describe.each([
const createViewResponse = await config.createView() const createViewResponse = await config.createView()
const response = await config.api.viewV2.search(createViewResponse.id) 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 () => { it("respects the limit parameter", async () => {
@ -1419,7 +1419,7 @@ describe.each([
query: {}, query: {},
}) })
expect(response.body.rows).toHaveLength(limit) expect(response.rows).toHaveLength(limit)
}) })
it("can handle pagination", async () => { it("can handle pagination", async () => {
@ -1428,7 +1428,7 @@ describe.each([
const createViewResponse = await config.createView() const createViewResponse = await config.createView()
const allRows = (await config.api.viewV2.search(createViewResponse.id)) const allRows = (await config.api.viewV2.search(createViewResponse.id))
.body.rows .rows
const firstPageResponse = await config.api.viewV2.search( const firstPageResponse = await config.api.viewV2.search(
createViewResponse.id, createViewResponse.id,
@ -1438,7 +1438,7 @@ describe.each([
query: {}, query: {},
} }
) )
expect(firstPageResponse.body).toEqual({ expect(firstPageResponse).toEqual({
rows: expect.arrayContaining(allRows.slice(0, 4)), rows: expect.arrayContaining(allRows.slice(0, 4)),
totalRows: isInternal ? 10 : undefined, totalRows: isInternal ? 10 : undefined,
hasNextPage: true, hasNextPage: true,
@ -1450,12 +1450,12 @@ describe.each([
{ {
paginate: true, paginate: true,
limit: 4, limit: 4,
bookmark: firstPageResponse.body.bookmark, bookmark: firstPageResponse.bookmark,
query: {}, query: {},
} }
) )
expect(secondPageResponse.body).toEqual({ expect(secondPageResponse).toEqual({
rows: expect.arrayContaining(allRows.slice(4, 8)), rows: expect.arrayContaining(allRows.slice(4, 8)),
totalRows: isInternal ? 10 : undefined, totalRows: isInternal ? 10 : undefined,
hasNextPage: true, hasNextPage: true,
@ -1467,11 +1467,11 @@ describe.each([
{ {
paginate: true, paginate: true,
limit: 4, limit: 4,
bookmark: secondPageResponse.body.bookmark, bookmark: secondPageResponse.bookmark,
query: {}, query: {},
} }
) )
expect(lastPageResponse.body).toEqual({ expect(lastPageResponse).toEqual({
rows: expect.arrayContaining(allRows.slice(8)), rows: expect.arrayContaining(allRows.slice(8)),
totalRows: isInternal ? 10 : undefined, totalRows: isInternal ? 10 : undefined,
hasNextPage: false, hasNextPage: false,
@ -1518,9 +1518,8 @@ describe.each([
it("does not allow public users to fetch by default", async () => { it("does not allow public users to fetch by default", async () => {
await config.publish() await config.publish()
await config.api.viewV2.search(viewId, undefined, { await config.api.viewV2.publicSearch(viewId, undefined, {
expectStatus: 403, status: 403,
usePublicUser: true,
}) })
}) })
@ -1532,11 +1531,9 @@ describe.each([
}) })
await config.publish() await config.publish()
const response = await config.api.viewV2.search(viewId, undefined, { const response = await config.api.viewV2.publicSearch(viewId)
usePublicUser: true,
})
expect(response.body.rows).toHaveLength(10) expect(response.rows).toHaveLength(10)
}) })
it("allow public users to fetch when permissions are inherited", async () => { it("allow public users to fetch when permissions are inherited", async () => {
@ -1547,11 +1544,9 @@ describe.each([
}) })
await config.publish() await config.publish()
const response = await config.api.viewV2.search(viewId, undefined, { const response = await config.api.viewV2.publicSearch(viewId)
usePublicUser: true,
})
expect(response.body.rows).toHaveLength(10) expect(response.rows).toHaveLength(10)
}) })
it("respects inherited permissions, not allowing not public views from public tables", async () => { it("respects inherited permissions, not allowing not public views from public tables", async () => {
@ -1567,9 +1562,8 @@ describe.each([
}) })
await config.publish() await config.publish()
await config.api.viewV2.search(viewId, undefined, { await config.api.viewV2.publicSearch(viewId, undefined, {
usePublicUser: true, status: 403,
expectStatus: 403,
}) })
}) })
}) })

View File

@ -177,7 +177,7 @@ describe.each([
} }
await config.api.viewV2.create(newView, { await config.api.viewV2.create(newView, {
expectStatus: 201, status: 201,
}) })
}) })
}) })
@ -275,7 +275,7 @@ describe.each([
const tableId = table._id! const tableId = table._id!
await config.api.viewV2.update( await config.api.viewV2.update(
{ ...view, id: generator.guid() }, { ...view, id: generator.guid() },
{ expectStatus: 404 } { status: 404 }
) )
expect(await config.api.table.get(tableId)).toEqual( 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( expect(await config.api.table.get(tableId)).toEqual(
@ -326,12 +326,10 @@ describe.each([
...viewV1, ...viewV1,
}, },
{ {
expectStatus: 400, status: 400,
handleResponse: r => { body: {
expect(r.body).toEqual({ message: "Only views V2 can be updated",
message: "Only views V2 can be updated", status: 400,
status: 400,
})
}, },
} }
) )
@ -403,7 +401,7 @@ describe.each([
} as Record<string, FieldSchema>, } as Record<string, FieldSchema>,
}, },
{ {
expectStatus: 200, status: 200,
} }
) )
}) })

View File

@ -38,6 +38,7 @@ export interface RequestOpts {
Buffer | ReadStream | string | AttachedFile | undefined Buffer | ReadStream | string | AttachedFile | undefined
> >
expectations?: Expectations expectations?: Expectations
publicUser?: boolean
} }
export abstract class TestAPI { export abstract class TestAPI {
@ -84,6 +85,7 @@ export abstract class TestAPI {
fields = {}, fields = {},
files = {}, files = {},
expectations, expectations,
publicUser = false,
} = opts || {} } = opts || {}
const { status = 200 } = expectations || {} const { status = 200 } = expectations || {}
const expectHeaders = expectations?.headers || {} const expectHeaders = expectations?.headers || {}
@ -102,8 +104,11 @@ export abstract class TestAPI {
url += `?${queryParams.join("&")}` 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( let request = this.request[method](url).set(
this.config.defaultHeaders({ headersFn({
"x-budibase-include-stacktrace": "true", "x-budibase-include-stacktrace": "true",
}) })
) )

View File

@ -3,21 +3,16 @@ import {
UpdateViewRequest, UpdateViewRequest,
ViewV2, ViewV2,
SearchViewRowRequest, SearchViewRowRequest,
PaginatedSearchRowResponse,
} from "@budibase/types" } from "@budibase/types"
import TestConfiguration from "../TestConfiguration" import { Expectations, TestAPI } from "./base"
import { TestAPI } from "./base"
import { generator } from "@budibase/backend-core/tests" import { generator } from "@budibase/backend-core/tests"
import { Response } from "superagent"
import sdk from "../../../sdk" import sdk from "../../../sdk"
export class ViewV2API extends TestAPI { export class ViewV2API extends TestAPI {
constructor(config: TestConfiguration) {
super(config)
}
create = async ( create = async (
viewData?: Partial<CreateViewRequest>, viewData?: Partial<CreateViewRequest>,
{ expectStatus } = { expectStatus: 201 } expectations?: Expectations
): Promise<ViewV2> => { ): Promise<ViewV2> => {
let tableId = viewData?.tableId let tableId = viewData?.tableId
if (!tableId && !this.config.table) { if (!tableId && !this.config.table) {
@ -30,43 +25,27 @@ export class ViewV2API extends TestAPI {
name: generator.guid(), name: generator.guid(),
...viewData, ...viewData,
} }
const result = await this.request
.post(`/api/v2/views`) const resp = await this._post<{ data: ViewV2 }>("/api/v2/views", {
.send(view) body: view,
.set(this.config.defaultHeaders()) expectations,
.expect("Content-Type", /json/) })
.expect(expectStatus) return resp.data
return result.body.data as ViewV2
} }
update = async ( update = async (
view: UpdateViewRequest, view: UpdateViewRequest,
{ expectations?: Expectations
expectStatus,
handleResponse,
}: {
expectStatus: number
handleResponse?: (response: Response) => void
} = { expectStatus: 200 }
): Promise<ViewV2> => { ): Promise<ViewV2> => {
const result = await this.request const resp = await this._put<{ data: ViewV2 }>(`/api/v2/views/${view.id}`, {
.put(`/api/v2/views/${view.id}`) body: view,
.send(view) expectations,
.set(this.config.defaultHeaders()) })
.expect("Content-Type", /json/) return resp.data
.expect(expectStatus)
if (handleResponse) {
handleResponse(result)
}
return result.body.data as ViewV2
} }
delete = async (viewId: string, { expectStatus } = { expectStatus: 204 }) => { delete = async (viewId: string, expectations?: Expectations) => {
return this.request return await this._delete(`/api/v2/views/${viewId}`, { expectations })
.delete(`/api/v2/views/${viewId}`)
.set(this.config.defaultHeaders())
.expect(expectStatus)
} }
get = async (viewId: string) => { get = async (viewId: string) => {
@ -78,17 +57,29 @@ export class ViewV2API extends TestAPI {
search = async ( search = async (
viewId: string, viewId: string,
params?: SearchViewRowRequest, params?: SearchViewRowRequest,
{ expectStatus = 200, usePublicUser = false } = {} expectations?: Expectations
) => { ) => {
return this.request return await this._post<PaginatedSearchRowResponse>(
.post(`/api/v2/views/${viewId}/search`) `/api/v2/views/${viewId}/search`,
.send(params) {
.set( body: params,
usePublicUser expectations,
? this.config.publicHeaders() }
: this.config.defaultHeaders() )
) }
.expect("Content-Type", /json/)
.expect(expectStatus) publicSearch = async (
viewId: string,
params?: SearchViewRowRequest,
expectations?: Expectations
) => {
return await this._post<PaginatedSearchRowResponse>(
`/api/v2/views/${viewId}/search`,
{
body: params,
expectations,
publicUser: true,
}
)
} }
} }

View File

@ -1,6 +1,6 @@
import { SearchFilters, SearchParams } from "../../../sdk" import { SearchFilters, SearchParams } from "../../../sdk"
import { Row } from "../../../documents" import { Row } from "../../../documents"
import { SortOrder } from "../../../api" import { PaginationResponse, SortOrder } from "../../../api"
import { ReadStream } from "fs" import { ReadStream } from "fs"
export interface SaveRowRequest extends Row {} export interface SaveRowRequest extends Row {}
@ -31,6 +31,10 @@ export interface SearchRowResponse {
rows: any[] rows: any[]
} }
export interface PaginatedSearchRowResponse
extends SearchRowResponse,
PaginationResponse {}
export interface ExportRowsRequest { export interface ExportRowsRequest {
rows: string[] rows: string[]
columns?: string[] columns?: string[]