From ba171bb5a229c9e089484ef8926c6a04245bd410 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 11 Apr 2024 11:58:21 +0100 Subject: [PATCH 1/4] Reduce duplication in search.spec.ts --- .../src/api/routes/tests/search.spec.ts | 292 +++++++++--------- 1 file changed, 144 insertions(+), 148 deletions(-) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 3fabbfbef9..5be65553e4 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -6,11 +6,18 @@ import { Datasource, EmptyFilterOption, FieldType, - Row, - SearchFilters, + RowSearchParams, + SortOrder, Table, } from "@budibase/types" +function leftContainsRight< + A extends Record, + B extends Record +>(left: A, right: B) { + return Object.entries(right).every(([k, v]) => left[k] === v) +} + jest.unmock("mssql") describe.each([ @@ -47,10 +54,79 @@ describe.each([ } }) - describe("strings", () => { - beforeAll(async () => { - table = await config.api.table.save( - tableForDatasource(datasource, { + async function testSearch>( + test: SearchTest, + table: Table + ) { + const expected = test.expectToFind + delete test.expectToFind + const { rows: foundRows } = await config.api.row.search(table._id!, { + ...test, + tableId: table._id!, + }) + if (!expected) { + return + } + expect(foundRows).toHaveLength(expected.length) + expect(foundRows).toEqual( + expect.arrayContaining( + expected.map(expectedRow => + expect.objectContaining( + foundRows.find(foundRow => leftContainsRight(foundRow, expectedRow)) + ) + ) + ) + ) + } + + function searchTests>( + name: string, + opts: { + table: (ds?: Datasource) => Promise + rows: T[] + tests: SearchTest[] + } + ) { + let table: Table + + for (const test of opts.tests) { + test.toString = () => { + const queryStr = JSON.stringify({ + query: test.query, + limit: test.limit, + sort: test.sort, + sortOrder: test.sortOrder, + }) + const expectStr = JSON.stringify(test.expectToFind) + return `should run: ${queryStr} and find ${expectStr}` + } + } + + // eslint-disable-next-line jest/valid-title + describe(name, () => { + beforeAll(async () => { + table = await opts.table(datasource) + }) + + beforeAll(async () => { + await Promise.all( + opts.rows.map(r => config.api.row.save(table._id!, r)) + ) + }) + + it.each(opts.tests)(`%s`, test => testSearch(test, table)) + }) + } + + interface SearchTest> + extends Omit { + expectToFind?: RowType[] + } + + searchTests("strings", { + table: async ds => { + return await config.api.table.save( + tableForDatasource(ds, { schema: { name: { name: "name", @@ -59,66 +135,38 @@ describe.each([ }, }) ) - }) + }, + rows: [{ name: "foo" }, { name: "bar" }], + tests: [ + // These test cases are generic and don't really need to be repeated for + // all data types, so we just do them here. - const rows = [{ name: "foo" }, { name: "bar" }] - let savedRows: Row[] - - beforeAll(async () => { - savedRows = await Promise.all( - rows.map(r => config.api.row.save(table._id!, r)) - ) - }) - - interface StringSearchTest { - query: SearchFilters - expected: (typeof rows)[number][] - } - - const stringSearchTests: StringSearchTest[] = [ - // These three test cases are generic and don't really need - // to be repeated for all data types, so we just do them here. - { query: {}, expected: rows }, + // @ts-expect-error - intentionally not passing a query to make sure the + // API can handle it. + { expectToFind: [{ name: "foo" }, { name: "bar" }] }, + { query: {}, expectToFind: [{ name: "foo" }, { name: "bar" }] }, { query: { onEmptyFilter: EmptyFilterOption.RETURN_ALL }, - expected: rows, + expectToFind: [{ name: "foo" }, { name: "bar" }], }, { query: { onEmptyFilter: EmptyFilterOption.RETURN_NONE }, - expected: [], + expectToFind: [], }, // The rest of these tests are specific to strings. - { query: { string: { name: "foo" } }, expected: [rows[0]] }, - { query: { string: { name: "none" } }, expected: [] }, - { query: { fuzzy: { name: "oo" } }, expected: [rows[0]] }, - { query: { equal: { name: "foo" } }, expected: [rows[0]] }, - { query: { notEqual: { name: "foo" } }, expected: [rows[1]] }, - { query: { oneOf: { name: ["foo"] } }, expected: [rows[0]] }, - ] - - it.each(stringSearchTests)( - `should be able to run query: $query`, - async ({ query, expected }) => { - const { rows: foundRows } = await config.api.row.search(table._id!, { - tableId: table._id!, - query, - }) - expect(foundRows).toHaveLength(expected.length) - expect(foundRows).toEqual( - expect.arrayContaining( - expected.map(r => - expect.objectContaining(savedRows.find(sr => sr.name === r.name)!) - ) - ) - ) - } - ) + { query: { string: { name: "foo" } }, expectToFind: [{ name: "foo" }] }, + { query: { string: { name: "none" } }, expectToFind: [] }, + { query: { fuzzy: { name: "oo" } }, expectToFind: [{ name: "foo" }] }, + { query: { equal: { name: "foo" } }, expectToFind: [{ name: "foo" }] }, + { query: { notEqual: { name: "foo" } }, expectToFind: [{ name: "bar" }] }, + { query: { oneOf: { name: ["foo"] } }, expectToFind: [{ name: "foo" }] }, + ], }) - describe("number", () => { - beforeAll(async () => { - table = await config.api.table.save( - tableForDatasource(datasource, { + searchTests("numbers", { + table: async ds => { + return await config.api.table.save( + tableForDatasource(ds, { schema: { age: { name: "age", @@ -127,56 +175,33 @@ describe.each([ }, }) ) - }) - - const rows = [{ age: 1 }, { age: 10 }] - let savedRows: Row[] - - beforeAll(async () => { - savedRows = await Promise.all( - rows.map(r => config.api.row.save(table._id!, r)) - ) - }) - - interface NumberSearchTest { - query: SearchFilters - expected: (typeof rows)[number][] - } - - const numberSearchTests: NumberSearchTest[] = [ - { query: { equal: { age: 1 } }, expected: [rows[0]] }, - { query: { equal: { age: 2 } }, expected: [] }, - { query: { notEqual: { age: 1 } }, expected: [rows[1]] }, - { query: { oneOf: { age: [1] } }, expected: [rows[0]] }, - { query: { range: { age: { low: 1, high: 5 } } }, expected: [rows[0]] }, - { query: { range: { age: { low: 0, high: 1 } } }, expected: [rows[0]] }, - { query: { range: { age: { low: 3, high: 4 } } }, expected: [] }, - { query: { range: { age: { low: 0, high: 11 } } }, expected: rows }, - ] - - it.each(numberSearchTests)( - `should be able to run query: $query`, - async ({ query, expected }) => { - const { rows: foundRows } = await config.api.row.search(table._id!, { - tableId: table._id!, - query, - }) - expect(foundRows).toHaveLength(expected.length) - expect(foundRows).toEqual( - expect.arrayContaining( - expected.map(r => - expect.objectContaining(savedRows.find(sr => sr.age === r.age)!) - ) - ) - ) - } - ) + }, + rows: [{ age: 1 }, { age: 10 }], + tests: [ + { query: { equal: { age: 1 } }, expectToFind: [{ age: 1 }] }, + { query: { equal: { age: 2 } }, expectToFind: [] }, + { query: { notEqual: { age: 1 } }, expectToFind: [{ age: 10 }] }, + { query: { oneOf: { age: [1] } }, expectToFind: [{ age: 1 }] }, + { + query: { range: { age: { low: 1, high: 5 } } }, + expectToFind: [{ age: 1 }], + }, + { + query: { range: { age: { low: 0, high: 1 } } }, + expectToFind: [{ age: 1 }], + }, + { query: { range: { age: { low: 3, high: 4 } } }, expectToFind: [] }, + { + query: { range: { age: { low: 0, high: 11 } } }, + expectToFind: [{ age: 1 }, { age: 10 }], + }, + ], }) - describe("dates", () => { - beforeEach(async () => { - table = await config.api.table.save( - tableForDatasource(datasource, { + searchTests("dates", { + table: async ds => { + return await config.api.table.save( + tableForDatasource(ds, { schema: { dob: { name: "dob", @@ -185,41 +210,27 @@ describe.each([ }, }) ) - }) - - const rows = [ + }, + rows: [ { dob: new Date("2020-01-01").toISOString() }, { dob: new Date("2020-01-10").toISOString() }, - ] - let savedRows: Row[] - - beforeEach(async () => { - savedRows = await Promise.all( - rows.map(r => config.api.row.save(table._id!, r)) - ) - }) - - interface DateSearchTest { - query: SearchFilters - expected: (typeof rows)[number][] - } - - const dateSearchTests: DateSearchTest[] = [ + ], + tests: [ { query: { equal: { dob: new Date("2020-01-01").toISOString() } }, - expected: [rows[0]], + expectToFind: [{ dob: new Date("2020-01-01").toISOString() }], }, { query: { equal: { dob: new Date("2020-01-02").toISOString() } }, - expected: [], + expectToFind: [], }, { query: { notEqual: { dob: new Date("2020-01-01").toISOString() } }, - expected: [rows[1]], + expectToFind: [{ dob: new Date("2020-01-10").toISOString() }], }, { query: { oneOf: { dob: [new Date("2020-01-01").toISOString()] } }, - expected: [rows[0]], + expectToFind: [{ dob: new Date("2020-01-01").toISOString() }], }, { query: { @@ -230,7 +241,7 @@ describe.each([ }, }, }, - expected: [rows[0]], + expectToFind: [{ dob: new Date("2020-01-01").toISOString() }], }, { query: { @@ -241,7 +252,10 @@ describe.each([ }, }, }, - expected: rows, + expectToFind: [ + { dob: new Date("2020-01-01").toISOString() }, + { dob: new Date("2020-01-10").toISOString() }, + ], }, { query: { @@ -252,26 +266,8 @@ describe.each([ }, }, }, - expected: [rows[1]], + expectToFind: [{ dob: new Date("2020-01-10").toISOString() }], }, - ] - - it.each(dateSearchTests)( - `should be able to run query: $query`, - async ({ query, expected }) => { - const { rows: foundRows } = await config.api.row.search(table._id!, { - tableId: table._id!, - query, - }) - expect(foundRows).toHaveLength(expected.length) - expect(foundRows).toEqual( - expect.arrayContaining( - expected.map(r => - expect.objectContaining(savedRows.find(sr => sr.dob === r.dob)!) - ) - ) - ) - } - ) + ], }) }) From 0d564a8b4cd025415b4e0f8ca25c409f81e0d373 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 11 Apr 2024 11:58:49 +0100 Subject: [PATCH 2/4] Remove unused variables. --- packages/server/src/api/routes/tests/search.spec.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 5be65553e4..79399a9272 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -7,7 +7,6 @@ import { EmptyFilterOption, FieldType, RowSearchParams, - SortOrder, Table, } from "@budibase/types" @@ -32,7 +31,6 @@ describe.each([ const config = setup.getConfig() let envCleanup: (() => void) | undefined - let table: Table let datasource: Datasource | undefined beforeAll(async () => { From eb56140ce25e7ad7cb36bbb301c0c8dae03d0e2a Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 11 Apr 2024 12:03:34 +0100 Subject: [PATCH 3/4] Convert dates to strings, looks nicer and makes no difference. --- .../src/api/routes/tests/search.spec.ts | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index 79399a9272..a99df1a744 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -210,61 +210,61 @@ describe.each([ ) }, rows: [ - { dob: new Date("2020-01-01").toISOString() }, - { dob: new Date("2020-01-10").toISOString() }, + { dob: "2020-01-01T00:00:00.000Z" }, + { dob: "2020-01-10T00:00:00.000Z" }, ], tests: [ { - query: { equal: { dob: new Date("2020-01-01").toISOString() } }, - expectToFind: [{ dob: new Date("2020-01-01").toISOString() }], + query: { equal: { dob: "2020-01-01T00:00:00.000Z" } }, + expectToFind: [{ dob: "2020-01-01T00:00:00.000Z" }], }, { - query: { equal: { dob: new Date("2020-01-02").toISOString() } }, + query: { equal: { dob: "2020-01-02T00:00:00.000Z" } }, expectToFind: [], }, { - query: { notEqual: { dob: new Date("2020-01-01").toISOString() } }, - expectToFind: [{ dob: new Date("2020-01-10").toISOString() }], + query: { notEqual: { dob: "2020-01-01T00:00:00.000Z" } }, + expectToFind: [{ dob: "2020-01-10T00:00:00.000Z" }], }, { - query: { oneOf: { dob: [new Date("2020-01-01").toISOString()] } }, - expectToFind: [{ dob: new Date("2020-01-01").toISOString() }], + query: { oneOf: { dob: ["2020-01-01T00:00:00.000Z"] } }, + expectToFind: [{ dob: "2020-01-01T00:00:00.000Z" }], }, { query: { range: { dob: { - low: new Date("2020-01-01").toISOString(), - high: new Date("2020-01-05").toISOString(), + low: "2020-01-01T00:00:00.000Z", + high: "2020-01-05T00:00:00.000Z", }, }, }, - expectToFind: [{ dob: new Date("2020-01-01").toISOString() }], + expectToFind: [{ dob: "2020-01-01T00:00:00.000Z" }], }, { query: { range: { dob: { - low: new Date("2020-01-01").toISOString(), - high: new Date("2020-01-10").toISOString(), + low: "2020-01-01T00:00:00.000Z", + high: "2020-01-10T00:00:00.000Z", }, }, }, expectToFind: [ - { dob: new Date("2020-01-01").toISOString() }, - { dob: new Date("2020-01-10").toISOString() }, + { dob: "2020-01-01T00:00:00.000Z" }, + { dob: "2020-01-10T00:00:00.000Z" }, ], }, { query: { range: { dob: { - low: new Date("2020-01-05").toISOString(), - high: new Date("2020-01-10").toISOString(), + low: "2020-01-05T00:00:00.000Z", + high: "2020-01-10T00:00:00.000Z", }, }, }, - expectToFind: [{ dob: new Date("2020-01-10").toISOString() }], + expectToFind: [{ dob: "2020-01-10T00:00:00.000Z" }], }, ], }) From c07882b4526899912ec31787e496c1c06fc03872 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 11 Apr 2024 15:16:26 +0100 Subject: [PATCH 4/4] Restructure search.spec.ts to be much more readable. --- .../src/api/routes/tests/search.spec.ts | 406 +++++++++--------- 1 file changed, 200 insertions(+), 206 deletions(-) diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index a99df1a744..fdf1ed7603 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -7,15 +7,11 @@ import { EmptyFilterOption, FieldType, RowSearchParams, + SearchFilters, Table, + TableSchema, } from "@budibase/types" - -function leftContainsRight< - A extends Record, - B extends Record ->(left: A, right: B) { - return Object.entries(right).every(([k, v]) => left[k] === v) -} +import _ from "lodash" jest.unmock("mssql") @@ -32,6 +28,7 @@ describe.each([ let envCleanup: (() => void) | undefined let datasource: Datasource | undefined + let table: Table beforeAll(async () => { if (isSqs) { @@ -52,220 +49,217 @@ describe.each([ } }) - async function testSearch>( - test: SearchTest, - table: Table - ) { - const expected = test.expectToFind - delete test.expectToFind - const { rows: foundRows } = await config.api.row.search(table._id!, { - ...test, - tableId: table._id!, - }) - if (!expected) { - return - } - expect(foundRows).toHaveLength(expected.length) - expect(foundRows).toEqual( - expect.arrayContaining( - expected.map(expectedRow => - expect.objectContaining( - foundRows.find(foundRow => leftContainsRight(foundRow, expectedRow)) - ) - ) - ) + async function createTable(schema: TableSchema) { + table = await config.api.table.save( + tableForDatasource(datasource, { schema }) ) } - function searchTests>( - name: string, - opts: { - table: (ds?: Datasource) => Promise
- rows: T[] - tests: SearchTest[] - } - ) { - let table: Table + async function createRows(rows: Record[]) { + await Promise.all(rows.map(r => config.api.row.save(table._id!, r))) + } - for (const test of opts.tests) { - test.toString = () => { - const queryStr = JSON.stringify({ - query: test.query, - limit: test.limit, - sort: test.sort, - sortOrder: test.sortOrder, - }) - const expectStr = JSON.stringify(test.expectToFind) - return `should run: ${queryStr} and find ${expectStr}` - } - } + class SearchAssertion { + constructor(private readonly query: RowSearchParams) {} - // eslint-disable-next-line jest/valid-title - describe(name, () => { - beforeAll(async () => { - table = await opts.table(datasource) + async toFind(expectedRows: any[]) { + const { rows: foundRows } = await config.api.row.search(table._id!, { + ...this.query, + tableId: table._id!, }) - beforeAll(async () => { - await Promise.all( - opts.rows.map(r => config.api.row.save(table._id!, r)) + // eslint-disable-next-line jest/no-standalone-expect + expect(foundRows).toHaveLength(expectedRows.length) + // eslint-disable-next-line jest/no-standalone-expect + expect(foundRows).toEqual( + expect.arrayContaining( + expectedRows.map((expectedRow: any) => + expect.objectContaining( + foundRows.find(foundRow => _.isMatch(foundRow, expectedRow)) + ) + ) ) + ) + } + + async toFindNothing() { + await this.toFind([]) + } + } + + function expectSearch(query: Omit) { + return new SearchAssertion({ ...query, tableId: table._id! }) + } + + function expectQuery(query: SearchFilters) { + return expectSearch({ query }) + } + + describe("strings", () => { + beforeAll(async () => { + await createTable({ + name: { name: "name", type: FieldType.STRING }, + }) + await createRows([{ name: "foo" }, { name: "bar" }]) + }) + + describe("misc", () => { + it("should return all if no query is passed", () => + expectSearch({} as RowSearchParams).toFind([ + { name: "foo" }, + { name: "bar" }, + ])) + + it("should return all if empty query is passed", () => + expectQuery({}).toFind([{ name: "foo" }, { name: "bar" }])) + + it("should return all if onEmptyFilter is RETURN_ALL", () => + expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + }).toFind([{ name: "foo" }, { name: "bar" }])) + + it("should return nothing if onEmptyFilter is RETURN_NONE", () => + expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + }).toFindNothing()) + }) + + describe("equal", () => { + it("successfully finds a row", () => + expectQuery({ equal: { name: "foo" } }).toFind([{ name: "foo" }])) + + it("fails to find nonexistent row", () => + expectQuery({ equal: { name: "none" } }).toFindNothing()) + }) + + describe("notEqual", () => { + it("successfully finds a row", () => + expectQuery({ notEqual: { name: "foo" } }).toFind([{ name: "bar" }])) + + it("fails to find nonexistent row", () => + expectQuery({ notEqual: { name: "bar" } }).toFind([{ name: "foo" }])) + }) + + describe("oneOf", () => { + it("successfully finds a row", () => + expectQuery({ oneOf: { name: ["foo"] } }).toFind([{ name: "foo" }])) + + it("fails to find nonexistent row", () => + expectQuery({ oneOf: { name: ["none"] } }).toFindNothing()) + }) + + describe("fuzzy", () => { + it("successfully finds a row", () => + expectQuery({ fuzzy: { name: "oo" } }).toFind([{ name: "foo" }])) + + it("fails to find nonexistent row", () => + expectQuery({ fuzzy: { name: "none" } }).toFindNothing()) + }) + }) + + describe("numbers", () => { + beforeAll(async () => { + await createTable({ + age: { name: "age", type: FieldType.NUMBER }, + }) + await createRows([{ age: 1 }, { age: 10 }]) + }) + + describe("equal", () => { + it("successfully finds a row", () => + expectQuery({ equal: { age: 1 } }).toFind([{ age: 1 }])) + + it("fails to find nonexistent row", () => + expectQuery({ equal: { age: 2 } }).toFindNothing()) + }) + + describe("notEqual", () => { + it("successfully finds a row", () => + expectQuery({ notEqual: { age: 1 } }).toFind([{ age: 10 }])) + + it("fails to find nonexistent row", () => + expectQuery({ notEqual: { age: 10 } }).toFind([{ age: 1 }])) + }) + + describe("oneOf", () => { + it("successfully finds a row", () => + expectQuery({ oneOf: { age: [1] } }).toFind([{ age: 1 }])) + + it("fails to find nonexistent row", () => + expectQuery({ oneOf: { age: [2] } }).toFindNothing()) + }) + + describe("range", () => { + it("successfully finds a row", () => + expectQuery({ + range: { age: { low: 1, high: 5 } }, + }).toFind([{ age: 1 }])) + + it("successfully finds multiple rows", () => + expectQuery({ + range: { age: { low: 1, high: 10 } }, + }).toFind([{ age: 1 }, { age: 10 }])) + + it("successfully finds a row with a high bound", () => + expectQuery({ + range: { age: { low: 5, high: 10 } }, + }).toFind([{ age: 10 }])) + }) + }) + + describe("dates", () => { + const JAN_1ST = "2020-01-01T00:00:00.000Z" + const JAN_2ND = "2020-01-02T00:00:00.000Z" + const JAN_5TH = "2020-01-05T00:00:00.000Z" + const JAN_10TH = "2020-01-10T00:00:00.000Z" + + beforeAll(async () => { + await createTable({ + dob: { name: "dob", type: FieldType.DATETIME }, }) - it.each(opts.tests)(`%s`, test => testSearch(test, table)) + await createRows([{ dob: JAN_1ST }, { dob: JAN_10TH }]) }) - } - interface SearchTest> - extends Omit { - expectToFind?: RowType[] - } + describe("equal", () => { + it("successfully finds a row", () => + expectQuery({ equal: { dob: JAN_1ST } }).toFind([{ dob: JAN_1ST }])) - searchTests("strings", { - table: async ds => { - return await config.api.table.save( - tableForDatasource(ds, { - schema: { - name: { - name: "name", - type: FieldType.STRING, - }, - }, - }) - ) - }, - rows: [{ name: "foo" }, { name: "bar" }], - tests: [ - // These test cases are generic and don't really need to be repeated for - // all data types, so we just do them here. + it("fails to find nonexistent row", () => + expectQuery({ equal: { dob: JAN_2ND } }).toFindNothing()) + }) - // @ts-expect-error - intentionally not passing a query to make sure the - // API can handle it. - { expectToFind: [{ name: "foo" }, { name: "bar" }] }, - { query: {}, expectToFind: [{ name: "foo" }, { name: "bar" }] }, - { - query: { onEmptyFilter: EmptyFilterOption.RETURN_ALL }, - expectToFind: [{ name: "foo" }, { name: "bar" }], - }, - { - query: { onEmptyFilter: EmptyFilterOption.RETURN_NONE }, - expectToFind: [], - }, - // The rest of these tests are specific to strings. - { query: { string: { name: "foo" } }, expectToFind: [{ name: "foo" }] }, - { query: { string: { name: "none" } }, expectToFind: [] }, - { query: { fuzzy: { name: "oo" } }, expectToFind: [{ name: "foo" }] }, - { query: { equal: { name: "foo" } }, expectToFind: [{ name: "foo" }] }, - { query: { notEqual: { name: "foo" } }, expectToFind: [{ name: "bar" }] }, - { query: { oneOf: { name: ["foo"] } }, expectToFind: [{ name: "foo" }] }, - ], - }) + describe("notEqual", () => { + it("successfully finds a row", () => + expectQuery({ notEqual: { dob: JAN_1ST } }).toFind([{ dob: JAN_10TH }])) - searchTests("numbers", { - table: async ds => { - return await config.api.table.save( - tableForDatasource(ds, { - schema: { - age: { - name: "age", - type: FieldType.NUMBER, - }, - }, - }) - ) - }, - rows: [{ age: 1 }, { age: 10 }], - tests: [ - { query: { equal: { age: 1 } }, expectToFind: [{ age: 1 }] }, - { query: { equal: { age: 2 } }, expectToFind: [] }, - { query: { notEqual: { age: 1 } }, expectToFind: [{ age: 10 }] }, - { query: { oneOf: { age: [1] } }, expectToFind: [{ age: 1 }] }, - { - query: { range: { age: { low: 1, high: 5 } } }, - expectToFind: [{ age: 1 }], - }, - { - query: { range: { age: { low: 0, high: 1 } } }, - expectToFind: [{ age: 1 }], - }, - { query: { range: { age: { low: 3, high: 4 } } }, expectToFind: [] }, - { - query: { range: { age: { low: 0, high: 11 } } }, - expectToFind: [{ age: 1 }, { age: 10 }], - }, - ], - }) + it("fails to find nonexistent row", () => + expectQuery({ notEqual: { dob: JAN_10TH } }).toFind([{ dob: JAN_1ST }])) + }) - searchTests("dates", { - table: async ds => { - return await config.api.table.save( - tableForDatasource(ds, { - schema: { - dob: { - name: "dob", - type: FieldType.DATETIME, - }, - }, - }) - ) - }, - rows: [ - { dob: "2020-01-01T00:00:00.000Z" }, - { dob: "2020-01-10T00:00:00.000Z" }, - ], - tests: [ - { - query: { equal: { dob: "2020-01-01T00:00:00.000Z" } }, - expectToFind: [{ dob: "2020-01-01T00:00:00.000Z" }], - }, - { - query: { equal: { dob: "2020-01-02T00:00:00.000Z" } }, - expectToFind: [], - }, - { - query: { notEqual: { dob: "2020-01-01T00:00:00.000Z" } }, - expectToFind: [{ dob: "2020-01-10T00:00:00.000Z" }], - }, - { - query: { oneOf: { dob: ["2020-01-01T00:00:00.000Z"] } }, - expectToFind: [{ dob: "2020-01-01T00:00:00.000Z" }], - }, - { - query: { - range: { - dob: { - low: "2020-01-01T00:00:00.000Z", - high: "2020-01-05T00:00:00.000Z", - }, - }, - }, - expectToFind: [{ dob: "2020-01-01T00:00:00.000Z" }], - }, - { - query: { - range: { - dob: { - low: "2020-01-01T00:00:00.000Z", - high: "2020-01-10T00:00:00.000Z", - }, - }, - }, - expectToFind: [ - { dob: "2020-01-01T00:00:00.000Z" }, - { dob: "2020-01-10T00:00:00.000Z" }, - ], - }, - { - query: { - range: { - dob: { - low: "2020-01-05T00:00:00.000Z", - high: "2020-01-10T00:00:00.000Z", - }, - }, - }, - expectToFind: [{ dob: "2020-01-10T00:00:00.000Z" }], - }, - ], + describe("oneOf", () => { + it("successfully finds a row", () => + expectQuery({ oneOf: { dob: [JAN_1ST] } }).toFind([{ dob: JAN_1ST }])) + + it("fails to find nonexistent row", () => + expectQuery({ oneOf: { dob: [JAN_2ND] } }).toFindNothing()) + }) + + describe("range", () => { + it("successfully finds a row", () => + expectQuery({ + range: { dob: { low: JAN_1ST, high: JAN_5TH } }, + }).toFind([{ dob: JAN_1ST }])) + + it("successfully finds multiple rows", () => + expectQuery({ + range: { dob: { low: JAN_1ST, high: JAN_10TH } }, + }).toFind([{ dob: JAN_1ST }, { dob: JAN_10TH }])) + + it("successfully finds a row with a high bound", () => + expectQuery({ + range: { dob: { low: JAN_5TH, high: JAN_10TH } }, + }).toFind([{ dob: JAN_10TH }])) + }) }) })