Fix scienarios.spec.ts

This commit is contained in:
Sam Rose 2024-11-06 17:13:29 +00:00
parent 6801ade481
commit 50ce97135c
No known key found for this signature in database
6 changed files with 4289 additions and 4294 deletions

View File

@ -1,4 +1,3 @@
import * as setup from "./utilities"
import { import {
CreateViewRequest, CreateViewRequest,
Datasource, Datasource,
@ -37,22 +36,17 @@ import {
SearchFilters, SearchFilters,
} from "@budibase/types" } from "@budibase/types"
import { generator, mocks } from "@budibase/backend-core/tests" import { generator, mocks } from "@budibase/backend-core/tests"
import { DatabaseName, getDatasource } from "../../../integrations/tests/utils" import {
DatabaseName,
datasourceDescribe,
} from "../../../integrations/tests/utils"
import merge from "lodash/merge" import merge from "lodash/merge"
import { quotas } from "@budibase/pro" import { quotas } from "@budibase/pro"
import { db, roles, features, context } from "@budibase/backend-core" import { db, roles, features, context } from "@budibase/backend-core"
describe.each([ datasourceDescribe(
["sqs", undefined], { name: "/v2/views (%s)", exclude: [DatabaseName.MONGODB] },
[DatabaseName.POSTGRES, getDatasource(DatabaseName.POSTGRES)], ({ config, isInternal, dsProvider }) => {
[DatabaseName.MYSQL, getDatasource(DatabaseName.MYSQL)],
[DatabaseName.SQL_SERVER, getDatasource(DatabaseName.SQL_SERVER)],
[DatabaseName.MARIADB, getDatasource(DatabaseName.MARIADB)],
[DatabaseName.ORACLE, getDatasource(DatabaseName.ORACLE)],
])("/v2/views (%s)", (name, dsProvider) => {
const config = setup.getConfig()
const isInternal = name === "sqs"
let table: Table let table: Table
let rawDatasource: Datasource | undefined let rawDatasource: Datasource | undefined
let datasource: Datasource | undefined let datasource: Datasource | undefined
@ -104,19 +98,12 @@ describe.each([
beforeAll(async () => { beforeAll(async () => {
await config.init() await config.init()
if (dsProvider) { const ds = await dsProvider()
rawDatasource = await dsProvider rawDatasource = ds.rawDatasource
datasource = await config.createDatasource({ datasource = ds.datasource
datasource: rawDatasource,
})
}
table = await config.api.table.save(priceTable()) table = await config.api.table.save(priceTable())
}) })
afterAll(async () => {
setup.afterAll()
})
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks() jest.clearAllMocks()
mocks.licenses.useCloudFree() mocks.licenses.useCloudFree()
@ -207,7 +194,8 @@ describe.each([
}) })
it("can create a view with just a query field, no queryUI, for backwards compatibility", async () => { it("can create a view with just a query field, no queryUI, for backwards compatibility", async () => {
const newView: Required<Omit<CreateViewRequest, "queryUI" | "type">> = { const newView: Required<Omit<CreateViewRequest, "queryUI" | "type">> =
{
name: generator.name(), name: generator.name(),
tableId: table._id!, tableId: table._id!,
primaryDisplay: "id", primaryDisplay: "id",
@ -377,7 +365,8 @@ describe.each([
await config.api.viewV2.create(newView, { await config.api.viewV2.create(newView, {
status: 400, status: 400,
body: { body: {
message: 'Field "nonExisting" is not valid for the requested table', message:
'Field "nonExisting" is not valid for the requested table',
}, },
}) })
}) })
@ -572,7 +561,8 @@ describe.each([
await config.api.viewV2.create(newView, { await config.api.viewV2.create(newView, {
status: 400, status: 400,
body: { body: {
message: 'You can\'t hide "name" because it is the display column.', message:
'You can\'t hide "name" because it is the display column.',
status: 400, status: 400,
}, },
}) })
@ -706,7 +696,8 @@ describe.each([
{ {
status: 400, status: 400,
body: { body: {
message: "Calculation views can only have a maximum of 5 fields", message:
"Calculation views can only have a maximum of 5 fields",
}, },
} }
) )
@ -1079,7 +1070,11 @@ describe.each([
expect(await config.api.table.get(tableId)).toEqual( expect(await config.api.table.get(tableId)).toEqual(
expect.objectContaining({ expect.objectContaining({
views: { views: {
[newName]: { ...view, name: newName, schema: expect.anything() }, [newName]: {
...view,
name: newName,
schema: expect.anything(),
},
}, },
}) })
) )
@ -1292,7 +1287,8 @@ describe.each([
{ {
status: 400, status: 400,
body: { body: {
message: 'You can\'t hide "id" because it is a required field.', message:
'You can\'t hide "id" because it is a required field.',
status: 400, status: 400,
}, },
} }
@ -2708,7 +2704,9 @@ describe.each([
describe("search", () => { describe("search", () => {
it("returns empty rows from view when no schema is passed", async () => { it("returns empty rows from view when no schema is passed", async () => {
const rows = await Promise.all( const rows = await Promise.all(
Array.from({ length: 10 }, () => config.api.row.save(table._id!, {})) Array.from({ length: 10 }, () =>
config.api.row.save(table._id!, {})
)
) )
const response = await config.api.viewV2.search(view.id) const response = await config.api.viewV2.search(view.id)
expect(response.rows).toHaveLength(10) expect(response.rows).toHaveLength(10)
@ -2845,7 +2843,9 @@ describe.each([
it("respects the limit parameter", async () => { it("respects the limit parameter", async () => {
await Promise.all( await Promise.all(
Array.from({ length: 10 }, () => config.api.row.save(table._id!, {})) Array.from({ length: 10 }, () =>
config.api.row.save(table._id!, {})
)
) )
const limit = generator.integer({ min: 1, max: 8 }) const limit = generator.integer({ min: 1, max: 8 })
const response = await config.api.viewV2.search(view.id, { const response = await config.api.viewV2.search(view.id, {
@ -2857,7 +2857,9 @@ describe.each([
it("can handle pagination", async () => { it("can handle pagination", async () => {
await Promise.all( await Promise.all(
Array.from({ length: 10 }, () => config.api.row.save(table._id!, {})) Array.from({ length: 10 }, () =>
config.api.row.save(table._id!, {})
)
) )
const rows = (await config.api.viewV2.search(view.id)).rows const rows = (await config.api.viewV2.search(view.id)).rows
@ -3122,7 +3124,9 @@ describe.each([
}) })
expect(response.rows).toHaveLength(1) expect(response.rows).toHaveLength(1)
expect(response.rows).toEqual( expect(response.rows).toEqual(
expect.arrayContaining([expect.objectContaining({ _id: three._id })]) expect.arrayContaining([
expect.objectContaining({ _id: three._id }),
])
) )
}) })
@ -3546,7 +3550,10 @@ describe.each([
query: {}, query: {},
}) })
function calculate(type: CalculationType, numbers: number[]): number { function calculate(
type: CalculationType,
numbers: number[]
): number {
switch (type) { switch (type) {
case CalculationType.COUNT: case CalculationType.COUNT:
return numbers.length return numbers.length
@ -4421,7 +4428,9 @@ describe.each([
}), }),
expected: () => [ expected: () => [
{ {
users: [expect.objectContaining({ _id: config.getUser()._id })], users: [
expect.objectContaining({ _id: config.getUser()._id }),
],
}, },
], ],
}, },
@ -4558,7 +4567,9 @@ describe.each([
query: {}, query: {},
...searchOpts, ...searchOpts,
}) })
expect(rows).toEqual(expected.map(r => expect.objectContaining(r))) expect(rows).toEqual(
expected.map(r => expect.objectContaining(r))
)
} }
) )
}) })
@ -4567,7 +4578,9 @@ describe.each([
describe("permissions", () => { describe("permissions", () => {
beforeEach(async () => { beforeEach(async () => {
await Promise.all( await Promise.all(
Array.from({ length: 10 }, () => config.api.row.save(table._id!, {})) Array.from({ length: 10 }, () =>
config.api.row.save(table._id!, {})
)
) )
}) })
@ -4628,4 +4641,5 @@ describe.each([
}) })
}) })
}) })
}) }
)

View File

@ -1,35 +1,33 @@
import { Datasource, Query } from "@budibase/types" import { Datasource, Query } from "@budibase/types"
import * as setup from "./utilities" import * as setup from "./utilities"
import { DatabaseName } from "../../integrations/tests/utils" import {
DatabaseName,
datasourceDescribe,
} from "../../integrations/tests/utils"
import { Knex } from "knex" import { Knex } from "knex"
import { generator } from "@budibase/backend-core/tests"
describe.each([ datasourceDescribe(
DatabaseName.POSTGRES, { name: "execute query action", exclude: [DatabaseName.MONGODB] },
DatabaseName.MYSQL, ({ config, dsProvider }) => {
DatabaseName.SQL_SERVER,
DatabaseName.MARIADB,
DatabaseName.ORACLE,
])("execute query action (%s)", name => {
let tableName: string let tableName: string
let client: Knex let client: Knex
let datasource: Datasource let datasource: Datasource
let query: Query let query: Query
const config = setup.getConfig()
beforeAll(async () => { beforeAll(async () => {
await config.init() const ds = await dsProvider()
datasource = ds.datasource!
const testSetup = await setup.setupTestDatasource(config, name) client = ds.client!
datasource = testSetup.datasource
client = testSetup.client
}) })
beforeEach(async () => { beforeEach(async () => {
tableName = await setup.createTestTable(client, { tableName = generator.guid()
a: { type: "string" }, await client.schema.createTable(tableName, table => {
b: { type: "number" }, table.string("a")
table.integer("b")
}) })
await setup.insertTestData(client, tableName, [{ a: "string", b: 1 }]) await client(tableName).insert({ a: "string", b: 1 })
query = await setup.saveTestQuery(config, client, tableName, datasource) query = await setup.saveTestQuery(config, client, tableName, datasource)
}) })
@ -62,4 +60,5 @@ describe.each([
expect(res.response).toBeDefined() expect(res.response).toBeDefined()
expect(res.success).toEqual(false) expect(res.success).toEqual(false)
}) })
}) }
)

View File

@ -1,9 +1,14 @@
import * as automation from "../../index" import * as automation from "../../index"
import * as setup from "../utilities" import * as setup from "../utilities"
import { LoopStepType, FieldType, Table } from "@budibase/types" import { LoopStepType, FieldType, Table, Datasource } from "@budibase/types"
import { createAutomationBuilder } from "../utilities/AutomationTestBuilder" import { createAutomationBuilder } from "../utilities/AutomationTestBuilder"
import { DatabaseName } from "../../../integrations/tests/utils" import {
DatabaseName,
datasourceDescribe,
} from "../../../integrations/tests/utils"
import { FilterConditions } from "../../../automations/steps/filter" import { FilterConditions } from "../../../automations/steps/filter"
import { Knex } from "knex"
import { generator } from "@budibase/backend-core/tests"
describe("Automation Scenarios", () => { describe("Automation Scenarios", () => {
let config = setup.getConfig() let config = setup.getConfig()
@ -107,96 +112,6 @@ describe("Automation Scenarios", () => {
expect(results.steps[2].outputs.rows).toHaveLength(1) expect(results.steps[2].outputs.rows).toHaveLength(1)
}) })
it("should query an external database for some data then insert than into an internal table", async () => {
const { datasource, client } = await setup.setupTestDatasource(
config,
DatabaseName.MYSQL
)
const newTable = await config.createTable({
name: "table",
type: "table",
schema: {
name: {
name: "name",
type: FieldType.STRING,
constraints: {
presence: true,
},
},
age: {
name: "age",
type: FieldType.NUMBER,
constraints: {
presence: true,
},
},
},
})
const tableName = await setup.createTestTable(client, {
name: { type: "string" },
age: { type: "number" },
})
const rows = [
{ name: "Joe", age: 20 },
{ name: "Bob", age: 25 },
{ name: "Paul", age: 30 },
]
await setup.insertTestData(client, tableName, rows)
const query = await setup.saveTestQuery(
config,
client,
tableName,
datasource
)
const builder = createAutomationBuilder({
name: "Test external query and save",
})
const results = await builder
.appAction({
fields: {},
})
.executeQuery({
query: {
queryId: query._id!,
},
})
.loop({
option: LoopStepType.ARRAY,
binding: "{{ steps.1.response }}",
})
.createRow({
row: {
name: "{{ loop.currentItem.name }}",
age: "{{ loop.currentItem.age }}",
tableId: newTable._id!,
},
})
.queryRows({
tableId: newTable._id!,
})
.run()
expect(results.steps).toHaveLength(3)
expect(results.steps[1].outputs.iterations).toBe(3)
expect(results.steps[1].outputs.items).toHaveLength(3)
expect(results.steps[2].outputs.rows).toHaveLength(3)
rows.forEach(expectedRow => {
expect(results.steps[2].outputs.rows).toEqual(
expect.arrayContaining([expect.objectContaining(expectedRow)])
)
})
})
it("should trigger an automation which creates and then updates a row", async () => { it("should trigger an automation which creates and then updates a row", async () => {
const table = await config.createTable({ const table = await config.createTable({
name: "TestTable", name: "TestTable",
@ -517,3 +432,104 @@ describe("Automation Scenarios", () => {
expect(results.steps[0].outputs.message).toContain("example.com") expect(results.steps[0].outputs.message).toContain("example.com")
}) })
}) })
datasourceDescribe(
{ name: "", only: [DatabaseName.MYSQL] },
({ config, dsProvider }) => {
let datasource: Datasource
let client: Knex
beforeAll(async () => {
const ds = await dsProvider()
datasource = ds.datasource!
client = ds.client!
})
it("should query an external database for some data then insert than into an internal table", async () => {
const newTable = await config.createTable({
name: "table",
type: "table",
schema: {
name: {
name: "name",
type: FieldType.STRING,
constraints: {
presence: true,
},
},
age: {
name: "age",
type: FieldType.NUMBER,
constraints: {
presence: true,
},
},
},
})
const tableName = generator.guid()
await client.schema.createTable(tableName, table => {
table.string("name")
table.integer("age")
})
const rows = [
{ name: "Joe", age: 20 },
{ name: "Bob", age: 25 },
{ name: "Paul", age: 30 },
]
await client(tableName).insert(rows)
const query = await setup.saveTestQuery(
config,
client,
tableName,
datasource
)
const builder = createAutomationBuilder({
name: "Test external query and save",
config,
})
const results = await builder
.appAction({
fields: {},
})
.executeQuery({
query: {
queryId: query._id!,
},
})
.loop({
option: LoopStepType.ARRAY,
binding: "{{ steps.1.response }}",
})
.createRow({
row: {
name: "{{ loop.currentItem.name }}",
age: "{{ loop.currentItem.age }}",
tableId: newTable._id!,
},
})
.queryRows({
tableId: newTable._id!,
})
.run()
expect(results.steps).toHaveLength(3)
expect(results.steps[1].outputs.iterations).toBe(3)
expect(results.steps[1].outputs.items).toHaveLength(3)
expect(results.steps[2].outputs.rows).toHaveLength(3)
rows.forEach(expectedRow => {
expect(results.steps[2].outputs.rows).toEqual(
expect.arrayContaining([expect.objectContaining(expectedRow)])
)
})
})
}
)

View File

@ -5,12 +5,6 @@ import emitter from "../../../events/index"
import env from "../../../environment" import env from "../../../environment"
import { AutomationActionStepId, Datasource } from "@budibase/types" import { AutomationActionStepId, Datasource } from "@budibase/types"
import { Knex } from "knex" import { Knex } from "knex"
import { generator } from "@budibase/backend-core/tests"
import {
getDatasource,
knexClient,
DatabaseName,
} from "../../../integrations/tests/utils"
let config: TestConfig let config: TestConfig
@ -64,29 +58,6 @@ export async function runStep(stepId: string, inputs: any, stepContext?: any) {
} }
} }
export async function createTestTable(client: Knex, schema: any) {
const tableName = generator.guid()
await client.schema.createTable(tableName, table => {
for (const fieldName in schema) {
const field = schema[fieldName]
if (field.type === "string") {
table.string(fieldName)
} else if (field.type === "number") {
table.integer(fieldName)
}
}
})
return tableName
}
export async function insertTestData(
client: Knex,
tableName: string,
rows: any[]
) {
await client(tableName).insert(rows)
}
export async function saveTestQuery( export async function saveTestQuery(
config: TestConfig, config: TestConfig,
client: Knex, client: Knex,
@ -107,15 +78,5 @@ export async function saveTestQuery(
}) })
} }
export async function setupTestDatasource(
config: TestConfig,
dbName: DatabaseName
) {
const db = await getDatasource(dbName)
const datasource = await config.api.datasource.create(db)
const client = await knexClient(db)
return { datasource, client }
}
export const apiKey = "test" export const apiKey = "test"
export const actions = BUILTIN_ACTION_DEFINITIONS export const actions = BUILTIN_ACTION_DEFINITIONS

View File

@ -135,7 +135,7 @@ export function datasourceDescribe(
}) })
} }
export function getDatasource( function getDatasource(
sourceName: DatabaseName sourceName: DatabaseName
): Promise<Datasource | undefined> { ): Promise<Datasource | undefined> {
return providers[sourceName]() return providers[sourceName]()

View File

@ -1,13 +1,18 @@
// Generated with:
// cd packages/server
// rg -l "datasourceDescribe" --glob "*.spec.ts"
export const DATASOURCE_TEST_FILES = [ export const DATASOURCE_TEST_FILES = [
"src/automations/tests/executeQuery.spec.ts",
"src/integration-test/mysql.spec.ts", "src/integration-test/mysql.spec.ts",
"src/integration-test/postgres.spec.ts", "src/integration-test/postgres.spec.ts",
"src/api/routes/tests/rowAction.spec.ts",
"src/automations/tests/scenarios/scenarios.spec.ts",
"src/api/routes/tests/queries/generic-sql.spec.ts", "src/api/routes/tests/queries/generic-sql.spec.ts",
"src/sdk/app/rows/search/tests/search.spec.ts", "src/api/routes/tests/table.spec.ts",
"src/api/routes/tests/queries/mongodb.spec.ts", "src/api/routes/tests/queries/mongodb.spec.ts",
"src/api/routes/tests/search.spec.ts",
"src/api/routes/tests/datasource.spec.ts", "src/api/routes/tests/datasource.spec.ts",
"src/api/routes/tests/viewV2.spec.ts", "src/api/routes/tests/viewV2.spec.ts",
"src/api/routes/tests/row.spec.ts", "src/api/routes/tests/row.spec.ts",
"src/api/routes/tests/rowAction.spec.ts", "src/api/routes/tests/search.spec.ts",
"src/api/routes/tests/table.spec.ts", "src/sdk/app/rows/search/tests/search.spec.ts",
] ]