wip
This commit is contained in:
parent
85d42002f9
commit
a344f2216c
|
@ -1,8 +1,7 @@
|
||||||
import { tableForDatasource } from "../../../tests/utilities/structures"
|
import { tableForDatasource } from "../../../tests/utilities/structures"
|
||||||
import {
|
import {
|
||||||
DatabaseName,
|
DatabaseName,
|
||||||
getDatasource,
|
datasourceDescribe,
|
||||||
knexClient,
|
|
||||||
} from "../../../integrations/tests/utils"
|
} from "../../../integrations/tests/utils"
|
||||||
import {
|
import {
|
||||||
context,
|
context,
|
||||||
|
@ -15,7 +14,6 @@ import {
|
||||||
withEnv as withCoreEnv,
|
withEnv as withCoreEnv,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
|
|
||||||
import * as setup from "./utilities"
|
|
||||||
import {
|
import {
|
||||||
AIOperationEnum,
|
AIOperationEnum,
|
||||||
AutoFieldSubType,
|
AutoFieldSubType,
|
||||||
|
@ -60,21 +58,13 @@ jest.mock("@budibase/pro", () => ({
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
describe.each([
|
datasourceDescribe(
|
||||||
["in-memory", undefined],
|
{
|
||||||
["sqs", undefined],
|
name: "search (%s)",
|
||||||
[DatabaseName.POSTGRES, getDatasource(DatabaseName.POSTGRES)],
|
// exclude: [DatabaseName.MONGODB],
|
||||||
[DatabaseName.MYSQL, getDatasource(DatabaseName.MYSQL)],
|
only: [DatabaseName.SQS],
|
||||||
[DatabaseName.SQL_SERVER, getDatasource(DatabaseName.SQL_SERVER)],
|
},
|
||||||
[DatabaseName.MARIADB, getDatasource(DatabaseName.MARIADB)],
|
({ config, dsProvider, isInternal, isOracle, isSql }) => {
|
||||||
[DatabaseName.ORACLE, getDatasource(DatabaseName.ORACLE)],
|
|
||||||
])("search (%s)", (name, dsProvider) => {
|
|
||||||
const isInMemory = name === "in-memory"
|
|
||||||
const isInternal = !dsProvider
|
|
||||||
const isOracle = name === DatabaseName.ORACLE
|
|
||||||
const isSql = !isInMemory
|
|
||||||
const config = setup.getConfig()
|
|
||||||
|
|
||||||
let datasource: Datasource | undefined
|
let datasource: Datasource | undefined
|
||||||
let client: Knex | undefined
|
let client: Knex | undefined
|
||||||
let tableOrViewId: string
|
let tableOrViewId: string
|
||||||
|
@ -105,8 +95,6 @@ describe.each([
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await config.init()
|
|
||||||
|
|
||||||
if (config.app?.appId) {
|
if (config.app?.appId) {
|
||||||
config.app = await config.api.application.update(config.app?.appId, {
|
config.app = await config.api.application.update(config.app?.appId, {
|
||||||
snippets: [
|
snippets: [
|
||||||
|
@ -118,17 +106,9 @@ describe.each([
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dsProvider) {
|
const ds = await dsProvider
|
||||||
const rawDatasource = await dsProvider
|
datasource = ds.datasource
|
||||||
client = await knexClient(rawDatasource)
|
client = ds.client
|
||||||
datasource = await config.createDatasource({
|
|
||||||
datasource: rawDatasource,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
setup.afterAll()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
async function createTable(schema?: TableSchema) {
|
async function createTable(schema?: TableSchema) {
|
||||||
|
@ -181,9 +161,17 @@ describe.each([
|
||||||
expect(count).toEqual(numRows)
|
expect(count).toEqual(numRows)
|
||||||
}
|
}
|
||||||
|
|
||||||
describe.each([
|
describe.each([true, false])("in-memory: %s", isInMemory => {
|
||||||
["table", createTable],
|
// We only run the in-memory tests during the SQS (isInternal) run
|
||||||
[
|
if (isInMemory && !isInternal) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateFn = (schema?: TableSchema) => Promise<string>
|
||||||
|
let tableOrView: [string, CreateFn][] = [["table", createTable]]
|
||||||
|
|
||||||
|
if (!isInMemory) {
|
||||||
|
tableOrView.push([
|
||||||
"view",
|
"view",
|
||||||
async (schema?: TableSchema) => {
|
async (schema?: TableSchema) => {
|
||||||
const tableId = await createTable(schema)
|
const tableId = await createTable(schema)
|
||||||
|
@ -203,8 +191,10 @@ describe.each([
|
||||||
)
|
)
|
||||||
return viewId
|
return viewId
|
||||||
},
|
},
|
||||||
],
|
])
|
||||||
])("from %s", (sourceType, createTableOrView) => {
|
}
|
||||||
|
|
||||||
|
describe.each(tableOrView)("from %s", (sourceType, createTableOrView) => {
|
||||||
const isView = sourceType === "view"
|
const isView = sourceType === "view"
|
||||||
|
|
||||||
class SearchAssertion {
|
class SearchAssertion {
|
||||||
|
@ -227,7 +217,10 @@ describe.each([
|
||||||
// the source array is an exact match of the target.
|
// the source array is an exact match of the target.
|
||||||
//
|
//
|
||||||
// _.isMatch("100", "1") also returns true which is not what we want.
|
// _.isMatch("100", "1") also returns true which is not what we want.
|
||||||
private isMatch<T extends Record<string, any>>(expected: T, found: T) {
|
private isMatch<T extends Record<string, any>>(
|
||||||
|
expected: T,
|
||||||
|
found: T
|
||||||
|
) {
|
||||||
if (!expected) {
|
if (!expected) {
|
||||||
throw new Error("Expected is undefined")
|
throw new Error("Expected is undefined")
|
||||||
}
|
}
|
||||||
|
@ -332,7 +325,9 @@ describe.each([
|
||||||
async toMatch(properties: Record<string, any>) {
|
async toMatch(properties: Record<string, any>) {
|
||||||
const response = await this.performSearch()
|
const response = await this.performSearch()
|
||||||
const cloned = cloneDeep(response)
|
const cloned = cloneDeep(response)
|
||||||
const keys = Object.keys(properties) as Array<keyof SearchResponse<Row>>
|
const keys = Object.keys(properties) as Array<
|
||||||
|
keyof SearchResponse<Row>
|
||||||
|
>
|
||||||
for (let key of keys) {
|
for (let key of keys) {
|
||||||
// eslint-disable-next-line jest/no-standalone-expect
|
// eslint-disable-next-line jest/no-standalone-expect
|
||||||
expect(response[key]).toBeDefined()
|
expect(response[key]).toBeDefined()
|
||||||
|
@ -418,29 +413,29 @@ describe.each([
|
||||||
|
|
||||||
describe("notEqual", () => {
|
describe("notEqual", () => {
|
||||||
it("successfully finds false row", async () => {
|
it("successfully finds false row", async () => {
|
||||||
await expectQuery({ notEqual: { isTrue: true } }).toContainExactly([
|
await expectQuery({
|
||||||
{ isTrue: false },
|
notEqual: { isTrue: true },
|
||||||
])
|
}).toContainExactly([{ isTrue: false }])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("successfully finds true row", async () => {
|
it("successfully finds true row", async () => {
|
||||||
await expectQuery({ notEqual: { isTrue: false } }).toContainExactly([
|
await expectQuery({
|
||||||
{ isTrue: true },
|
notEqual: { isTrue: false },
|
||||||
])
|
}).toContainExactly([{ isTrue: true }])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("oneOf", () => {
|
describe("oneOf", () => {
|
||||||
it("successfully finds true row", async () => {
|
it("successfully finds true row", async () => {
|
||||||
await expectQuery({ oneOf: { isTrue: [true] } }).toContainExactly([
|
await expectQuery({ oneOf: { isTrue: [true] } }).toContainExactly(
|
||||||
{ isTrue: true },
|
[{ isTrue: true }]
|
||||||
])
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("successfully finds false row", async () => {
|
it("successfully finds false row", async () => {
|
||||||
await expectQuery({ oneOf: { isTrue: [false] } }).toContainExactly([
|
await expectQuery({
|
||||||
{ isTrue: false },
|
oneOf: { isTrue: [false] },
|
||||||
])
|
}).toContainExactly([{ isTrue: false }])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -474,13 +469,18 @@ describe.each([
|
||||||
// expected.
|
// expected.
|
||||||
serverTime.setMilliseconds(0)
|
serverTime.setMilliseconds(0)
|
||||||
|
|
||||||
const future = new Date(serverTime.getTime() + 1000 * 60 * 60 * 24 * 30)
|
const future = new Date(
|
||||||
|
serverTime.getTime() + 1000 * 60 * 60 * 24 * 30
|
||||||
|
)
|
||||||
|
|
||||||
const rows = (currentUser: User) => {
|
const rows = (currentUser: User) => {
|
||||||
return [
|
return [
|
||||||
{ name: "foo", appointment: "1982-01-05T00:00:00.000Z" },
|
{ name: "foo", appointment: "1982-01-05T00:00:00.000Z" },
|
||||||
{ name: "bar", appointment: "1995-05-06T00:00:00.000Z" },
|
{ name: "bar", appointment: "1995-05-06T00:00:00.000Z" },
|
||||||
{ name: currentUser.firstName, appointment: future.toISOString() },
|
{
|
||||||
|
name: currentUser.firstName,
|
||||||
|
appointment: future.toISOString(),
|
||||||
|
},
|
||||||
{ name: "serverDate", appointment: serverTime.toISOString() },
|
{ name: "serverDate", appointment: serverTime.toISOString() },
|
||||||
{
|
{
|
||||||
name: "single user, session user",
|
name: "single user, session user",
|
||||||
|
@ -893,15 +893,15 @@ describe.each([
|
||||||
|
|
||||||
describe("notEqual", () => {
|
describe("notEqual", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ notEqual: { name: "foo" } }).toContainExactly([
|
await expectQuery({ notEqual: { name: "foo" } }).toContainExactly(
|
||||||
{ name: "bar" },
|
[{ name: "bar" }]
|
||||||
])
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
await expectQuery({ notEqual: { name: "bar" } }).toContainExactly([
|
await expectQuery({ notEqual: { name: "bar" } }).toContainExactly(
|
||||||
{ name: "foo" },
|
[{ name: "foo" }]
|
||||||
])
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1325,23 +1325,23 @@ describe.each([
|
||||||
|
|
||||||
describe("notEqual", () => {
|
describe("notEqual", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ notEqual: { dob: JAN_1ST } }).toContainExactly([
|
await expectQuery({
|
||||||
{ dob: JAN_10TH },
|
notEqual: { dob: JAN_1ST },
|
||||||
])
|
}).toContainExactly([{ dob: JAN_10TH }])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
await expectQuery({ notEqual: { dob: JAN_10TH } }).toContainExactly([
|
await expectQuery({
|
||||||
{ dob: JAN_1ST },
|
notEqual: { dob: JAN_10TH },
|
||||||
])
|
}).toContainExactly([{ dob: JAN_1ST }])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("oneOf", () => {
|
describe("oneOf", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ oneOf: { dob: [JAN_1ST] } }).toContainExactly([
|
await expectQuery({ oneOf: { dob: [JAN_1ST] } }).toContainExactly(
|
||||||
{ dob: JAN_1ST },
|
[{ dob: JAN_1ST }]
|
||||||
])
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
|
@ -1461,7 +1461,11 @@ describe.each([
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
tableOrViewId = await createTableOrView({
|
tableOrViewId = await createTableOrView({
|
||||||
timeid: { name: "timeid", type: FieldType.STRING },
|
timeid: { name: "timeid", type: FieldType.STRING },
|
||||||
time: { name: "time", type: FieldType.DATETIME, timeOnly: true },
|
time: {
|
||||||
|
name: "time",
|
||||||
|
type: FieldType.DATETIME,
|
||||||
|
timeOnly: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await createRows([
|
await createRows([
|
||||||
|
@ -1476,9 +1480,9 @@ describe.each([
|
||||||
|
|
||||||
describe("equal", () => {
|
describe("equal", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ equal: { time: T_1000 } }).toContainExactly([
|
await expectQuery({ equal: { time: T_1000 } }).toContainExactly(
|
||||||
{ time: "10:00:00" },
|
[{ time: "10:00:00" }]
|
||||||
])
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
|
@ -1490,7 +1494,9 @@ describe.each([
|
||||||
|
|
||||||
describe("notEqual", () => {
|
describe("notEqual", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ notEqual: { time: T_1000 } }).toContainExactly([
|
await expectQuery({
|
||||||
|
notEqual: { time: T_1000 },
|
||||||
|
}).toContainExactly([
|
||||||
{ timeid: NULL_TIME__ID },
|
{ timeid: NULL_TIME__ID },
|
||||||
{ time: "10:45:00" },
|
{ time: "10:45:00" },
|
||||||
{ time: "12:00:00" },
|
{ time: "12:00:00" },
|
||||||
|
@ -1515,9 +1521,9 @@ describe.each([
|
||||||
|
|
||||||
describe("oneOf", () => {
|
describe("oneOf", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ oneOf: { time: [T_1000] } }).toContainExactly([
|
await expectQuery({
|
||||||
{ time: "10:00:00" },
|
oneOf: { time: [T_1000] },
|
||||||
])
|
}).toContainExactly([{ time: "10:00:00" }])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
|
@ -1546,7 +1552,9 @@ describe.each([
|
||||||
|
|
||||||
it("successfully finds no rows", async () => {
|
it("successfully finds no rows", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
range: { time: { low: UNEXISTING_TIME, high: UNEXISTING_TIME } },
|
range: {
|
||||||
|
time: { low: UNEXISTING_TIME, high: UNEXISTING_TIME },
|
||||||
|
},
|
||||||
}).toFindNothing()
|
}).toFindNothing()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1637,7 +1645,10 @@ describe.each([
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await createRows([{ product: "Big Mac" }, { product: "McCrispy" }])
|
await createRows([
|
||||||
|
{ product: "Big Mac" },
|
||||||
|
{ product: "McCrispy" },
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("equal", () => {
|
describe("equal", () => {
|
||||||
|
@ -1704,7 +1715,10 @@ describe.each([
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
await createRows([{ numbers: ["one", "two"] }, { numbers: ["three"] }])
|
await createRows([
|
||||||
|
{ numbers: ["one", "two"] },
|
||||||
|
{ numbers: ["three"] },
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("contains", () => {
|
describe("contains", () => {
|
||||||
|
@ -1715,7 +1729,9 @@ describe.each([
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
await expectQuery({ contains: { numbers: ["none"] } }).toFindNothing()
|
await expectQuery({
|
||||||
|
contains: { numbers: ["none"] },
|
||||||
|
}).toFindNothing()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find row containing all", async () => {
|
it("fails to find row containing all", async () => {
|
||||||
|
@ -1725,10 +1741,9 @@ describe.each([
|
||||||
})
|
})
|
||||||
|
|
||||||
it("finds all with empty list", async () => {
|
it("finds all with empty list", async () => {
|
||||||
await expectQuery({ contains: { numbers: [] } }).toContainExactly([
|
await expectQuery({ contains: { numbers: [] } }).toContainExactly(
|
||||||
{ numbers: ["one", "two"] },
|
[{ numbers: ["one", "two"] }, { numbers: ["three"] }]
|
||||||
{ numbers: ["three"] },
|
)
|
||||||
])
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1751,7 +1766,9 @@ describe.each([
|
||||||
// Not sure if this is correct behaviour but changing it would be a
|
// Not sure if this is correct behaviour but changing it would be a
|
||||||
// breaking change.
|
// breaking change.
|
||||||
it("finds all with empty list", async () => {
|
it("finds all with empty list", async () => {
|
||||||
await expectQuery({ notContains: { numbers: [] } }).toContainExactly([
|
await expectQuery({
|
||||||
|
notContains: { numbers: [] },
|
||||||
|
}).toContainExactly([
|
||||||
{ numbers: ["one", "two"] },
|
{ numbers: ["one", "two"] },
|
||||||
{ numbers: ["three"] },
|
{ numbers: ["three"] },
|
||||||
])
|
])
|
||||||
|
@ -1775,7 +1792,9 @@ describe.each([
|
||||||
})
|
})
|
||||||
|
|
||||||
it("finds all with empty list", async () => {
|
it("finds all with empty list", async () => {
|
||||||
await expectQuery({ containsAny: { numbers: [] } }).toContainExactly([
|
await expectQuery({
|
||||||
|
containsAny: { numbers: [] },
|
||||||
|
}).toContainExactly([
|
||||||
{ numbers: ["one", "two"] },
|
{ numbers: ["one", "two"] },
|
||||||
{ numbers: ["three"] },
|
{ numbers: ["three"] },
|
||||||
])
|
])
|
||||||
|
@ -1842,7 +1861,11 @@ describe.each([
|
||||||
it("successfully finds all rows", async () => {
|
it("successfully finds all rows", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
oneOf: { num: [SMALL, MEDIUM, BIG] },
|
oneOf: { num: [SMALL, MEDIUM, BIG] },
|
||||||
}).toContainExactly([{ num: SMALL }, { num: MEDIUM }, { num: BIG }])
|
}).toContainExactly([
|
||||||
|
{ num: SMALL },
|
||||||
|
{ num: MEDIUM },
|
||||||
|
{ num: BIG },
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
|
@ -2094,7 +2117,9 @@ describe.each([
|
||||||
bookmark = response.bookmark
|
bookmark = response.bookmark
|
||||||
}
|
}
|
||||||
|
|
||||||
const autoValues = rows.map(row => row.auto).sort((a, b) => a - b)
|
const autoValues = rows
|
||||||
|
.map(row => row.auto)
|
||||||
|
.sort((a, b) => a - b)
|
||||||
expect(autoValues).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
expect(autoValues).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -2109,9 +2134,9 @@ describe.each([
|
||||||
})
|
})
|
||||||
|
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ equal: { "1:1:name": "bar" } }).toContainExactly([
|
await expectQuery({
|
||||||
{ "1:name": "bar" },
|
equal: { "1:1:name": "bar" },
|
||||||
])
|
}).toContainExactly([{ "1:name": "bar" }])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
|
@ -2170,7 +2195,9 @@ describe.each([
|
||||||
})
|
})
|
||||||
|
|
||||||
it("formula is correct with relationship arrays", async () => {
|
it("formula is correct with relationship arrays", async () => {
|
||||||
await expectQuery({}).toContain([{ formula: "option 1,option 2" }])
|
await expectQuery({}).toContain([
|
||||||
|
{ formula: "option 1,option 2" },
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2195,9 +2222,9 @@ describe.each([
|
||||||
|
|
||||||
describe("equal", () => {
|
describe("equal", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ equal: { user: user1._id } }).toContainExactly([
|
await expectQuery({
|
||||||
{ user: { _id: user1._id } },
|
equal: { user: user1._id },
|
||||||
])
|
}).toContainExactly([{ user: { _id: user1._id } }])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
|
@ -2207,33 +2234,41 @@ describe.each([
|
||||||
|
|
||||||
describe("notEqual", () => {
|
describe("notEqual", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ notEqual: { user: user1._id } }).toContainExactly(
|
await expectQuery({
|
||||||
[{ user: { _id: user2._id } }, {}]
|
notEqual: { user: user1._id },
|
||||||
)
|
}).toContainExactly([{ user: { _id: user2._id } }, {}])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
await expectQuery({ notEqual: { user: "us_none" } }).toContainExactly(
|
await expectQuery({
|
||||||
[{ user: { _id: user1._id } }, { user: { _id: user2._id } }, {}]
|
notEqual: { user: "us_none" },
|
||||||
)
|
}).toContainExactly([
|
||||||
|
{ user: { _id: user1._id } },
|
||||||
|
{ user: { _id: user2._id } },
|
||||||
|
{},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("oneOf", () => {
|
describe("oneOf", () => {
|
||||||
it("successfully finds a row", async () => {
|
it("successfully finds a row", async () => {
|
||||||
await expectQuery({ oneOf: { user: [user1._id] } }).toContainExactly([
|
await expectQuery({
|
||||||
{ user: { _id: user1._id } },
|
oneOf: { user: [user1._id] },
|
||||||
])
|
}).toContainExactly([{ user: { _id: user1._id } }])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("fails to find nonexistent row", async () => {
|
it("fails to find nonexistent row", async () => {
|
||||||
await expectQuery({ oneOf: { user: ["us_none"] } }).toFindNothing()
|
await expectQuery({
|
||||||
|
oneOf: { user: ["us_none"] },
|
||||||
|
}).toFindNothing()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("empty", () => {
|
describe("empty", () => {
|
||||||
it("finds empty rows", async () => {
|
it("finds empty rows", async () => {
|
||||||
await expectQuery({ empty: { user: null } }).toContainExactly([{}])
|
await expectQuery({ empty: { user: null } }).toContainExactly([
|
||||||
|
{},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2432,7 +2467,10 @@ describe.each([
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([
|
}).toContainExactly([
|
||||||
{ name: "foo", productCat: [{ _id: productCatRows[0]._id }] },
|
{
|
||||||
|
name: "foo",
|
||||||
|
productCat: [{ _id: productCatRows[0]._id }],
|
||||||
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2531,7 +2569,10 @@ describe.each([
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([
|
}).toContainExactly([
|
||||||
{ name: "foo", productCat: [{ _id: productCatRows[0]._id }] },
|
{
|
||||||
|
name: "foo",
|
||||||
|
productCat: [{ _id: productCatRows[0]._id }],
|
||||||
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2546,8 +2587,14 @@ describe.each([
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([
|
}).toContainExactly([
|
||||||
{ name: "foo", productCat: [{ _id: productCatRows[0]._id }] },
|
{
|
||||||
{ name: "bar", productCat: [{ _id: productCatRows[1]._id }] },
|
name: "foo",
|
||||||
|
productCat: [{ _id: productCatRows[0]._id }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bar",
|
||||||
|
productCat: [{ _id: productCatRows[1]._id }],
|
||||||
|
},
|
||||||
{ name: "baz", productCat: undefined },
|
{ name: "baz", productCat: undefined },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
@ -2627,8 +2674,14 @@ describe.each([
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([
|
}).toContainExactly([
|
||||||
{ name: "foo", productCat: [{ _id: productCatRows[0]._id }] },
|
{
|
||||||
{ name: "bar", productCat: [{ _id: productCatRows[1]._id }] },
|
name: "foo",
|
||||||
|
productCat: [{ _id: productCatRows[0]._id }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bar",
|
||||||
|
productCat: [{ _id: productCatRows[1]._id }],
|
||||||
|
},
|
||||||
{ name: "baz", productCat: undefined },
|
{ name: "baz", productCat: undefined },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
@ -2659,13 +2712,17 @@ describe.each([
|
||||||
|
|
||||||
it("can only pull 10 related rows", async () => {
|
it("can only pull 10 related rows", async () => {
|
||||||
await withCoreEnv({ SQL_MAX_RELATED_ROWS: "10" }, async () => {
|
await withCoreEnv({ SQL_MAX_RELATED_ROWS: "10" }, async () => {
|
||||||
const response = await expectQuery({}).toContain([{ name: "foo" }])
|
const response = await expectQuery({}).toContain([
|
||||||
|
{ name: "foo" },
|
||||||
|
])
|
||||||
expect(response.rows[0].productCat).toBeArrayOfSize(10)
|
expect(response.rows[0].productCat).toBeArrayOfSize(10)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("can pull max rows when env not set (defaults to 500)", async () => {
|
it("can pull max rows when env not set (defaults to 500)", async () => {
|
||||||
const response = await expectQuery({}).toContain([{ name: "foo" }])
|
const response = await expectQuery({}).toContain([
|
||||||
|
{ name: "foo" },
|
||||||
|
])
|
||||||
expect(response.rows[0].productCat).toBeArrayOfSize(11)
|
expect(response.rows[0].productCat).toBeArrayOfSize(11)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -3239,7 +3296,10 @@ describe.each([
|
||||||
it("successfully finds a row for one level condition", async () => {
|
it("successfully finds a row for one level condition", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
$and: {
|
$and: {
|
||||||
conditions: [{ equal: { age: 10 } }, { equal: { name: "Jack" } }],
|
conditions: [
|
||||||
|
{ equal: { age: 10 } },
|
||||||
|
{ equal: { name: "Jack" } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([{ age: 10, name: "Jack" }])
|
}).toContainExactly([{ age: 10, name: "Jack" }])
|
||||||
})
|
})
|
||||||
|
@ -3247,7 +3307,10 @@ describe.each([
|
||||||
it("successfully finds a row for one level with multiple conditions", async () => {
|
it("successfully finds a row for one level with multiple conditions", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
$and: {
|
$and: {
|
||||||
conditions: [{ equal: { age: 10 } }, { equal: { name: "Jack" } }],
|
conditions: [
|
||||||
|
{ equal: { age: 10 } },
|
||||||
|
{ equal: { name: "Jack" } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([{ age: 10, name: "Jack" }])
|
}).toContainExactly([{ age: 10, name: "Jack" }])
|
||||||
})
|
})
|
||||||
|
@ -3289,7 +3352,10 @@ describe.each([
|
||||||
it("returns nothing when filtering out all data", async () => {
|
it("returns nothing when filtering out all data", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
$and: {
|
$and: {
|
||||||
conditions: [{ equal: { age: 7 } }, { equal: { name: "Jack" } }],
|
conditions: [
|
||||||
|
{ equal: { age: 7 } },
|
||||||
|
{ equal: { name: "Jack" } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}).toFindNothing()
|
}).toFindNothing()
|
||||||
})
|
})
|
||||||
|
@ -3299,7 +3365,10 @@ describe.each([
|
||||||
await expect(
|
await expect(
|
||||||
expectQuery({
|
expectQuery({
|
||||||
$and: {
|
$and: {
|
||||||
conditions: [{ equal: { age: 10 } }, "invalidCondition" as any],
|
conditions: [
|
||||||
|
{ equal: { age: 10 } },
|
||||||
|
"invalidCondition" as any,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}).toFindNothing()
|
}).toFindNothing()
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
|
@ -3369,7 +3438,10 @@ describe.each([
|
||||||
it("successfully finds a row for one level condition", async () => {
|
it("successfully finds a row for one level condition", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
$or: {
|
$or: {
|
||||||
conditions: [{ equal: { age: 7 } }, { equal: { name: "Jack" } }],
|
conditions: [
|
||||||
|
{ equal: { age: 7 } },
|
||||||
|
{ equal: { name: "Jack" } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([
|
}).toContainExactly([
|
||||||
{ age: 10, name: "Jack" },
|
{ age: 10, name: "Jack" },
|
||||||
|
@ -3380,7 +3452,10 @@ describe.each([
|
||||||
it("successfully finds a row for one level with multiple conditions", async () => {
|
it("successfully finds a row for one level with multiple conditions", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
$or: {
|
$or: {
|
||||||
conditions: [{ equal: { age: 7 } }, { equal: { name: "Jack" } }],
|
conditions: [
|
||||||
|
{ equal: { age: 7 } },
|
||||||
|
{ equal: { name: "Jack" } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}).toContainExactly([
|
}).toContainExactly([
|
||||||
{ age: 10, name: "Jack" },
|
{ age: 10, name: "Jack" },
|
||||||
|
@ -3430,7 +3505,10 @@ describe.each([
|
||||||
it("returns nothing when filtering out all data", async () => {
|
it("returns nothing when filtering out all data", async () => {
|
||||||
await expectQuery({
|
await expectQuery({
|
||||||
$or: {
|
$or: {
|
||||||
conditions: [{ equal: { age: 6 } }, { equal: { name: "John" } }],
|
conditions: [
|
||||||
|
{ equal: { age: 6 } },
|
||||||
|
{ equal: { name: "John" } },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}).toFindNothing()
|
}).toFindNothing()
|
||||||
})
|
})
|
||||||
|
@ -3567,7 +3645,8 @@ describe.each([
|
||||||
// The SQL that knex generates when you try to use a double quote in a
|
// The SQL that knex generates when you try to use a double quote in a
|
||||||
// field name is always invalid and never works, so we skip it for these
|
// field name is always invalid and never works, so we skip it for these
|
||||||
// tests.
|
// tests.
|
||||||
const skipFieldNameCheck = isOracle && badStringTemplate.includes('"')
|
const skipFieldNameCheck =
|
||||||
|
isOracle && badStringTemplate.includes('"')
|
||||||
|
|
||||||
!skipFieldNameCheck &&
|
!skipFieldNameCheck &&
|
||||||
it("should not allow SQL injection as a field name", async () => {
|
it("should not allow SQL injection as a field name", async () => {
|
||||||
|
@ -3596,7 +3675,9 @@ describe.each([
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
await config.api.row.save(tableOrViewId, { [badString]: "foo" })
|
await config.api.row.save(tableOrViewId, {
|
||||||
|
[badString]: "foo",
|
||||||
|
})
|
||||||
|
|
||||||
await assertTableExists(table)
|
await assertTableExists(table)
|
||||||
await assertTableNumRows(table, 1)
|
await assertTableNumRows(table, 1)
|
||||||
|
@ -3644,4 +3725,6 @@ describe.each([
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
@ -52,6 +52,7 @@ export interface DatasourceDescribeReturn {
|
||||||
dsProvider: Promise<DatasourceDescribeReturnPromise>
|
dsProvider: Promise<DatasourceDescribeReturnPromise>
|
||||||
isInternal: boolean
|
isInternal: boolean
|
||||||
isExternal: boolean
|
isExternal: boolean
|
||||||
|
isSql: boolean
|
||||||
isMySQL: boolean
|
isMySQL: boolean
|
||||||
isPostgres: boolean
|
isPostgres: boolean
|
||||||
isMongodb: boolean
|
isMongodb: boolean
|
||||||
|
@ -118,6 +119,13 @@ export function datasourceDescribe(
|
||||||
dsProvider: createDatasources(config, name),
|
dsProvider: createDatasources(config, name),
|
||||||
isInternal: name === DatabaseName.SQS,
|
isInternal: name === DatabaseName.SQS,
|
||||||
isExternal: name !== DatabaseName.SQS,
|
isExternal: name !== DatabaseName.SQS,
|
||||||
|
isSql: [
|
||||||
|
DatabaseName.MARIADB,
|
||||||
|
DatabaseName.MYSQL,
|
||||||
|
DatabaseName.POSTGRES,
|
||||||
|
DatabaseName.SQL_SERVER,
|
||||||
|
DatabaseName.ORACLE,
|
||||||
|
].includes(name),
|
||||||
isMySQL: name === DatabaseName.MYSQL,
|
isMySQL: name === DatabaseName.MYSQL,
|
||||||
isPostgres: name === DatabaseName.POSTGRES,
|
isPostgres: name === DatabaseName.POSTGRES,
|
||||||
isMongodb: name === DatabaseName.MONGODB,
|
isMongodb: name === DatabaseName.MONGODB,
|
||||||
|
|
Loading…
Reference in New Issue