Making more progress on testing view searching.
This commit is contained in:
parent
b3b7069deb
commit
714029b9a0
|
@ -29,12 +29,18 @@ import {
|
|||
JsonTypes,
|
||||
FilterGroupLogicalOperator,
|
||||
EmptyFilterOption,
|
||||
JsonFieldSubType,
|
||||
SearchFilterGroup,
|
||||
LegacyFilter,
|
||||
SearchViewRowRequest,
|
||||
SearchFilterChild,
|
||||
} from "@budibase/types"
|
||||
import { generator, mocks } from "@budibase/backend-core/tests"
|
||||
import { DatabaseName, getDatasource } from "../../../integrations/tests/utils"
|
||||
import merge from "lodash/merge"
|
||||
import { quotas } from "@budibase/pro"
|
||||
import { db, roles, features } from "@budibase/backend-core"
|
||||
import { single } from "validate.js"
|
||||
|
||||
describe.each([
|
||||
["lucene", undefined],
|
||||
|
@ -3657,6 +3663,148 @@ describe.each([
|
|||
expect(rows).toHaveLength(1)
|
||||
expect(rows[0].user._id).toEqual(config.getUser()._id)
|
||||
})
|
||||
|
||||
describe("search operators", () => {
|
||||
let table: Table
|
||||
beforeEach(async () => {
|
||||
table = await config.api.table.save(
|
||||
saveTableRequest({
|
||||
schema: {
|
||||
string: { name: "string", type: FieldType.STRING },
|
||||
longform: { name: "longform", type: FieldType.LONGFORM },
|
||||
options: {
|
||||
name: "options",
|
||||
type: FieldType.OPTIONS,
|
||||
constraints: { inclusion: ["a", "b", "c"] },
|
||||
},
|
||||
array: {
|
||||
name: "array",
|
||||
type: FieldType.ARRAY,
|
||||
constraints: {
|
||||
type: JsonFieldSubType.ARRAY,
|
||||
inclusion: ["a", "b", "c"],
|
||||
},
|
||||
},
|
||||
number: { name: "number", type: FieldType.NUMBER },
|
||||
bigint: { name: "bigint", type: FieldType.BIGINT },
|
||||
datetime: { name: "datetime", type: FieldType.DATETIME },
|
||||
timeOnly: {
|
||||
name: "timeOnly",
|
||||
type: FieldType.DATETIME,
|
||||
timeOnly: true,
|
||||
},
|
||||
boolean: { name: "boolean", type: FieldType.BOOLEAN },
|
||||
user: {
|
||||
name: "user",
|
||||
type: FieldType.BB_REFERENCE_SINGLE,
|
||||
subtype: BBReferenceFieldSubType.USER,
|
||||
},
|
||||
users: {
|
||||
name: "users",
|
||||
type: FieldType.BB_REFERENCE,
|
||||
subtype: BBReferenceFieldSubType.USER,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
interface TestCase {
|
||||
name: string
|
||||
query: SearchFilterGroup
|
||||
insert: Row[]
|
||||
expected: Row[]
|
||||
searchOpts?: SearchViewRowRequest
|
||||
}
|
||||
|
||||
function defaultQuery(
|
||||
query: Partial<SearchFilterGroup>
|
||||
): SearchFilterGroup {
|
||||
return {
|
||||
onEmptyFilter: EmptyFilterOption.RETURN_ALL,
|
||||
logicalOperator: FilterGroupLogicalOperator.ALL,
|
||||
groups: [],
|
||||
...query,
|
||||
}
|
||||
}
|
||||
|
||||
function defaultGroup(
|
||||
group: Partial<SearchFilterChild>
|
||||
): SearchFilterChild {
|
||||
return {
|
||||
logicalOperator: FilterGroupLogicalOperator.ALL,
|
||||
filters: [],
|
||||
...group,
|
||||
}
|
||||
}
|
||||
|
||||
function simpleQuery(...filters: LegacyFilter[]): SearchFilterGroup {
|
||||
return defaultQuery({ groups: [defaultGroup({ filters })] })
|
||||
}
|
||||
|
||||
const testCases: TestCase[] = [
|
||||
{
|
||||
name: "empty query return all",
|
||||
insert: [{ string: "foo" }],
|
||||
query: defaultQuery({
|
||||
onEmptyFilter: EmptyFilterOption.RETURN_ALL,
|
||||
}),
|
||||
expected: [{ string: "foo" }],
|
||||
},
|
||||
{
|
||||
name: "empty query return none",
|
||||
insert: [{ string: "foo" }],
|
||||
query: defaultQuery({
|
||||
onEmptyFilter: EmptyFilterOption.RETURN_NONE,
|
||||
}),
|
||||
expected: [],
|
||||
},
|
||||
{
|
||||
name: "simple string search",
|
||||
insert: [{ string: "foo" }],
|
||||
query: simpleQuery({
|
||||
operator: BasicOperator.EQUAL,
|
||||
field: "string",
|
||||
value: "foo",
|
||||
}),
|
||||
expected: [{ string: "foo" }],
|
||||
},
|
||||
{
|
||||
name: "non matching string search",
|
||||
insert: [{ string: "foo" }],
|
||||
query: simpleQuery({
|
||||
operator: BasicOperator.EQUAL,
|
||||
field: "string",
|
||||
value: "bar",
|
||||
}),
|
||||
expected: [],
|
||||
},
|
||||
]
|
||||
|
||||
it.only.each(testCases)(
|
||||
"$name",
|
||||
async ({ query, insert, expected, searchOpts }) => {
|
||||
await config.api.row.bulkImport(table._id!, { rows: insert })
|
||||
|
||||
const view = await config.api.viewV2.create({
|
||||
tableId: table._id!,
|
||||
name: generator.guid(),
|
||||
queryUI: query,
|
||||
schema: {
|
||||
string: { visible: true },
|
||||
},
|
||||
})
|
||||
|
||||
const { rows } = await config.api.viewV2.search(
|
||||
view.id,
|
||||
searchOpts
|
||||
)
|
||||
expect(rows).toEqual(
|
||||
expected.map(r => expect.objectContaining(r))
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("permissions", () => {
|
||||
|
|
|
@ -89,9 +89,6 @@ export async function search(
|
|||
options = searchInputMapping(table, options)
|
||||
|
||||
if (options.viewId) {
|
||||
// Delete extraneous search params that cannot be overridden
|
||||
delete options.query.onEmptyFilter
|
||||
|
||||
const view = source as ViewV2
|
||||
// Enrich saved query with ephemeral query params.
|
||||
// We prevent searching on any fields that are saved as part of the query, as
|
||||
|
@ -99,7 +96,6 @@ export async function search(
|
|||
let viewQuery = await enrichSearchContext(view.query || {}, context)
|
||||
viewQuery = dataFilters.buildQueryLegacy(viewQuery) || {}
|
||||
viewQuery = checkFilters(table, viewQuery)
|
||||
delete viewQuery?.onEmptyFilter
|
||||
|
||||
const sqsEnabled = await features.flags.isEnabled("SQS")
|
||||
const supportsLogicalOperators =
|
||||
|
@ -112,8 +108,6 @@ export async function search(
|
|||
? view.query
|
||||
: []
|
||||
|
||||
delete options.query.onEmptyFilter
|
||||
|
||||
// Extract existing fields
|
||||
const existingFields =
|
||||
queryFilters
|
||||
|
|
|
@ -600,7 +600,7 @@ export function buildQuery(
|
|||
|
||||
const globalOperator = operatorMap[parsedFilter.logicalOperator]
|
||||
|
||||
return {
|
||||
const ret = {
|
||||
...(globalOnEmpty ? { onEmptyFilter: globalOnEmpty } : {}),
|
||||
[globalOperator]: {
|
||||
conditions: parsedFilter.groups?.map(group => {
|
||||
|
@ -614,6 +614,8 @@ export function buildQuery(
|
|||
}),
|
||||
},
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// The frontend can send single values for array fields sometimes, so to handle
|
||||
|
|
Loading…
Reference in New Issue