diff --git a/packages/nocodb/tests/unit/factory/row.ts b/packages/nocodb/tests/unit/factory/row.ts index 484fc60b24..7ed81a64b4 100644 --- a/packages/nocodb/tests/unit/factory/row.ts +++ b/packages/nocodb/tests/unit/factory/row.ts @@ -61,7 +61,22 @@ const rowMixedValue = (column: ColumnType, index: number) => { ]; // Array of random integers, not more than 10000 - const numbers = [33, 456, 54, 267, 34, 8754, 3234, 44, 33, null]; + const numbers = [33, null, 456, 333, 267, 34, 8754, 3234, 44, 33, null]; + const decimals = [ + 33.3, + 456.34, + 333.3, + null, + 267.5674, + 34.0, + 8754.0, + 3234.547, + 44.2647, + 33.98, + null, + ]; + const duration = [10, 20, 30, 40, 50, 60, null, 70, 80, 90, null]; + const rating = [0, 1, 2, 3, null, 0, 4, 5, 0, 1, null]; // Array of random sample email strings (not more than 100 characters) const emails = [ @@ -115,7 +130,15 @@ const rowMixedValue = (column: ColumnType, index: number) => { switch (column.uidt) { case UITypes.Number: + case UITypes.Percent: return numbers[index % numbers.length]; + case UITypes.Decimal: + case UITypes.Currency: + return decimals[index % decimals.length]; + case UITypes.Duration: + return duration[index % duration.length]; + case UITypes.Rating: + return rating[index % rating.length]; case UITypes.SingleLineText: return countries[index % countries.length]; case UITypes.Email: diff --git a/packages/nocodb/tests/unit/rest/tests/filter.test.ts b/packages/nocodb/tests/unit/rest/tests/filter.test.ts index dc89848231..3d2fd52d65 100644 --- a/packages/nocodb/tests/unit/rest/tests/filter.test.ts +++ b/packages/nocodb/tests/unit/rest/tests/filter.test.ts @@ -16,14 +16,66 @@ import Model from '../../../../src/lib/models/Model'; import { expect } from 'chai'; import request from 'supertest'; +const debugMode = true; + // Test case list -function filterTests() { - let context; - let project: Project; - let table: Model; - let columns: any[]; - let unfilteredRecords: any[] = []; +async function retrieveRecordsAndValidate( + filter: { + comparison_op: string; + value: string; + fk_column_id: any; + status: string; + logical_op: string; + }, + expectedRecords: any[], + title: string +) { + // retrieve filtered records + const response = await request(context.app) + .get(`/api/v1/db/data/noco/${project.id}/${table.id}`) + .set('xc-auth', context.token) + .query({ + filterArrJson: JSON.stringify([filter]), + }) + .expect(200); + + // validate + if (debugMode) { + if (response.body.pageInfo.totalRows !== expectedRecords.length) { + console.log(`Failed for filter: ${JSON.stringify(filter)}`); + console.log(`Expected: ${expectedRecords.length}`); + console.log(`Actual: ${response.body.pageInfo.totalRows}`); + throw new Error('fix me!'); + } + response.body.list.forEach((row, index) => { + if (row[title] !== expectedRecords[index][title]) { + console.log(`Failed for filter: ${JSON.stringify(filter)}`); + console.log(`Expected: ${expectedRecords[index][title]}`); + console.log(`Actual: ${row[title]}`); + throw new Error('fix me!'); + } + }); + } else { + expect(response.body.pageInfo.totalRows).to.equal(expectedRecords.length); + response.body.list.forEach((row, index) => { + expect(row[title] !== expectedRecords[index][title]); + }); + } +} + +let context; +let project: Project; +let table: Model; +let columns: any[]; +let unfilteredRecords: any[] = []; + +function filterTextBased() { + // let context; + // let project: Project; + // let table: Model; + // let columns: any[]; + // let unfilteredRecords: any[] = []; // prepare data for test cases beforeEach(async function () { @@ -91,36 +143,55 @@ function filterTests() { expect(unfilteredRecords.length).to.equal(400); }); - async function retrieveRecordsAndValidate( - filter: { - comparison_op: string; - value: string; - fk_column_id: any; - status: string; - logical_op: string; - }, - expectedRecords: any[] - ) { - // retrieve filtered records - const response = await request(context.app) - .get(`/api/v1/db/data/noco/${project.id}/${table.id}`) - .set('xc-auth', context.token) - .query({ - filterArrJson: JSON.stringify([filter]), - }) - .expect(200); - - // validate - expect(response.body.pageInfo.totalRows).to.equal(expectedRecords.length); - response.body.list.forEach((row, index) => { - expect(row[columns[1].title] !== expectedRecords[index].SingleLineText); - }); - } + // async function retrieveRecordsAndValidate( + // filter: { + // comparison_op: string; + // value: string; + // fk_column_id: any; + // status: string; + // logical_op: string; + // }, + // expectedRecords: any[] + // ) { + // // retrieve filtered records + // const response = await request(context.app) + // .get(`/api/v1/db/data/noco/${project.id}/${table.id}`) + // .set('xc-auth', context.token) + // .query({ + // filterArrJson: JSON.stringify([filter]), + // }) + // .expect(200); + // + // // validate + // if (debugMode) { + // if (response.body.pageInfo.totalRows !== expectedRecords.length) { + // console.log(`Failed for filter: ${JSON.stringify(filter)}`); + // console.log(`Expected: ${expectedRecords.length}`); + // console.log(`Actual: ${response.body.pageInfo.totalRows}`); + // throw new Error('fix me!'); + // } + // response.body.list.forEach((row, index) => { + // if (row[columns[1].title] !== expectedRecords[index].SingleLineText) { + // console.log(`Failed for filter: ${JSON.stringify(filter)}`); + // console.log(`Expected: ${expectedRecords[index].SingleLineText}`); + // console.log(`Actual: ${row[columns[1].title]}`); + // throw new Error('fix me!'); + // } + // }); + // } else { + // expect(response.body.pageInfo.totalRows).to.equal(expectedRecords.length); + // response.body.list.forEach((row, index) => { + // expect(row[columns[1].title] !== expectedRecords[index].SingleLineText); + // }); + // } + // } it('Type: Single Line Text', async () => { // filter types to be verified // eq, neq, null, notnull, empty, notempty, like, nlike + const dataType = 'SingleLineText'; + const filter = { fk_column_id: columns[1].id, status: 'create', @@ -130,63 +201,780 @@ function filterTests() { }; let expectedRecords = unfilteredRecords.filter( - (record) => record.SingleLineText === 'Afghanistan' + (record) => record[dataType] === 'Afghanistan' ); - await retrieveRecordsAndValidate(filter, expectedRecords); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); // filter: neq filter.comparison_op = 'neq'; expectedRecords = unfilteredRecords.filter( - (record) => record.SingleLineText !== 'Afghanistan' + (record) => record[dataType] !== 'Afghanistan' ); - await retrieveRecordsAndValidate(filter, expectedRecords); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); // filter: null filter.comparison_op = 'null'; expectedRecords = unfilteredRecords.filter( - (record) => record.SingleLineText === null + (record) => record[dataType] === null ); - await retrieveRecordsAndValidate(filter, expectedRecords); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); // filter: notnull filter.comparison_op = 'notnull'; expectedRecords = unfilteredRecords.filter( - (record) => record.SingleLineText !== null + (record) => record[dataType] !== null ); - await retrieveRecordsAndValidate(filter, expectedRecords); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); // filter: empty filter.comparison_op = 'empty'; expectedRecords = unfilteredRecords.filter( - (record) => record.SingleLineText === '' + (record) => record[dataType] === '' ); - await retrieveRecordsAndValidate(filter, expectedRecords); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); // filter: notempty filter.comparison_op = 'notempty'; expectedRecords = unfilteredRecords.filter( - (record) => record.SingleLineText !== '' + (record) => record[dataType] !== '' ); - //TBD await retrieveRecordsAndValidate(filter, expectedRecords); + //TBD await retrieveRecordsAndValidate(filter, expectedRecords, dataType); // filter: like filter.comparison_op = 'like'; filter.value = 'Au'; expectedRecords = unfilteredRecords.filter((record) => - record.SingleLineText?.includes('Au') + record[dataType]?.includes('Au') ); - await retrieveRecordsAndValidate(filter, expectedRecords); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); // filter: nlike filter.comparison_op = 'nlike'; filter.value = 'Au'; expectedRecords = unfilteredRecords.filter( - (record) => !record.SingleLineText?.includes('Au') + (record) => !record[dataType]?.includes('Au') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: LongText', async () => { + // filter types to be verified + // eq, neq, null, notnull, empty, notempty, like, nlike + + const dataType = 'MultiLineText'; + + const filter = { + fk_column_id: columns[2].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: 'Aberdeen, United Kingdom', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === 'Aberdeen, United Kingdom' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== 'Aberdeen, United Kingdom' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: empty + filter.comparison_op = 'empty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === '' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notempty + filter.comparison_op = 'notempty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== '' + ); + //TBD await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: like + filter.comparison_op = 'like'; + filter.value = 'abad'; + expectedRecords = unfilteredRecords.filter((record) => + record[dataType]?.includes('abad') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: nlike + filter.comparison_op = 'nlike'; + filter.value = 'abad'; + expectedRecords = unfilteredRecords.filter( + (record) => !record[dataType]?.includes('abad') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: Email', async () => { + // filter types to be verified + // eq, neq, null, notnull, empty, notempty, like, nlike + + const dataType = 'Email'; + + const filter = { + fk_column_id: columns[3].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: 'leota@hotmail.com', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === 'leota@hotmail.com' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== 'leota@hotmail.com' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: empty + filter.comparison_op = 'empty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === '' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notempty + filter.comparison_op = 'notempty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== '' + ); + //TBD await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: like + filter.comparison_op = 'like'; + filter.value = 'cox.net'; + expectedRecords = unfilteredRecords.filter((record) => + record[dataType]?.includes('cox.net') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: nlike + filter.comparison_op = 'nlike'; + filter.value = 'cox.net'; + expectedRecords = unfilteredRecords.filter( + (record) => !record[dataType]?.includes('cox.net') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: Phone', async () => { + // filter types to be verified + // eq, neq, null, notnull, empty, notempty, like, nlike + + const dataType = 'Phone'; + + const filter = { + fk_column_id: columns[4].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: '504-621-8927', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === '504-621-8927' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== '504-621-8927' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: empty + filter.comparison_op = 'empty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === '' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notempty + filter.comparison_op = 'notempty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== '' + ); + //TBD await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: like + filter.comparison_op = 'like'; + filter.value = '504'; + expectedRecords = unfilteredRecords.filter((record) => + record[dataType]?.includes('504') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: nlike + filter.comparison_op = 'nlike'; + filter.value = '504'; + expectedRecords = unfilteredRecords.filter( + (record) => !record[dataType]?.includes('504') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: URL', async () => { + // filter types to be verified + // eq, neq, null, notnull, empty, notempty, like, nlike + + const dataType = 'Url'; + + const filter = { + fk_column_id: columns[5].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: 'https://www.youtube.com', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === 'https://www.youtube.com' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== 'https://www.youtube.com' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: empty + filter.comparison_op = 'empty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === '' + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notempty + filter.comparison_op = 'notempty'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== '' + ); + //TBD await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: like + filter.comparison_op = 'like'; + filter.value = 'e.com'; + expectedRecords = unfilteredRecords.filter((record) => + record[dataType]?.includes('e.com') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: nlike + filter.comparison_op = 'nlike'; + filter.value = 'e.com'; + expectedRecords = unfilteredRecords.filter( + (record) => !record[dataType]?.includes('e.com') + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); +} + +function filterNumberBased() { + // prepare data for test cases + beforeEach(async function () { + context = await init(); + project = await createProject(context); + table = await createTable(context, project, { + table_name: 'numberBased', + title: 'numberBased', + columns: [ + { + column_name: 'Id', + title: 'Id', + uidt: UITypes.ID, + }, + { + column_name: 'Number', + title: 'Number', + uidt: UITypes.Number, + }, + { + column_name: 'Decimal', + title: 'Decimal', + uidt: UITypes.Decimal, + }, + { + column_name: 'Currency', + title: 'Currency', + uidt: UITypes.Currency, + }, + { + column_name: 'Percent', + title: 'Percent', + uidt: UITypes.Percent, + }, + { + column_name: 'Duration', + title: 'Duration', + uidt: UITypes.Duration, + }, + { + column_name: 'Rating', + title: 'Rating', + uidt: UITypes.Rating, + }, + ], + }); + + columns = await table.getColumns(); + + let rowAttributes = []; + for (let i = 0; i < 400; i++) { + let row = { + Number: rowMixedValue(columns[1], i), + Decimal: rowMixedValue(columns[2], i), + Currency: rowMixedValue(columns[3], i), + Percent: rowMixedValue(columns[4], i), + Duration: rowMixedValue(columns[5], i), + Rating: rowMixedValue(columns[6], i), + }; + rowAttributes.push(row); + } + + await createBulkRows(context, { + project, + table, + values: rowAttributes, + }); + unfilteredRecords = await listRow({ project, table }); + + // verify length of unfiltered records to be 400 + expect(unfilteredRecords.length).to.equal(400); + }); + + it('Type: Number', async () => { + // filter types to be verified + // eq, neq, null, notnull, like, nlike, >, >=, <, <= + + const dataType = 'Number'; + + const filter = { + fk_column_id: columns[1].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: '33', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === 33 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== 33 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: > + filter.comparison_op = 'gt'; + filter.value = '44'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] > 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: >= + filter.comparison_op = 'gte'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] >= 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: < + filter.comparison_op = 'lt'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] < 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: <= + filter.comparison_op = 'lte'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] <= 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: Decimal', async () => { + // filter types to be verified + // eq, neq, null, notnull, like, nlike, >, >=, <, <= + + const dataType = 'Decimal'; + + const filter = { + fk_column_id: columns[2].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: '33.3', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => parseFloat(record[dataType]) === 33.3 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => parseFloat(record[dataType]) !== 33.3 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: > + filter.comparison_op = 'gt'; + filter.value = '44.26'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) > 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: >= + filter.comparison_op = 'gte'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) >= 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: < + filter.comparison_op = 'lt'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) < 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: <= + filter.comparison_op = 'lte'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) <= 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: Currency', async () => { + // filter types to be verified + // eq, neq, null, notnull, like, nlike, >, >=, <, <= + + const dataType = 'Currency'; + + const filter = { + fk_column_id: columns[3].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: '33.3', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => parseFloat(record[dataType]) === 33.3 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => parseFloat(record[dataType]) !== 33.3 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: > + filter.comparison_op = 'gt'; + filter.value = '44.26'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) > 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: >= + filter.comparison_op = 'gte'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) >= 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: < + filter.comparison_op = 'lt'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) < 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: <= + filter.comparison_op = 'lte'; + expectedRecords = unfilteredRecords.filter( + (record) => + parseFloat(record[dataType]) <= 44.26 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: Percent', async () => { + // filter types to be verified + // eq, neq, null, notnull, like, nlike, >, >=, <, <= + + const dataType = 'Percent'; + + const filter = { + fk_column_id: columns[4].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: '33', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === 33 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== 33 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: > + filter.comparison_op = 'gt'; + filter.value = '44'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] > 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: >= + filter.comparison_op = 'gte'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] >= 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: < + filter.comparison_op = 'lt'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] < 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: <= + filter.comparison_op = 'lte'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] <= 44 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + }); + + it('Type: Rating', async () => { + // filter types to be verified + // eq, neq, null, notnull, like, nlike, >, >=, <, <= + + const dataType = 'Rating'; + + const filter = { + fk_column_id: columns[6].id, + status: 'create', + logical_op: 'and', + comparison_op: 'eq', + value: '3', + }; + + let expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === 3 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: neq + filter.comparison_op = 'neq'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== 3 + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: null + filter.comparison_op = 'null'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] === null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: notnull + filter.comparison_op = 'notnull'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: > + filter.comparison_op = 'gt'; + filter.value = '2'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] > 2 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: >= + filter.comparison_op = 'gte'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] >= 2 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: < + filter.comparison_op = 'lt'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] < 2 && record[dataType] !== null + ); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); + + // filter: <= + filter.comparison_op = 'lte'; + expectedRecords = unfilteredRecords.filter( + (record) => record[dataType] <= 2 && record[dataType] !== null ); - await retrieveRecordsAndValidate(filter, expectedRecords); + await retrieveRecordsAndValidate(filter, expectedRecords, dataType); }); } export default function () { - describe('Filters', filterTests); + describe('Filter: Text based', filterTextBased); + describe('Filter: Numerical', filterNumberBased); }