Merge remote-tracking branch 'origin/master' into feature/automation-row-ux-update

This commit is contained in:
Dean 2024-07-01 14:15:24 +01:00
commit dd4519067e
4 changed files with 46 additions and 3 deletions

View File

@ -1,5 +1,5 @@
{ {
"version": "2.29.4", "version": "2.29.5",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*", "packages/*",

View File

@ -1938,6 +1938,17 @@ describe.each([
]) ])
}) })
it("successfully finds a row searching with a string", async () => {
await expectQuery({
// @ts-expect-error this test specifically goes against the type to
// test that we coerce the string to an array.
contains: { "1:users": user1._id },
}).toContainExactly([
{ users: [{ _id: user1._id }] },
{ users: [{ _id: user1._id }, { _id: user2._id }] },
])
})
it("fails to find nonexistent row", async () => { it("fails to find nonexistent row", async () => {
await expectQuery({ contains: { users: ["us_none"] } }).toFindNothing() await expectQuery({ contains: { users: ["us_none"] } }).toFindNothing()
}) })

View File

@ -91,8 +91,13 @@ describe("jsRunner (using isolated-vm)", () => {
}) })
it("handle test case 2", async () => { it("handle test case 2", async () => {
const todayDate = new Date()
// add a year and a month
todayDate.setMonth(new Date().getMonth() + 1)
todayDate.setFullYear(todayDate.getFullYear() + 1)
const context = { const context = {
"Purchase Date": DATE, "Purchase Date": DATE,
today: todayDate.toISOString(),
} }
const result = await processJS( const result = await processJS(
` `
@ -100,7 +105,7 @@ describe("jsRunner (using isolated-vm)", () => {
let purchaseyear = purchase.getFullYear(); let purchaseyear = purchase.getFullYear();
let purchasemonth = purchase.getMonth(); let purchasemonth = purchase.getMonth();
var today = new Date (); var today = new Date($("today"));
let todayyear = today.getFullYear(); let todayyear = today.getFullYear();
let todaymonth = today.getMonth(); let todaymonth = today.getMonth();
@ -113,7 +118,7 @@ describe("jsRunner (using isolated-vm)", () => {
context context
) )
expect(result).toBeDefined() expect(result).toBeDefined()
expect(result).toBe(3) expect(result).toBe(1)
}) })
it("should handle test case 3", async () => { it("should handle test case 3", async () => {

View File

@ -2,6 +2,7 @@ import {
EmptyFilterOption, EmptyFilterOption,
Row, Row,
RowSearchParams, RowSearchParams,
SearchFilterOperator,
SearchFilters, SearchFilters,
SearchResponse, SearchResponse,
SortOrder, SortOrder,
@ -65,11 +66,37 @@ export function removeEmptyFilters(filters: SearchFilters) {
return filters return filters
} }
// The frontend can send single values for array fields sometimes, so to handle
// this we convert them to arrays at the controller level so that nothing below
// this has to worry about the non-array values.
function fixupFilterArrays(filters: SearchFilters) {
const arrayFields = [
SearchFilterOperator.ONE_OF,
SearchFilterOperator.CONTAINS,
SearchFilterOperator.NOT_CONTAINS,
SearchFilterOperator.CONTAINS_ANY,
]
for (const searchField of arrayFields) {
const field = filters[searchField]
if (field == null) {
continue
}
for (const key of Object.keys(field)) {
if (!Array.isArray(field[key])) {
field[key] = [field[key]]
}
}
}
return filters
}
export async function search( export async function search(
options: RowSearchParams options: RowSearchParams
): Promise<SearchResponse<Row>> { ): Promise<SearchResponse<Row>> {
const isExternalTable = isExternalTableID(options.tableId) const isExternalTable = isExternalTableID(options.tableId)
options.query = removeEmptyFilters(options.query || {}) options.query = removeEmptyFilters(options.query || {})
options.query = fixupFilterArrays(options.query)
if ( if (
!dataFilters.hasFilters(options.query) && !dataFilters.hasFilters(options.query) &&
options.query.onEmptyFilter === EmptyFilterOption.RETURN_NONE options.query.onEmptyFilter === EmptyFilterOption.RETURN_NONE