Merge branch 'master' into fix/got-version
This commit is contained in:
commit
206b7c37c2
|
@ -14,7 +14,6 @@ import { events } from "@budibase/backend-core"
|
||||||
import {
|
import {
|
||||||
BulkImportRequest,
|
BulkImportRequest,
|
||||||
BulkImportResponse,
|
BulkImportResponse,
|
||||||
DocumentType,
|
|
||||||
FetchTablesResponse,
|
FetchTablesResponse,
|
||||||
MigrateRequest,
|
MigrateRequest,
|
||||||
MigrateResponse,
|
MigrateResponse,
|
||||||
|
@ -25,7 +24,6 @@ import {
|
||||||
TableResponse,
|
TableResponse,
|
||||||
TableSourceType,
|
TableSourceType,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
SEPARATOR,
|
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import sdk from "../../../sdk"
|
import sdk from "../../../sdk"
|
||||||
import { jsonFromCsvString } from "../../../utilities/csv"
|
import { jsonFromCsvString } from "../../../utilities/csv"
|
||||||
|
@ -77,9 +75,10 @@ export async function save(ctx: UserCtx<SaveTableRequest, SaveTableResponse>) {
|
||||||
const table = ctx.request.body
|
const table = ctx.request.body
|
||||||
const isImport = table.rows
|
const isImport = table.rows
|
||||||
|
|
||||||
const savedTable = await pickApi({ table }).save(ctx)
|
let savedTable = await pickApi({ table }).save(ctx)
|
||||||
if (!table._id) {
|
if (!table._id) {
|
||||||
await events.table.created(savedTable)
|
await events.table.created(savedTable)
|
||||||
|
savedTable = sdk.tables.enrichViewSchemas(savedTable)
|
||||||
} else {
|
} else {
|
||||||
await events.table.updated(savedTable)
|
await events.table.updated(savedTable)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,15 @@ export async function save(ctx: UserCtx<SaveTableRequest, SaveTableResponse>) {
|
||||||
} = {
|
} = {
|
||||||
_id: generateTableID(),
|
_id: generateTableID(),
|
||||||
...rest,
|
...rest,
|
||||||
type: "table",
|
// Ensure these fields are populated, even if not sent in the request
|
||||||
sourceType: TableSourceType.INTERNAL,
|
type: rest.type || "table",
|
||||||
views: {},
|
sourceType: rest.sourceType || TableSourceType.INTERNAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tableToSave.views) {
|
||||||
|
tableToSave.views = {}
|
||||||
|
}
|
||||||
|
|
||||||
const renaming = tableToSave._rename
|
const renaming = tableToSave._rename
|
||||||
delete tableToSave._rename
|
delete tableToSave._rename
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
FieldType,
|
FieldType,
|
||||||
INTERNAL_TABLE_SOURCE_ID,
|
INTERNAL_TABLE_SOURCE_ID,
|
||||||
InternalTable,
|
InternalTable,
|
||||||
|
NumberFieldMetadata,
|
||||||
RelationshipType,
|
RelationshipType,
|
||||||
Row,
|
Row,
|
||||||
SaveTableRequest,
|
SaveTableRequest,
|
||||||
|
@ -18,6 +19,12 @@ import * as setup from "./utilities"
|
||||||
import sdk from "../../../sdk"
|
import sdk from "../../../sdk"
|
||||||
import * as uuid from "uuid"
|
import * as uuid from "uuid"
|
||||||
|
|
||||||
|
import tk from "timekeeper"
|
||||||
|
import { mocks } from "@budibase/backend-core/tests"
|
||||||
|
import { TableToBuild } from "../../../tests/utilities/TestConfiguration"
|
||||||
|
|
||||||
|
tk.freeze(mocks.date.MOCK_DATE)
|
||||||
|
|
||||||
const { basicTable } = setup.structures
|
const { basicTable } = setup.structures
|
||||||
|
|
||||||
describe("/tables", () => {
|
describe("/tables", () => {
|
||||||
|
@ -60,6 +67,67 @@ describe("/tables", () => {
|
||||||
expect(events.table.created).toBeCalledWith(res.body)
|
expect(events.table.created).toBeCalledWith(res.body)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("creates all the passed fields", async () => {
|
||||||
|
const tableData: TableToBuild = {
|
||||||
|
name: "TestTable",
|
||||||
|
type: "table",
|
||||||
|
schema: {
|
||||||
|
autoId: {
|
||||||
|
name: "id",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
subtype: AutoFieldSubType.AUTO_ID,
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
views: {
|
||||||
|
"table view": {
|
||||||
|
id: "viewId",
|
||||||
|
version: 2,
|
||||||
|
name: "table view",
|
||||||
|
tableId: "tableId",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const testTable = await config.createTable(tableData)
|
||||||
|
|
||||||
|
const expected: Table = {
|
||||||
|
...tableData,
|
||||||
|
type: "table",
|
||||||
|
views: {
|
||||||
|
"table view": {
|
||||||
|
...tableData.views!["table view"],
|
||||||
|
schema: {
|
||||||
|
autoId: {
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
presence: false,
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
name: "id",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
subtype: AutoFieldSubType.AUTO_ID,
|
||||||
|
visible: false,
|
||||||
|
} as NumberFieldMetadata,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sourceType: TableSourceType.INTERNAL,
|
||||||
|
sourceId: expect.any(String),
|
||||||
|
_rev: expect.stringMatching(/^1-.+/),
|
||||||
|
_id: expect.any(String),
|
||||||
|
createdAt: mocks.date.MOCK_DATE.toISOString(),
|
||||||
|
updatedAt: mocks.date.MOCK_DATE.toISOString(),
|
||||||
|
}
|
||||||
|
expect(testTable).toEqual(expected)
|
||||||
|
|
||||||
|
const persistedTable = await config.api.table.get(testTable._id!)
|
||||||
|
expect(persistedTable).toEqual(expected)
|
||||||
|
})
|
||||||
|
|
||||||
it("creates a table via data import", async () => {
|
it("creates a table via data import", async () => {
|
||||||
const table: SaveTableRequest = basicTable()
|
const table: SaveTableRequest = basicTable()
|
||||||
table.rows = [{ name: "test-name", description: "test-desc" }]
|
table.rows = [{ name: "test-name", description: "test-desc" }]
|
||||||
|
@ -152,6 +220,56 @@ describe("/tables", () => {
|
||||||
expect(res.body.name).toBeUndefined()
|
expect(res.body.name).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("updates only the passed fields", async () => {
|
||||||
|
const testTable = await config.createTable({
|
||||||
|
name: "TestTable",
|
||||||
|
type: "table",
|
||||||
|
schema: {
|
||||||
|
autoId: {
|
||||||
|
name: "id",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
subtype: AutoFieldSubType.AUTO_ID,
|
||||||
|
autocolumn: true,
|
||||||
|
constraints: {
|
||||||
|
type: "number",
|
||||||
|
presence: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
views: {
|
||||||
|
view1: {
|
||||||
|
id: "viewId",
|
||||||
|
version: 2,
|
||||||
|
name: "table view",
|
||||||
|
tableId: "tableId",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const response = await request
|
||||||
|
.post(`/api/tables`)
|
||||||
|
.send({
|
||||||
|
...testTable,
|
||||||
|
name: "UpdatedName",
|
||||||
|
})
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect("Content-Type", /json/)
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(response.body).toEqual({
|
||||||
|
...testTable,
|
||||||
|
name: "UpdatedName",
|
||||||
|
_rev: expect.stringMatching(/^2-.+/),
|
||||||
|
})
|
||||||
|
|
||||||
|
const persistedTable = await config.api.table.get(testTable._id!)
|
||||||
|
expect(persistedTable).toEqual({
|
||||||
|
...testTable,
|
||||||
|
name: "UpdatedName",
|
||||||
|
_rev: expect.stringMatching(/^2-.+/),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("user table", () => {
|
describe("user table", () => {
|
||||||
it("should add roleId and email field when adjusting user table schema", async () => {
|
it("should add roleId and email field when adjusting user table schema", async () => {
|
||||||
const res = await request
|
const res = await request
|
||||||
|
@ -230,6 +348,7 @@ describe("/tables", () => {
|
||||||
|
|
||||||
describe("fetch", () => {
|
describe("fetch", () => {
|
||||||
let testTable: Table
|
let testTable: Table
|
||||||
|
const enrichViewSchemasMock = jest.spyOn(sdk.tables, "enrichViewSchemas")
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
testTable = await config.createTable(testTable)
|
testTable = await config.createTable(testTable)
|
||||||
|
@ -239,6 +358,10 @@ describe("/tables", () => {
|
||||||
delete testTable._rev
|
delete testTable._rev
|
||||||
})
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
enrichViewSchemasMock.mockRestore()
|
||||||
|
})
|
||||||
|
|
||||||
it("returns all the tables for that instance in the response body", async () => {
|
it("returns all the tables for that instance in the response body", async () => {
|
||||||
const res = await request
|
const res = await request
|
||||||
.get(`/api/tables`)
|
.get(`/api/tables`)
|
||||||
|
@ -287,7 +410,7 @@ describe("/tables", () => {
|
||||||
|
|
||||||
it("should enrich the view schemas for viewsV2", async () => {
|
it("should enrich the view schemas for viewsV2", async () => {
|
||||||
const tableId = config.table!._id!
|
const tableId = config.table!._id!
|
||||||
jest.spyOn(sdk.tables, "enrichViewSchemas").mockImplementation(t => ({
|
enrichViewSchemasMock.mockImplementation(t => ({
|
||||||
...t,
|
...t,
|
||||||
views: {
|
views: {
|
||||||
view1: {
|
view1: {
|
||||||
|
@ -295,7 +418,7 @@ describe("/tables", () => {
|
||||||
name: "view1",
|
name: "view1",
|
||||||
schema: {},
|
schema: {},
|
||||||
id: "new_view_id",
|
id: "new_view_id",
|
||||||
tableId,
|
tableId: t._id!,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
@ -362,11 +485,7 @@ describe("/tables", () => {
|
||||||
let testTable: Table
|
let testTable: Table
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
testTable = await config.createTable(testTable)
|
testTable = await config.createTable()
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
delete testTable._rev
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("returns a success response when a table is deleted.", async () => {
|
it("returns a success response when a table is deleted.", async () => {
|
||||||
|
|
|
@ -75,11 +75,13 @@ export async function save(
|
||||||
if (!tableView) continue
|
if (!tableView) continue
|
||||||
|
|
||||||
if (viewsSdk.isV2(tableView)) {
|
if (viewsSdk.isV2(tableView)) {
|
||||||
table.views[view] = viewsSdk.syncSchema(
|
if (oldTable?.views && oldTable.views[view]) {
|
||||||
oldTable!.views![view] as ViewV2,
|
table.views[view] = viewsSdk.syncSchema(
|
||||||
table.schema,
|
oldTable.views[view] as ViewV2,
|
||||||
renaming
|
table.schema,
|
||||||
)
|
renaming
|
||||||
|
)
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,12 +84,12 @@ type DefaultUserValues = {
|
||||||
csrfToken: string
|
csrfToken: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TableToBuild extends Omit<Table, "sourceId" | "sourceType"> {
|
export interface TableToBuild extends Omit<Table, "sourceId" | "sourceType"> {
|
||||||
sourceId?: string
|
sourceId?: string
|
||||||
sourceType?: TableSourceType
|
sourceType?: TableSourceType
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestConfiguration {
|
export default class TestConfiguration {
|
||||||
server: any
|
server: any
|
||||||
request: supertest.SuperTest<supertest.Test> | undefined
|
request: supertest.SuperTest<supertest.Test> | undefined
|
||||||
started: boolean
|
started: boolean
|
||||||
|
@ -912,4 +912,4 @@ class TestConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export = TestConfiguration
|
module.exports = TestConfiguration
|
||||||
|
|
Loading…
Reference in New Issue