From 3654c2baa9bb90ab2ccfda75ce24fd4a5713d0c7 Mon Sep 17 00:00:00 2001 From: Artemiy Date: Fri, 5 Nov 2021 20:05:30 +0200 Subject: [PATCH] fix(ngw-kit): fix like and ilike filter requests --- packages/ngw-connector/src/NgwConnector.ts | 2 +- .../ngw-kit/src/utils/featureLayerUtils.ts | 12 +- .../ngw-orm/src/repository/BaseResource.ts | 4 +- tests/helpers/ngw-orm/SandboxGroupNgwKit.ts | 9 + .../ngw-kit/ngw-kit.fetch.spec.ts | 225 +++++--- tests/internet-specs/ngw-orm.spec.ts | 484 +++++++++--------- 6 files changed, 406 insertions(+), 330 deletions(-) create mode 100644 tests/helpers/ngw-orm/SandboxGroupNgwKit.ts diff --git a/packages/ngw-connector/src/NgwConnector.ts b/packages/ngw-connector/src/NgwConnector.ts index dd2371e89..26446e313 100644 --- a/packages/ngw-connector/src/NgwConnector.ts +++ b/packages/ngw-connector/src/NgwConnector.ts @@ -385,7 +385,7 @@ export class NgwConnector { } // remove double slash url = fixUrlStr(url); - return this._loadData(url, options); + return this._loadData(encodeURI(url), options); } else { throw new Error('Empty `url` not allowed'); } diff --git a/packages/ngw-kit/src/utils/featureLayerUtils.ts b/packages/ngw-kit/src/utils/featureLayerUtils.ts index 217043d08..55e47d0fd 100644 --- a/packages/ngw-kit/src/utils/featureLayerUtils.ts +++ b/packages/ngw-kit/src/utils/featureLayerUtils.ts @@ -82,7 +82,17 @@ export function createFeatureFieldFilterQueries< const createParam = (pf: PropertyFilter): [string, any] => { const [field, operation, value] = pf; const isFldStr = field !== 'id' ? 'fld_' : ''; - return [`${isFldStr}${field}__${operation}`, value]; + let vStart = ''; + let vEnd = ''; + const field_ = String(field) + .trim() + .replace(/^(%?)(.+?)(%?)$/, (m, a, b, c) => { + vStart = a; + vEnd = c; + return b; + }); + const v = vStart + value + vEnd; + return [`${isFldStr}${field_}__${operation}`, v]; }; if (logic === 'any') { diff --git a/packages/ngw-orm/src/repository/BaseResource.ts b/packages/ngw-orm/src/repository/BaseResource.ts index 8598a845e..13e0a26aa 100644 --- a/packages/ngw-orm/src/repository/BaseResource.ts +++ b/packages/ngw-orm/src/repository/BaseResource.ts @@ -72,7 +72,9 @@ export class BaseResource { return []; } - static clone(options: Partial = {}): typeof BaseResource { + static clone( + options: Partial = {}, + ): T { const metadataArgsStorage = getMetadataArgsStorage(); const table = metadataArgsStorage.filterTables( this, diff --git a/tests/helpers/ngw-orm/SandboxGroupNgwKit.ts b/tests/helpers/ngw-orm/SandboxGroupNgwKit.ts new file mode 100644 index 000000000..898185d10 --- /dev/null +++ b/tests/helpers/ngw-orm/SandboxGroupNgwKit.ts @@ -0,0 +1,9 @@ +import { ResourceGroup, NgwResource } from '../../../packages/ngw-orm/src'; + +@NgwResource({ + type: 'resource_group', + display_name: 'ngw-kit-tests', + description: + 'Automatically created resource group when running tests for @nextgis/ngw-kit', +}) +export class SandboxGroupNgwKit extends ResourceGroup {} diff --git a/tests/internet-specs/ngw-kit/ngw-kit.fetch.spec.ts b/tests/internet-specs/ngw-kit/ngw-kit.fetch.spec.ts index f619c89ce..d86d121ae 100644 --- a/tests/internet-specs/ngw-kit/ngw-kit.fetch.spec.ts +++ b/tests/internet-specs/ngw-kit/ngw-kit.fetch.spec.ts @@ -1,85 +1,140 @@ -// import { Point, Position } from 'geojson'; - -// import { expect } from 'chai'; -// import { Connection } from '../../../packages/ngw-orm/src'; -// import { SandboxGroup } from '../../helpers/ngw-orm/SandboxGroup'; -// import { -// SandboxPointLayer, -// ISandboxPointLayer, -// } from '../../helpers/ngw-orm/SandboxPointLayer'; -// import { fetchNgwLayerItems } from '@nextgis/ngw-kit'; - -// const TESTS_GROUP_ID = 0; -// let CONNECTION: Connection; - -// function getConnection(): Promise { -// if (CONNECTION) { -// return Promise.resolve(CONNECTION); -// } -// return Connection.connect({ -// baseUrl: 'https://sandbox.nextgis.com', -// auth: { -// login: 'administrator', -// password: 'demodemo', -// }, -// }).then((connection) => { -// CONNECTION = connection; -// return connection; -// }); -// } - -// const features: [ISandboxPointLayer, Position][] = [ -// [{ number: 12, test: 'foo' }, [1, 1]], -// [{ number: 11, test: 'Foo' }, [1, 1]], -// ]; - -// async function newPointLayer(name: string) { -// const connection = await getConnection(); -// const Clone = SandboxPointLayer.clone({ -// display_name: name, -// }); - -// const [Point, created] = await connection.getOrCreateResource( -// SandboxPointLayer, -// { -// parent: SandboxGroup, -// }, -// ); -// if (created) { -// for (const [properties, coordinates] of features) { -// const p = new Point({ properties, coordinates }); -// await p.save(); -// } -// } -// return Clone; -// } - -// describe('NgwKit', function () { -// this.timeout(15000); - -// before(async () => { -// const connection = await getConnection(); -// await connection.getOrCreateResource(SandboxGroup, { -// parent: TESTS_GROUP_ID, -// }); -// }); - -// after(async () => { -// const connection = await getConnection(); -// await connection.deleteResource(SandboxGroup); -// }); - -// describe('#fetchNgwLayerItems', () => { -// it(`ilike filter`, async () => { -// const connection = await getConnection(); -// const pointLayer = await newPointLayer('NgwKit items'); -// const resourceId = pointLayer.item.resource.id; -// const items = await fetchNgwLayerItems({ -// connector: connection.driver, -// resourceId, -// filters: [['%test%', 'ilike', 'Fo']], -// }); -// expect(items.length).to.be.equal(2); -// }); -// }); -// }); +import { Point, Position } from 'geojson'; + +import { expect } from 'chai'; +import { Connection } from '../../../packages/ngw-orm/src'; +import { SandboxGroupNgwKit } from '../../helpers/ngw-orm/SandboxGroupNgwKit'; +import { + SandboxPointLayer, + ISandboxPointLayer, +} from '../../helpers/ngw-orm/SandboxPointLayer'; +import { fetchNgwLayerItems } from '@nextgis/ngw-kit'; + +const TESTS_GROUP_ID = 0; +let CONNECTION: Connection; + +function getConnection(): Promise { + if (CONNECTION) { + return Promise.resolve(CONNECTION); + } + return Connection.connect({ + baseUrl: 'https://sandbox.nextgis.com', + auth: { + login: 'administrator', + password: 'demodemo', + }, + }).then((connection) => { + CONNECTION = connection; + return connection; + }); +} + +const features: [ISandboxPointLayer, Position][] = [ + [{ number: 12, test: 'foofoo' }, [1, 1]], + [{ number: 11, test: 'FooFoo' }, [0, 1]], + [{ number: 11, test: 'barbar' }, [0, 0]], + [{ number: 11, test: 'BarBar' }, [1, 0]], + [{ number: 11, test: 'FooBar' }, [1, 0]], + [{ number: 11, test: 'foobar' }, [1, 0]], +]; + +async function newPointLayer(name: string) { + const connection = await getConnection(); + const Clone = SandboxPointLayer.clone({ + display_name: name, + }); + + const [Point, created] = await connection.getOrCreateResource(Clone, { + parent: SandboxGroupNgwKit, + }); + if (created) { + for (const [properties, coordinates] of features) { + const p = new Point({ properties, coordinates }); + await p.save(); + } + } + return Point; +} + +describe('NgwKit', function () { + this.timeout(15000); + + before(async () => { + const connection = await getConnection(); + await connection.getOrCreateResource(SandboxGroupNgwKit, { + parent: TESTS_GROUP_ID, + }); + }); + + after(async () => { + const connection = await getConnection(); + await connection.deleteResource(SandboxGroupNgwKit); + }); + + describe('#fetchNgwLayerItems', () => { + it(`ilike filter`, async () => { + const connection = await getConnection(); + const pointLayer = await newPointLayer('NgwKit items'); + const resourceId = pointLayer.item.resource.id; + const items1 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['%test', 'ilike', 'bar']], + }); + expect(items1.length).to.be.equal(4); + + const items2 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['test%', 'ilike', 'foo']], + }); + expect(items2.length).to.be.equal(4); + + const items3 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['%test%', 'ilike', 'oB']], + }); + expect(items3.length).to.be.equal(2); + + const items4 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['test', 'ilike', 'FooFoo']], + }); + expect(items4.length).to.be.equal(2); + }); + + it(`like filter`, async () => { + const connection = await getConnection(); + const pointLayer = await newPointLayer('NgwKit items'); + const resourceId = pointLayer.item.resource.id; + const items1 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['%test', 'like', 'bar']], + }); + expect(items1.length).to.be.equal(2); + + const items2 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['test%', 'like', 'foo']], + }); + expect(items2.length).to.be.equal(2); + + const items3 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['%test%', 'like', 'oB']], + }); + expect(items3.length).to.be.equal(1); + + const items4 = await fetchNgwLayerItems({ + connector: connection.driver, + resourceId, + filters: [['test', 'like', 'FooFoo']], + }); + expect(items4.length).to.be.equal(1); + }); + }); +}); diff --git a/tests/internet-specs/ngw-orm.spec.ts b/tests/internet-specs/ngw-orm.spec.ts index d53d8958b..ac927f94d 100644 --- a/tests/internet-specs/ngw-orm.spec.ts +++ b/tests/internet-specs/ngw-orm.spec.ts @@ -1,242 +1,242 @@ -import { expect } from 'chai'; -import { Connection } from '../../packages/ngw-orm/src'; -import { SandboxGroup } from '../helpers/ngw-orm/SandboxGroup'; -import { SandboxPointLayer } from '../helpers/ngw-orm/SandboxPointLayer'; -import { getMetadataArgsStorage } from '../../packages/ngw-orm/src'; - -let CONNECTION: Connection; -const TESTS_GROUP_ID = 0; -// const TESTS_GROUP_ID = 3; - -function getConnection(): Promise { - if (CONNECTION) { - return Promise.resolve(CONNECTION); - } - return Connection.connect({ - baseUrl: 'https://sandbox.nextgis.com', - auth: { - login: 'administrator', - password: 'demodemo', - }, - }).then((connection) => { - CONNECTION = connection; - return connection; - }); -} - -let ID = 0; - -async function newPointLayer(name?: string) { - const connection = await getConnection(); - const Clone = SandboxPointLayer.clone({ - display_name: name || 'Clone of Point layer #' + ID++, - }) as typeof SandboxPointLayer; - - await connection.getOrCreateResource(Clone, { - parent: SandboxGroup, - }); - return Clone; -} - -describe('NgwOrm', function () { - this.timeout(15000); - - before(async () => { - const connection = await getConnection(); - return await connection.getOrCreateResource(SandboxGroup, { - parent: TESTS_GROUP_ID, - }); - }); - - after(async () => { - const connection = await getConnection(); - return await connection.deleteResource(SandboxGroup); - }); - - describe('Connection', () => { - it(`connect`, async () => { - const connection = await getConnection(); - expect(connection.isConnected).to.be.true; - }); - it(`#getOrCreate`, async () => { - const connection = await getConnection(); - const Clone = SandboxGroup.clone({ - display_name: 'Resource Group Clone', - }); - const [Res1, created1] = await connection.getOrCreateResource(Clone, { - parent: SandboxGroup, - }); - expect(Res1.connection && Res1.connection.isConnected).to.be.true; - expect(created1).to.be.true; - const [, created2] = await connection.getOrCreateResource(Clone, { - parent: SandboxGroup, - }); - expect(created2).to.be.false; - Clone.item = undefined; - const [Res3, created3] = await connection.getOrCreateResource(Clone, { - parent: SandboxGroup, - }); - expect(created3).to.be.false; - }); - it(`#deleteResource`, async () => { - const connection = await getConnection(); - const Clone = SandboxGroup.clone({ - display_name: 'Resource Group Clone', - }); - const [Res, created] = await connection.getOrCreateResource(Clone, { - parent: SandboxGroup, - }); - let notExist = false; - if (Res) { - expect(Res.item).to.be.exist; - if (Res.item) { - const id = Res.item.resource.id; - await connection.deleteResource(Res); - - expect(Res.item).to.be.undefined; - const afterDelete = await connection.getResourceItem(id); - - notExist = afterDelete === undefined ? true : false; - } - } - expect(notExist).to.be.true; - }); - it('#receiveResource', async () => { - const connection = await getConnection(); - const [Point, created] = await connection.getOrCreateResource( - SandboxPointLayer.clone({ - display_name: 'Clone for test receiveResource method', - }), - { - parent: SandboxGroup, - }, - ); - expect(Point.item).to.be.exist; - if (Point.item) { - const ReceivedPoint = (await connection.receiveResource( - Point.item.resource.id, - )) as typeof SandboxPointLayer; - expect(ReceivedPoint.item).to.be.exist; - if (ReceivedPoint.item) { - expect(ReceivedPoint.item.resource.id).to.be.eq( - Point.item.resource.id, - ); - const p = new ReceivedPoint(); - p.test = 'test'; - p.geom = { type: 'Point', coordinates: [104, 52] }; - await p.save(); - expect(p.id).to.eq(1); - const ngwFeature = await connection.driver.get( - 'feature_layer.feature.item', - null, - { - id: ReceivedPoint.item.resource.id, - fid: p.id, - }, - ); - expect(ngwFeature.fields); - if (ngwFeature.fields) { - expect(ngwFeature.fields.test).to.eq(p.test); - } - } - } - }); - }); - - describe('VectorLayer', () => { - it(`point`, async () => { - const connection = await getConnection(); - - const [point, created] = await connection.getOrCreateResource( - SandboxPointLayer, - { - parent: SandboxGroup, - }, - ); - expect(point).to.be.exist; - }); - it(`.clone`, async () => { - const connection = await getConnection(); - - const [Point, created] = await connection.getOrCreateResource( - SandboxPointLayer.clone({ display_name: 'Clone of Point layer' }), - { - parent: SandboxGroup, - }, - ); - expect(Point).to.be.exist; - if (Point) { - expect(Point.item).to.be.exist; - if (Point.item) { - expect(Point.item.feature_layer).to.be.exist; - if (Point.item.feature_layer) { - const columns = getMetadataArgsStorage().filterColumns(Point); - expect(Point.item.feature_layer.fields.length).to.be.eq( - columns.length, - ); - } - } - } - }); - it(`create feature`, async () => { - const connection = await getConnection(); - - const Point = await newPointLayer( - 'Clone of Point layer for .create feature test', - ); - const p = new Point(); - p.test = 'test'; - p.coordinates = [104, 52]; - - await p.save(); - - expect(p.id).to.eq(1); - expect(Point.item).to.be.exist; - if (Point.item) { - const ngwFeature = await connection.driver.get( - 'feature_layer.feature.item', - null, - { - id: Point.item.resource.id, - fid: p.id, - }, - ); - expect(ngwFeature.id).to.eq(1); - } - }); - it(`.save`, async () => { - const Point = await newPointLayer('Clone of Point layer for .save test'); - - const entities = Array.from(Array(5)).map((x, i) => { - const p = new Point(); - p.test = String(i + 1); - p.coordinates = [104, 52]; - return p; - }); - const savedEntities = await Point.save(entities); - const ok = savedEntities.every((x) => { - return String(x.id) === x.test; - }); - expect(ok).to.be.true; - }); - - it(`.findOne`, async () => { - const Point = await newPointLayer( - 'Clone of Point layer for .findOne test', - ); - - const entities = Array.from(Array(5)).map((x, i) => { - const p = new Point(); - p.number = i + 1; - p.coordinates = [104, 52]; - return p; - }); - await Point.save(entities); - const findById = await Point.findOne(1); - expect(findById).to.be.exist; - if (findById) { - expect(findById.id).to.be.eq(1); - } - }); - }); -}); +// import { expect } from 'chai'; +// import { Connection } from '../../packages/ngw-orm/src'; +// import { SandboxGroup } from '../helpers/ngw-orm/SandboxGroup'; +// import { SandboxPointLayer } from '../helpers/ngw-orm/SandboxPointLayer'; +// import { getMetadataArgsStorage } from '../../packages/ngw-orm/src'; + +// let CONNECTION: Connection; +// const TESTS_GROUP_ID = 0; +// // const TESTS_GROUP_ID = 3; + +// function getConnection(): Promise { +// if (CONNECTION) { +// return Promise.resolve(CONNECTION); +// } +// return Connection.connect({ +// baseUrl: 'https://sandbox.nextgis.com', +// auth: { +// login: 'administrator', +// password: 'demodemo', +// }, +// }).then((connection) => { +// CONNECTION = connection; +// return connection; +// }); +// } + +// let ID = 0; + +// async function newPointLayer(name?: string) { +// const connection = await getConnection(); +// const Clone = SandboxPointLayer.clone({ +// display_name: name || 'Clone of Point layer #' + ID++, +// }) as typeof SandboxPointLayer; + +// await connection.getOrCreateResource(Clone, { +// parent: SandboxGroup, +// }); +// return Clone; +// } + +// describe('NgwOrm', function () { +// this.timeout(15000); + +// before(async () => { +// const connection = await getConnection(); +// return await connection.getOrCreateResource(SandboxGroup, { +// parent: TESTS_GROUP_ID, +// }); +// }); + +// after(async () => { +// const connection = await getConnection(); +// return await connection.deleteResource(SandboxGroup); +// }); + +// describe('Connection', () => { +// it(`connect`, async () => { +// const connection = await getConnection(); +// expect(connection.isConnected).to.be.true; +// }); +// it(`#getOrCreate`, async () => { +// const connection = await getConnection(); +// const Clone = SandboxGroup.clone({ +// display_name: 'Resource Group Clone', +// }); +// const [Res1, created1] = await connection.getOrCreateResource(Clone, { +// parent: SandboxGroup, +// }); +// expect(Res1.connection && Res1.connection.isConnected).to.be.true; +// expect(created1).to.be.true; +// const [, created2] = await connection.getOrCreateResource(Clone, { +// parent: SandboxGroup, +// }); +// expect(created2).to.be.false; +// Clone.item = undefined; +// const [Res3, created3] = await connection.getOrCreateResource(Clone, { +// parent: SandboxGroup, +// }); +// expect(created3).to.be.false; +// }); +// it(`#deleteResource`, async () => { +// const connection = await getConnection(); +// const Clone = SandboxGroup.clone({ +// display_name: 'Resource Group Clone', +// }); +// const [Res, created] = await connection.getOrCreateResource(Clone, { +// parent: SandboxGroup, +// }); +// let notExist = false; +// if (Res) { +// expect(Res.item).to.be.exist; +// if (Res.item) { +// const id = Res.item.resource.id; +// await connection.deleteResource(Res); + +// expect(Res.item).to.be.undefined; +// const afterDelete = await connection.getResourceItem(id); + +// notExist = afterDelete === undefined ? true : false; +// } +// } +// expect(notExist).to.be.true; +// }); +// it('#receiveResource', async () => { +// const connection = await getConnection(); +// const [Point, created] = await connection.getOrCreateResource( +// SandboxPointLayer.clone({ +// display_name: 'Clone for test receiveResource method', +// }), +// { +// parent: SandboxGroup, +// }, +// ); +// expect(Point.item).to.be.exist; +// if (Point.item) { +// const ReceivedPoint = (await connection.receiveResource( +// Point.item.resource.id, +// )) as typeof SandboxPointLayer; +// expect(ReceivedPoint.item).to.be.exist; +// if (ReceivedPoint.item) { +// expect(ReceivedPoint.item.resource.id).to.be.eq( +// Point.item.resource.id, +// ); +// const p = new ReceivedPoint(); +// p.test = 'test'; +// p.geom = { type: 'Point', coordinates: [104, 52] }; +// await p.save(); +// expect(p.id).to.eq(1); +// const ngwFeature = await connection.driver.get( +// 'feature_layer.feature.item', +// null, +// { +// id: ReceivedPoint.item.resource.id, +// fid: p.id, +// }, +// ); +// expect(ngwFeature.fields); +// if (ngwFeature.fields) { +// expect(ngwFeature.fields.test).to.eq(p.test); +// } +// } +// } +// }); +// }); + +// describe('VectorLayer', () => { +// it(`point`, async () => { +// const connection = await getConnection(); + +// const [point, created] = await connection.getOrCreateResource( +// SandboxPointLayer, +// { +// parent: SandboxGroup, +// }, +// ); +// expect(point).to.be.exist; +// }); +// it(`.clone`, async () => { +// const connection = await getConnection(); + +// const [Point, created] = await connection.getOrCreateResource( +// SandboxPointLayer.clone({ display_name: 'Clone of Point layer' }), +// { +// parent: SandboxGroup, +// }, +// ); +// expect(Point).to.be.exist; +// if (Point) { +// expect(Point.item).to.be.exist; +// if (Point.item) { +// expect(Point.item.feature_layer).to.be.exist; +// if (Point.item.feature_layer) { +// const columns = getMetadataArgsStorage().filterColumns(Point); +// expect(Point.item.feature_layer.fields.length).to.be.eq( +// columns.length, +// ); +// } +// } +// } +// }); +// it(`create feature`, async () => { +// const connection = await getConnection(); + +// const Point = await newPointLayer( +// 'Clone of Point layer for .create feature test', +// ); +// const p = new Point(); +// p.test = 'test'; +// p.coordinates = [104, 52]; + +// await p.save(); + +// expect(p.id).to.eq(1); +// expect(Point.item).to.be.exist; +// if (Point.item) { +// const ngwFeature = await connection.driver.get( +// 'feature_layer.feature.item', +// null, +// { +// id: Point.item.resource.id, +// fid: p.id, +// }, +// ); +// expect(ngwFeature.id).to.eq(1); +// } +// }); +// it(`.save`, async () => { +// const Point = await newPointLayer('Clone of Point layer for .save test'); + +// const entities = Array.from(Array(5)).map((x, i) => { +// const p = new Point(); +// p.test = String(i + 1); +// p.coordinates = [104, 52]; +// return p; +// }); +// const savedEntities = await Point.save(entities); +// const ok = savedEntities.every((x) => { +// return String(x.id) === x.test; +// }); +// expect(ok).to.be.true; +// }); + +// it(`.findOne`, async () => { +// const Point = await newPointLayer( +// 'Clone of Point layer for .findOne test', +// ); + +// const entities = Array.from(Array(5)).map((x, i) => { +// const p = new Point(); +// p.number = i + 1; +// p.coordinates = [104, 52]; +// return p; +// }); +// await Point.save(entities); +// const findById = await Point.findOne(1); +// expect(findById).to.be.exist; +// if (findById) { +// expect(findById.id).to.be.eq(1); +// } +// }); +// }); +// });