From bf6d4e7e29c7784b5ecb4f096fd0996f63844e69 Mon Sep 17 00:00:00 2001 From: Max Polsky Date: Mon, 28 Mar 2022 13:43:15 +0300 Subject: [PATCH] New schema operations and implemented them in tests (#238) * feat: new schema operation * test: skip unsupported tests * feat: new schema operation to DynamoDB * feat: new schema operation to BigQuery --- .../lib/supported_operations.js | 6 +- .../lib/supported_operations.js | 6 +- .../lib/supported_operations.js | 6 +- .../lib/schema_commons.js | 3 + .../test/storage/data_provider.spec.js | 219 +++++++++--------- 5 files changed, 113 insertions(+), 127 deletions(-) diff --git a/packages/external-db-bigquery/lib/supported_operations.js b/packages/external-db-bigquery/lib/supported_operations.js index 1b65fe9fc..9b074c9a0 100644 --- a/packages/external-db-bigquery/lib/supported_operations.js +++ b/packages/external-db-bigquery/lib/supported_operations.js @@ -1,7 +1,5 @@ -const { SchemaOperations } = require('velo-external-db-commons') +const { List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, FindWithSort, Aggregate, BulkDelete, Truncate, StartWithCaseSensitive, Projection } = require('velo-external-db-commons').SchemaOperations -const { List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, FindWithSort, Aggregate, BulkDelete, Truncate } = SchemaOperations - -const supportedOperations = [ List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, FindWithSort, Aggregate, BulkDelete, Truncate ] +const supportedOperations = [ List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, FindWithSort, Aggregate, BulkDelete, Truncate, StartWithCaseSensitive, Projection ] module.exports = { supportedOperations } \ No newline at end of file diff --git a/packages/external-db-dynamodb/lib/supported_operations.js b/packages/external-db-dynamodb/lib/supported_operations.js index 726574715..d5f55eaa9 100644 --- a/packages/external-db-dynamodb/lib/supported_operations.js +++ b/packages/external-db-dynamodb/lib/supported_operations.js @@ -1,7 +1,5 @@ -const { SchemaOperations } = require('velo-external-db-commons') +const { List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately, Projection, StartWithCaseSensitive } = require('velo-external-db-commons').SchemaOperations -const { List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately } = SchemaOperations - -const supportedOperations = [ List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately ] +const supportedOperations = [ List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately, Projection, StartWithCaseSensitive ] module.exports = { supportedOperations } \ No newline at end of file diff --git a/packages/external-db-firestore/lib/supported_operations.js b/packages/external-db-firestore/lib/supported_operations.js index 726574715..5208e0bc6 100644 --- a/packages/external-db-firestore/lib/supported_operations.js +++ b/packages/external-db-firestore/lib/supported_operations.js @@ -1,7 +1,5 @@ -const { SchemaOperations } = require('velo-external-db-commons') +const { List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately, StartWithCaseSensitive } = require('velo-external-db-commons').SchemaOperations -const { List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately } = SchemaOperations - -const supportedOperations = [ List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately ] +const supportedOperations = [ List, ListHeaders, Create, Drop, AddColumn, RemoveColumn, Describe, BulkDelete, Truncate, DeleteImmediately, UpdateImmediately, StartWithCaseSensitive ] module.exports = { supportedOperations } \ No newline at end of file diff --git a/packages/velo-external-db-commons/lib/schema_commons.js b/packages/velo-external-db-commons/lib/schema_commons.js index 532087d3e..75fde7b85 100644 --- a/packages/velo-external-db-commons/lib/schema_commons.js +++ b/packages/velo-external-db-commons/lib/schema_commons.js @@ -38,6 +38,9 @@ const SchemaOperations = Object.freeze({ Truncate: 'truncate', UpdateImmediately: 'updateImmediately', DeleteImmediately: 'deleteImmediately', + StartWithCaseSensitive: 'startWithCaseSensitive', + StartWithCaseInsensitive: 'startWithCaseInsensitive', + Projection: 'projection', }) const AllSchemaOperations = Object.values(SchemaOperations) diff --git a/packages/velo-external-db/test/storage/data_provider.spec.js b/packages/velo-external-db/test/storage/data_provider.spec.js index d2a10c92a..eba1f291c 100644 --- a/packages/velo-external-db/test/storage/data_provider.spec.js +++ b/packages/velo-external-db/test/storage/data_provider.spec.js @@ -1,7 +1,8 @@ -const { Uninitialized, shouldNotRunOn } = require('test-commons') +const { Uninitialized, testIfSupportedOperationsIncludes } = require('test-commons') +const { FindWithSort, DeleteImmediately, Aggregate, UpdateImmediately, StartWithCaseSensitive, StartWithCaseInsensitive, Projection } = require('velo-external-db-commons').SchemaOperations const Chance = require('chance') const gen = require('../gen') -const { env, dbTeardown, setupDb, currentDbImplementationName } = require('../resources/provider_resources') +const { env, dbTeardown, setupDb, currentDbImplementationName, supportedOperations } = require('../resources/provider_resources') const { entitiesWithOwnerFieldOnly } = require ('../drivers/data_provider_matchers') //todo: move toggleCase to utils const chance = new Chance() @@ -26,68 +27,62 @@ describe(`Data API: ${currentDbImplementationName()}`, () => { await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual([]) }) + testIfSupportedOperationsIncludes(supportedOperations, [ FindWithSort ])('search with non empty filter, default projection will return data', async() => { + await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) + env.driver.givenFilterByIdWith(ctx.entity._id, ctx.filter) + env.driver.stubEmptyOrderByFor(ctx.sort) + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) + await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual(expect.arrayContaining([ctx.entity])) + }) - if (shouldNotRunOn(['DynamoDb'], currentDbImplementationName())) { - test('search with non empty filter, default projection will return data', async() => { - await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) - env.driver.givenFilterByIdWith(ctx.entity._id, ctx.filter) - env.driver.stubEmptyOrderByFor(ctx.sort) - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual(expect.arrayContaining([ctx.entity])) - }) - - test('search with non empty order by, default projection will return sorted data', async() => { - await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) - env.driver.stubEmptyFilterFor(ctx.filter) - env.driver.givenOrderByFor('_owner', ctx.sort) - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual([ctx.anotherEntity, ctx.entity].sort((a, b) => (a._owner > b._owner) ? 1 : -1)) - }) - - test('search with empty order, filter and default projection but with limit and skip', async() => { - await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) - env.driver.stubEmptyFilterFor(ctx.filter) - env.driver.givenOrderByFor('_owner', ctx.sort) - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, 1, 1, ctx.projection) ).resolves.toEqual([ctx.anotherEntity, ctx.entity].sort((a, b) => (a._owner < b._owner) ? 1 : -1).slice(0, 1)) - }) - } + testIfSupportedOperationsIncludes(supportedOperations, [ FindWithSort ])('search with non empty order by, default projection will return sorted data', async() => { + await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) + env.driver.stubEmptyFilterFor(ctx.filter) + env.driver.givenOrderByFor('_owner', ctx.sort) + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) + await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual([ctx.anotherEntity, ctx.entity].sort((a, b) => (a._owner > b._owner) ? 1 : -1)) + }) - if (shouldNotRunOn(['Firestore', 'Google-Sheet', 'Airtable'], currentDbImplementationName())) { - test('search with startsWith operator will return data', async() => { - await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) - const firstHalfOfValue = ctx.entity[ctx.column.name].substring(0, ctx.column.name.length / 2) - - env.driver.givenStartsWithFilterFor(ctx.filter, ctx.column.name, firstHalfOfValue) - env.driver.stubEmptyOrderByFor(ctx.sort) - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual(expect.arrayContaining([ctx.entity])) - }) - - if (shouldNotRunOn(['DynamoDb'], currentDbImplementationName())) { - test('search with startsWith operator will return data and be case-insensitive', async() => { - await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) - const firstHalfOfValue = ctx.entity[ctx.column.name].substring(0, ctx.column.name.length / 2) - const firstHalfOfValueToggled = firstHalfOfValue.toUpperCase() === firstHalfOfValue ? firstHalfOfValue.toLowerCase() : firstHalfOfValue.toUpperCase() - - env.driver.givenStartsWithFilterFor(ctx.filter, ctx.column.name, firstHalfOfValueToggled) - env.driver.stubEmptyOrderByFor(ctx.sort) - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual(expect.arrayContaining([ctx.entity])) - }) - } - } + testIfSupportedOperationsIncludes(supportedOperations, [ FindWithSort ])('search with empty order, filter and default projection but with limit and skip', async() => { + await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) + env.driver.stubEmptyFilterFor(ctx.filter) + env.driver.givenOrderByFor('_owner', ctx.sort) + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) + await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, 1, 1, ctx.projection) ).resolves.toEqual([ctx.anotherEntity, ctx.entity].sort((a, b) => (a._owner < b._owner) ? 1 : -1).slice(0, 1)) + }) + + + testIfSupportedOperationsIncludes(supportedOperations, [ StartWithCaseSensitive ])('search with startsWith operator will return data', async() => { + await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) + const firstHalfOfValue = ctx.entity[ctx.column.name].substring(0, ctx.column.name.length / 2) + + env.driver.givenStartsWithFilterFor(ctx.filter, ctx.column.name, firstHalfOfValue) + env.driver.stubEmptyOrderByFor(ctx.sort) + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) + await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual(expect.arrayContaining([ctx.entity])) + }) + + testIfSupportedOperationsIncludes(supportedOperations, [ StartWithCaseInsensitive ])('search with startsWith operator will return data and be case-insensitive', async() => { + await givenCollectionWith([ctx.entity, ctx.anotherEntity], ctx.collectionName, ctx.entityFields) + const firstHalfOfValue = ctx.entity[ctx.column.name].substring(0, ctx.column.name.length / 2) + const firstHalfOfValueToggled = firstHalfOfValue.toUpperCase() === firstHalfOfValue ? firstHalfOfValue.toLowerCase() : firstHalfOfValue.toUpperCase() + + env.driver.givenStartsWithFilterFor(ctx.filter, ctx.column.name, firstHalfOfValueToggled) + env.driver.stubEmptyOrderByFor(ctx.sort) + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) + await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, ctx.skip, ctx.limit, ctx.projection) ).resolves.toEqual(expect.arrayContaining([ctx.entity])) + }) + + testIfSupportedOperationsIncludes(supportedOperations, [ Projection ])('search with projection will return the specified fields', async() => { + const projection = ['_owner'] + await givenCollectionWith(ctx.entities, ctx.collectionName, ctx.entityFields) + env.driver.stubEmptyFilterFor(ctx.filter) + env.driver.stubEmptyOrderByFor(ctx.sort) + env.driver.givenProjectionExprFor(projection) + await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, 0, 50, projection) ).resolves.toEqual(entitiesWithOwnerFieldOnly(ctx.entities)) + }) + - if(shouldNotRunOn(['Firestore', 'Google-Sheet', 'Airtable'], currentDbImplementationName())) { - test('search with projection will return the specified fields', async() => { - const projection = ['_owner'] - await givenCollectionWith(ctx.entities, ctx.collectionName, ctx.entityFields) - env.driver.stubEmptyFilterFor(ctx.filter) - env.driver.stubEmptyOrderByFor(ctx.sort) - env.driver.givenProjectionExprFor(projection) - await expect( env.dataProvider.find(ctx.collectionName, ctx.filter, ctx.sort, 0, 50, projection) ).resolves.toEqual(entitiesWithOwnerFieldOnly(ctx.entities)) - }) - } test('count will run query', async() => { await givenCollectionWith(ctx.entities, ctx.collectionName, ctx.entityFields) env.driver.stubEmptyFilterFor(ctx.filter) @@ -130,41 +125,36 @@ describe(`Data API: ${currentDbImplementationName()}`, () => { await expect( env.dataProvider.find(ctx.numericCollectionName, '', '', 0, 50, ctx.projection) ).resolves.toEqual([ctx.numberEntity]) }) - if (shouldNotRunOn(['BigQuery'], currentDbImplementationName())) { - test('delete data from collection', async() => { - await givenCollectionWith(ctx.entities, ctx.collectionName, ctx.entityFields) - env.driver.stubEmptyFilterAndSortFor('', '') - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - - await expect( env.dataProvider.delete(ctx.collectionName, ctx.entities.map(e => e._id)) ).resolves.toEqual(ctx.entities.length) + testIfSupportedOperationsIncludes(supportedOperations, [ DeleteImmediately ])('delete data from collection', async() => { + await givenCollectionWith(ctx.entities, ctx.collectionName, ctx.entityFields) + env.driver.stubEmptyFilterAndSortFor('', '') + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - await expect( env.dataProvider.find(ctx.collectionName, '', '', 0, 50, ctx.projection) ).resolves.toEqual([]) - }) - } + await expect( env.dataProvider.delete(ctx.collectionName, ctx.entities.map(e => e._id)) ).resolves.toEqual(ctx.entities.length) - if (shouldNotRunOn(['BigQuery'], currentDbImplementationName())) { - test('allow update for single entity', async() => { - await givenCollectionWith([ctx.entity], ctx.collectionName, ctx.entityFields) - env.driver.stubEmptyFilterAndSortFor('', '') - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) + await expect( env.dataProvider.find(ctx.collectionName, '', '', 0, 50, ctx.projection) ).resolves.toEqual([]) + }) + + testIfSupportedOperationsIncludes(supportedOperations, [ UpdateImmediately ])('allow update for single entity', async() => { + await givenCollectionWith([ctx.entity], ctx.collectionName, ctx.entityFields) + env.driver.stubEmptyFilterAndSortFor('', '') + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - await expect( env.dataProvider.update(ctx.collectionName, [ctx.modifiedEntity]) ).resolves.toEqual(1) + await expect( env.dataProvider.update(ctx.collectionName, [ctx.modifiedEntity]) ).resolves.toEqual(1) - await expect( env.dataProvider.find(ctx.collectionName, '', '', 0, 50, ctx.projection) ).resolves.toEqual([ctx.modifiedEntity]) + await expect( env.dataProvider.find(ctx.collectionName, '', '', 0, 50, ctx.projection) ).resolves.toEqual([ctx.modifiedEntity]) }) -} - if (shouldNotRunOn(['BigQuery'], currentDbImplementationName())) { - test('allow update for multiple entities', async() => { - await givenCollectionWith(ctx.entities, ctx.collectionName, ctx.entityFields) - env.driver.stubEmptyFilterAndSortFor('', '') - env.driver.givenAllFieldsProjectionFor?.(ctx.projection) + testIfSupportedOperationsIncludes(supportedOperations, [ UpdateImmediately ])('allow update for multiple entities', async() => { + await givenCollectionWith(ctx.entities, ctx.collectionName, ctx.entityFields) + env.driver.stubEmptyFilterAndSortFor('', '') + env.driver.givenAllFieldsProjectionFor?.(ctx.projection) - expect( await env.dataProvider.update(ctx.collectionName, ctx.modifiedEntities) ).toEqual(ctx.modifiedEntities.length) + expect( await env.dataProvider.update(ctx.collectionName, ctx.modifiedEntities) ).toEqual(ctx.modifiedEntities.length) - expect( await env.dataProvider.find(ctx.collectionName, '', '', 0, 50, ctx.projection) ).toEqual(expect.arrayContaining(ctx.modifiedEntities)) - }) - } + expect( await env.dataProvider.find(ctx.collectionName, '', '', 0, 50, ctx.projection) ).toEqual(expect.arrayContaining(ctx.modifiedEntities)) + }) + // testt('if update does not have and updatable fields, do nothing', async () => { // await givenCollectionWith([ctx.entity], ctx.collectionName) @@ -185,41 +175,40 @@ describe(`Data API: ${currentDbImplementationName()}`, () => { await expect( env.dataProvider.find(ctx.collectionName, '', '', 0, 50, ctx.projection) ).resolves.toEqual([]) }) - if (shouldNotRunOn(['Firestore', 'Airtable', 'DynamoDb'], currentDbImplementationName())) { - test('aggregate api without filter', async() => { - await env.schemaProvider.create(ctx.numericCollectionName, ctx.numericColumns) - await givenCollectionWith([ctx.numberEntity, ctx.anotherNumberEntity], ctx.numericCollectionName, ctx.numberEntityFields) + testIfSupportedOperationsIncludes(supportedOperations, [ Aggregate ])('aggregate api without filter', async() => { + await env.schemaProvider.create(ctx.numericCollectionName, ctx.numericColumns) + await givenCollectionWith([ctx.numberEntity, ctx.anotherNumberEntity], ctx.numericCollectionName, ctx.numberEntityFields) - env.driver.stubEmptyFilterFor(ctx.filter) - env.driver.givenAggregateQueryWith(ctx.aggregation.processingStep, ctx.numericColumns, ctx.aliasColumns, ['_id'], ctx.aggregation.postFilteringStep, 1) + env.driver.stubEmptyFilterFor(ctx.filter) + env.driver.givenAggregateQueryWith(ctx.aggregation.processingStep, ctx.numericColumns, ctx.aliasColumns, ['_id'], ctx.aggregation.postFilteringStep, 1) - await expect( env.dataProvider.aggregate(ctx.numericCollectionName, ctx.filter, ctx.aggregation) ).resolves.toEqual(expect.arrayContaining([{ _id: ctx.numberEntity._id, [ctx.aliasColumns[0]]: ctx.numberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.numberEntity[ctx.numericColumns[1].name] }, - { _id: ctx.anotherNumberEntity._id, [ctx.aliasColumns[0]]: ctx.anotherNumberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.anotherNumberEntity[ctx.numericColumns[1].name] } - ])) - }) + await expect( env.dataProvider.aggregate(ctx.numericCollectionName, ctx.filter, ctx.aggregation) ).resolves.toEqual(expect.arrayContaining([{ _id: ctx.numberEntity._id, [ctx.aliasColumns[0]]: ctx.numberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.numberEntity[ctx.numericColumns[1].name] }, + { _id: ctx.anotherNumberEntity._id, [ctx.aliasColumns[0]]: ctx.anotherNumberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.anotherNumberEntity[ctx.numericColumns[1].name] } + ])) + }) - test('aggregate api without having', async() => { - await env.schemaProvider.create(ctx.numericCollectionName, ctx.numericColumns) - await givenCollectionWith([ctx.numberEntity, ctx.anotherNumberEntity], ctx.numericCollectionName, ctx.numberEntityFields) + testIfSupportedOperationsIncludes(supportedOperations, [ Aggregate ])('aggregate api without having', async() => { + await env.schemaProvider.create(ctx.numericCollectionName, ctx.numericColumns) + await givenCollectionWith([ctx.numberEntity, ctx.anotherNumberEntity], ctx.numericCollectionName, ctx.numberEntityFields) - env.driver.stubEmptyFilterFor(ctx.filter) - env.driver.givenAggregateQueryWith(ctx.aggregation.processingStep, ctx.numericColumns, ctx.aliasColumns, ['_id'], ctx.aggregation.postFilteringStep, 1) + env.driver.stubEmptyFilterFor(ctx.filter) + env.driver.givenAggregateQueryWith(ctx.aggregation.processingStep, ctx.numericColumns, ctx.aliasColumns, ['_id'], ctx.aggregation.postFilteringStep, 1) - await expect( env.dataProvider.aggregate(ctx.numericCollectionName, ctx.filter, ctx.aggregation) ).resolves.toEqual(expect.arrayContaining([{ _id: ctx.numberEntity._id, [ctx.aliasColumns[0]]: ctx.numberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.numberEntity[ctx.numericColumns[1].name] }, - { _id: ctx.anotherNumberEntity._id, [ctx.aliasColumns[0]]: ctx.anotherNumberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.anotherNumberEntity[ctx.numericColumns[1].name] } - ])) - }) + await expect( env.dataProvider.aggregate(ctx.numericCollectionName, ctx.filter, ctx.aggregation) ).resolves.toEqual(expect.arrayContaining([{ _id: ctx.numberEntity._id, [ctx.aliasColumns[0]]: ctx.numberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.numberEntity[ctx.numericColumns[1].name] }, + { _id: ctx.anotherNumberEntity._id, [ctx.aliasColumns[0]]: ctx.anotherNumberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.anotherNumberEntity[ctx.numericColumns[1].name] } + ])) + }) - test('aggregate api with filter', async() => { - await env.schemaProvider.create(ctx.numericCollectionName, ctx.numericColumns) - await givenCollectionWith([ctx.numberEntity, ctx.anotherNumberEntity], ctx.numericCollectionName, ctx.numberEntityFields) + testIfSupportedOperationsIncludes(supportedOperations, [ Aggregate ])('aggregate api with filter', async() => { + await env.schemaProvider.create(ctx.numericCollectionName, ctx.numericColumns) + await givenCollectionWith([ctx.numberEntity, ctx.anotherNumberEntity], ctx.numericCollectionName, ctx.numberEntityFields) - env.driver.givenFilterByIdWith(ctx.numberEntity._id, ctx.filter) - env.driver.givenAggregateQueryWith(ctx.aggregation.processingStep, ctx.numericColumns, ctx.aliasColumns, ['_id'], ctx.aggregation.postFilteringStep, 2) + env.driver.givenFilterByIdWith(ctx.numberEntity._id, ctx.filter) + env.driver.givenAggregateQueryWith(ctx.aggregation.processingStep, ctx.numericColumns, ctx.aliasColumns, ['_id'], ctx.aggregation.postFilteringStep, 2) - await expect( env.dataProvider.aggregate(ctx.numericCollectionName, ctx.filter, ctx.aggregation) ).resolves.toEqual([{ _id: ctx.numberEntity._id, [ctx.aliasColumns[0]]: ctx.numberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.numberEntity[ctx.numericColumns[1].name] }]) - }) - } + await expect( env.dataProvider.aggregate(ctx.numericCollectionName, ctx.filter, ctx.aggregation) ).resolves.toEqual([{ _id: ctx.numberEntity._id, [ctx.aliasColumns[0]]: ctx.numberEntity[ctx.numericColumns[0].name], [ctx.aliasColumns[1]]: ctx.numberEntity[ctx.numericColumns[1].name] }]) + }) + const ctx = { collectionName: Uninitialized,