From 2dcd50656a09bf9fcd70f2cfa76706b4b630cb92 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 13:11:15 +0300 Subject: [PATCH 01/73] delete: remove mapcolonies template tests --- .../anotherResourceName.spec.ts | 40 ---------------- .../anotherResource/helpers/requestSender.ts | 9 ---- .../resourceName/helpers/requestSender.ts | 13 ----- .../resourceName/resourceName.spec.ts | 47 ------------------- 4 files changed, 109 deletions(-) delete mode 100644 tests/integration/anotherResource/anotherResourceName.spec.ts delete mode 100644 tests/integration/anotherResource/helpers/requestSender.ts delete mode 100644 tests/integration/resourceName/helpers/requestSender.ts delete mode 100644 tests/integration/resourceName/resourceName.spec.ts diff --git a/tests/integration/anotherResource/anotherResourceName.spec.ts b/tests/integration/anotherResource/anotherResourceName.spec.ts deleted file mode 100644 index 29588869..00000000 --- a/tests/integration/anotherResource/anotherResourceName.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import jsLogger from '@map-colonies/js-logger'; -import { trace } from '@opentelemetry/api'; -import httpStatusCodes from 'http-status-codes'; -import { getApp } from '../../../src/app'; -import { SERVICES } from '../../../src/common/constants'; -import { IAnotherResourceModel } from '../../../src/anotherResource/models/anotherResourceManager'; -import { AnotherResourceRequestSender } from './helpers/requestSender'; - -describe('resourceName', function () { - let requestSender: AnotherResourceRequestSender; - beforeEach(function () { - const app = getApp({ - override: [ - { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, - { token: SERVICES.TRACER, provider: { useValue: trace.getTracer('testTracer') } }, - ], - useChild: true, - }); - requestSender = new AnotherResourceRequestSender(app); - }); - - describe('Happy Path', function () { - it('should return 200 status code and the resource', async function () { - const response = await requestSender.getResource(); - - expect(response.status).toBe(httpStatusCodes.OK); - expect(response).toSatisfyApiSpec(); - - const resource = response.body as IAnotherResourceModel; - expect(resource.kind).toBe('avi'); - expect(resource.isAlive).toBe(false); - }); - }); - describe('Bad Path', function () { - // All requests with status code of 400 - }); - describe('Sad Path', function () { - // All requests with status code 4XX-5XX - }); -}); diff --git a/tests/integration/anotherResource/helpers/requestSender.ts b/tests/integration/anotherResource/helpers/requestSender.ts deleted file mode 100644 index e9a0bed1..00000000 --- a/tests/integration/anotherResource/helpers/requestSender.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as supertest from 'supertest'; - -export class AnotherResourceRequestSender { - public constructor(private readonly app: Express.Application) {} - - public async getResource(): Promise { - return supertest.agent(this.app).get('/anotherResource').set('Content-Type', 'application/json'); - } -} diff --git a/tests/integration/resourceName/helpers/requestSender.ts b/tests/integration/resourceName/helpers/requestSender.ts deleted file mode 100644 index 0befb952..00000000 --- a/tests/integration/resourceName/helpers/requestSender.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as supertest from 'supertest'; - -export class ResourceNameRequestSender { - public constructor(private readonly app: Express.Application) {} - - public async getResource(): Promise { - return supertest.agent(this.app).get('/resourceName').set('Content-Type', 'application/json'); - } - - public async createResource(): Promise { - return supertest.agent(this.app).post('/resourceName').set('Content-Type', 'application/json'); - } -} diff --git a/tests/integration/resourceName/resourceName.spec.ts b/tests/integration/resourceName/resourceName.spec.ts deleted file mode 100644 index 7edad920..00000000 --- a/tests/integration/resourceName/resourceName.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import jsLogger from '@map-colonies/js-logger'; -import { trace } from '@opentelemetry/api'; -import httpStatusCodes from 'http-status-codes'; - -import { getApp } from '../../../src/app'; -import { SERVICES } from '../../../src/common/constants'; -import { IResourceNameModel } from '../../../src/resourceName/models/resourceNameManager'; -import { ResourceNameRequestSender } from './helpers/requestSender'; - -describe('resourceName', function () { - let requestSender: ResourceNameRequestSender; - beforeEach(function () { - const app = getApp({ - override: [ - { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, - { token: SERVICES.TRACER, provider: { useValue: trace.getTracer('testTracer') } }, - ], - useChild: true, - }); - requestSender = new ResourceNameRequestSender(app); - }); - - describe('Happy Path', function () { - it('should return 200 status code and the resource', async function () { - const response = await requestSender.getResource(); - - expect(response.status).toBe(httpStatusCodes.OK); - - const resource = response.body as IResourceNameModel; - expect(response).toSatisfyApiSpec(); - expect(resource.id).toBe(1); - expect(resource.name).toBe('ronin'); - expect(resource.description).toBe('can you do a logistics run?'); - }); - it('should return 200 status code and create the resource', async function () { - const response = await requestSender.createResource(); - - expect(response.status).toBe(httpStatusCodes.CREATED); - }); - }); - describe('Bad Path', function () { - // All requests with status code of 400 - }); - describe('Sad Path', function () { - // All requests with status code 4XX-5XX - }); -}); From be681886025423fb5948c62c03ceb7356e362081 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 13:12:08 +0300 Subject: [PATCH 02/73] fix: added await to getApp --- tests/integration/docs/docs.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/docs/docs.spec.ts b/tests/integration/docs/docs.spec.ts index eb4242f1..88f06840 100644 --- a/tests/integration/docs/docs.spec.ts +++ b/tests/integration/docs/docs.spec.ts @@ -7,15 +7,15 @@ import { DocsRequestSender } from './helpers/docsRequestSender'; describe('docs', function () { let requestSender: DocsRequestSender; - beforeEach(function () { - const app = getApp({ + beforeEach(async function () { + const app = await getApp({ override: [ { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, { token: SERVICES.TRACER, provider: { useValue: trace.getTracer('testTracer') } }, ], useChild: true, }); - requestSender = new DocsRequestSender(app); + requestSender = new DocsRequestSender(app.app); }); describe('Happy Path', function () { From 6ffad54cda58364f6b841f3ce965188637e7a44b Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 13:12:46 +0300 Subject: [PATCH 03/73] feat: exporting getTiles query params --- src/tile/controllers/tileController.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/tile/controllers/tileController.ts b/src/tile/controllers/tileController.ts index 786c5d45..27992fda 100644 --- a/src/tile/controllers/tileController.ts +++ b/src/tile/controllers/tileController.ts @@ -20,14 +20,16 @@ type GetResourceHandler = RequestHandler< message: string; }, undefined, - { - tile: string; - sub_tile?: string; - reduce_fuzzy_match?: string; - size?: string; - } + GetTilesQueryParams >; +export interface GetTilesQueryParams { + tile: string; + sub_tile?: string; + reduce_fuzzy_match?: string; + size?: string; +} + @injectable() export class TileController { private readonly createdResourceCounter: BoundCounter; From 86b5a54a4d7589e078a9353d5801e7f38efcb796 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 13:13:03 +0300 Subject: [PATCH 04/73] feat: created requestSender for tiles tests --- tests/integration/tile/helpers/requestSender.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/integration/tile/helpers/requestSender.ts diff --git a/tests/integration/tile/helpers/requestSender.ts b/tests/integration/tile/helpers/requestSender.ts new file mode 100644 index 00000000..2d8ec5b4 --- /dev/null +++ b/tests/integration/tile/helpers/requestSender.ts @@ -0,0 +1,15 @@ +import * as supertest from 'supertest'; +import { GetTilesQueryParams } from '../../../../src/tile/controllers/tileController'; + +export class TileRequestSender { + public constructor(private readonly app: Express.Application) {} + + public async getTiles(queryParams?: GetTilesQueryParams): Promise { + return supertest + .agent(this.app) + .get('/search/tiles/') + .set('Content-Type', 'application/json') + .set('X-API-Key', 'abc123') + .query(queryParams ?? {}); + } +} From 51b2785472a7d545b6e92fd3a794a5fc6f52df3e Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 13:13:40 +0300 Subject: [PATCH 05/73] feat: created tiles integration tests --- tests/integration/tile/tile.spec.ts | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/integration/tile/tile.spec.ts diff --git a/tests/integration/tile/tile.spec.ts b/tests/integration/tile/tile.spec.ts new file mode 100644 index 00000000..8dc966f4 --- /dev/null +++ b/tests/integration/tile/tile.spec.ts @@ -0,0 +1,57 @@ +import jsLogger from '@map-colonies/js-logger'; +import { trace } from '@opentelemetry/api'; +import httpStatusCodes from 'http-status-codes'; +import { getApp } from '../../../src/app'; +import { SERVICES } from '../../../src/common/constants'; +import { GetTilesQueryParams } from '../../../src/tile/controllers/tileController'; +import { TileRequestSender } from './helpers/requestSender'; + +describe('resourceName', function () { + let requestSender: TileRequestSender; + + beforeEach(async function () { + // elasticClient = await initElasticsearchClient(elasticDataSourceOptions); + const app = await getApp({ + override: [ + { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, + { token: SERVICES.TRACER, provider: { useValue: trace.getTracer('testTracer') } }, + ], + useChild: true, + }); + requestSender = new TileRequestSender(app.app); + }); + + describe('Happy Path', function () { + it('should return 200 status code and the resource', async function () { + const response = await requestSender.getTiles({ tile: 'בעל' }); + + expect(response.status).toBe(httpStatusCodes.OK); + expect(response).toSatisfyApiSpec(); + }); + }); + describe('Bad Path', function () { + // All requests with status code of 400 + it('Should return 400 status code and meessage "request/query must have required property \'tile\'"', async function () { + const message = "request/query must have required property 'tile'"; + + const response = await requestSender.getTiles(); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message }); + expect(response).toSatisfyApiSpec(); + }); + it('Should return 400 status code for unknown parameter', async function () { + const parameter = 'test1234'; + const message = `Unknown query parameter '${parameter}'`; + + const response = await requestSender.getTiles({ [parameter]: parameter } as unknown as GetTilesQueryParams); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message }); + expect(response).toSatisfyApiSpec(); + }); + }); + describe('Sad Path', function () { + // All requests with status code 4XX-5XX + }); +}); From 256443bc40dcd3398d546cef0c73ba973cf0cce7 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 15:42:21 +0300 Subject: [PATCH 06/73] chore: GetItemsQueryParams interface created and exported --- src/item/controllers/itemController.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/item/controllers/itemController.ts b/src/item/controllers/itemController.ts index 716f707a..a06d2457 100644 --- a/src/item/controllers/itemController.ts +++ b/src/item/controllers/itemController.ts @@ -16,16 +16,18 @@ type GetResourceHandler = RequestHandler< features: (Item | undefined)[]; }, undefined, - { - command_name: string; - tile?: string; - sub_tile?: string; - geo_context?: string; - reduce_fuzzy_match?: string; - size?: string; - } + GetItemsQueryParams >; +export interface GetItemsQueryParams { + command_name: string; + tile?: string; + sub_tile?: string; + geo_context?: string; + reduce_fuzzy_match?: string; + size?: string; +} + @injectable() export class ItemController { private readonly createdResourceCounter: BoundCounter; From 60459e6687d89b813f358de3075bdfb427089c51 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 15:43:25 +0300 Subject: [PATCH 07/73] feat: integration tests created for items --- .../integration/item/helpers/requestSender.ts | 15 +++++ tests/integration/item/item.spec.ts | 67 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 tests/integration/item/helpers/requestSender.ts create mode 100644 tests/integration/item/item.spec.ts diff --git a/tests/integration/item/helpers/requestSender.ts b/tests/integration/item/helpers/requestSender.ts new file mode 100644 index 00000000..6b07c6fd --- /dev/null +++ b/tests/integration/item/helpers/requestSender.ts @@ -0,0 +1,15 @@ +import * as supertest from 'supertest'; +import { GetItemsQueryParams } from '../../../../src/item/controllers/itemController'; + +export class ItemRequestSender { + public constructor(private readonly app: Express.Application) {} + + public async getItems(queryParams?: GetItemsQueryParams): Promise { + return supertest + .agent(this.app) + .get('/search/items/') + .set('Content-Type', 'application/json') + .set('X-API-Key', 'abc123') + .query(queryParams ?? {}); + } +} diff --git a/tests/integration/item/item.spec.ts b/tests/integration/item/item.spec.ts new file mode 100644 index 00000000..d1eb396b --- /dev/null +++ b/tests/integration/item/item.spec.ts @@ -0,0 +1,67 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import jsLogger from '@map-colonies/js-logger'; +import { trace } from '@opentelemetry/api'; +import httpStatusCodes from 'http-status-codes'; +import { getApp } from '../../../src/app'; +import { SERVICES } from '../../../src/common/constants'; +import { GetItemsQueryParams } from '../../../src/item/controllers/itemController'; +import { ItemRequestSender } from './helpers/requestSender'; + +describe('/items', function () { + let requestSender: ItemRequestSender; + + beforeEach(async function () { + const app = await getApp({ + override: [ + { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, + { token: SERVICES.TRACER, provider: { useValue: trace.getTracer('testTracer') } }, + ], + useChild: true, + }); + requestSender = new ItemRequestSender(app.app); + }); + + describe('Happy Path', function () { + it('should return 200 status code and the item', async function () { + const response = await requestSender.getItems({ command_name: '4805' }); + + expect(response.status).toBe(httpStatusCodes.OK); + expect(response).toSatisfyApiSpec(); + }); + it('should return 200 status code and empty response', async function () { + const response = await requestSender.getItems({ command_name: '48054805' }); + + expect(response.status).toBe(httpStatusCodes.OK); + expect(response).toSatisfyApiSpec(); + expect(response.body).toMatchObject({ + type: 'FeatureCollection', + features: [], + }); + }); + }); + describe('Bad Path', function () { + // All requests with status code of 400 + it('Should return 400 status code and meessage "request/query must have required property \'command_name\'"', async function () { + const message = "request/query must have required property 'command_name'"; + + const response = await requestSender.getItems(); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message }); + expect(response).toSatisfyApiSpec(); + }); + it('Should return 400 status code for unknown parameter', async function () { + const parameter = 'test1234'; + const message = `Unknown query parameter '${parameter}'`; + + const response = await requestSender.getItems({ [parameter]: parameter } as unknown as GetItemsQueryParams); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message }); + expect(response).toSatisfyApiSpec(); + }); + }); + describe('Sad Path', function () { + // All requests with status code 4XX-5XX + }); +}); From 75e9c349f1b0a048986af32b686c1ff2e001ff8c Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 16:28:30 +0300 Subject: [PATCH 08/73] chroe: created GetRoutesQueryParams and exported interface --- src/route/controllers/routeController.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/route/controllers/routeController.ts b/src/route/controllers/routeController.ts index a1155185..2232fde4 100644 --- a/src/route/controllers/routeController.ts +++ b/src/route/controllers/routeController.ts @@ -17,15 +17,17 @@ type GetResourceHandler = RequestHandler< features: (Route | undefined)[]; }, undefined, - { - command_name: string; - control_point?: string; - geo_context?: string; - reduce_fuzzy_match?: string; - size?: string; - } + GetRoutesQueryParams >; +export interface GetRoutesQueryParams { + command_name: string; + control_point?: string; + geo_context?: string; + reduce_fuzzy_match?: string; + size?: string; +} + @injectable() export class RouteController { private readonly createdResourceCounter: BoundCounter; From bbb3ad66c3de7c4f293175d0f055c516afcc5c5c Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 16:28:57 +0300 Subject: [PATCH 09/73] feat: created requestSender for route testing --- tests/integration/route/helpers/requestSender.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/integration/route/helpers/requestSender.ts diff --git a/tests/integration/route/helpers/requestSender.ts b/tests/integration/route/helpers/requestSender.ts new file mode 100644 index 00000000..767155ee --- /dev/null +++ b/tests/integration/route/helpers/requestSender.ts @@ -0,0 +1,15 @@ +import * as supertest from 'supertest'; +import { GetRoutesQueryParams } from '../../../../src/route/controllers/routeController'; + +export class RouteRequestSender { + public constructor(private readonly app: Express.Application) {} + + public async getRoutes(queryParams?: GetRoutesQueryParams): Promise { + return supertest + .agent(this.app) + .get('/search/routes/') + .set('Content-Type', 'application/json') + .set('X-API-Key', 'abc123') + .query(queryParams ?? {}); + } +} From fc9245dad576b26889c89e20b9cca2752bf2a76c Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 16:30:12 +0300 Subject: [PATCH 10/73] feat: created route integration testing --- tests/integration/route/route.spec.ts | 68 +++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/integration/route/route.spec.ts diff --git a/tests/integration/route/route.spec.ts b/tests/integration/route/route.spec.ts new file mode 100644 index 00000000..93b1500a --- /dev/null +++ b/tests/integration/route/route.spec.ts @@ -0,0 +1,68 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import jsLogger from '@map-colonies/js-logger'; +import { trace } from '@opentelemetry/api'; +import httpStatusCodes from 'http-status-codes'; +import { getApp } from '../../../src/app'; +import { SERVICES } from '../../../src/common/constants'; +import { GetRoutesQueryParams } from '../../../src/route/controllers/routeController'; +import { RouteRequestSender } from './helpers/requestSender'; + +describe('/routes', function () { + let requestSender: RouteRequestSender; + + beforeEach(async function () { + const app = await getApp({ + override: [ + { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, + { token: SERVICES.TRACER, provider: { useValue: trace.getTracer('testTracer') } }, + ], + useChild: true, + }); + requestSender = new RouteRequestSender(app.app); + }); + + describe('Happy Path', function () { + it('should return 200 status code and the route', async function () { + const response = await requestSender.getRoutes({ command_name: 'abc' }); + + expect(response.status).toBe(httpStatusCodes.OK); + expect(response).toSatisfyApiSpec(); + }); + it('should return 200 status code and empty response', async function () { + const response = await requestSender.getRoutes({ command_name: '48054805' }); + + expect(response.status).toBe(httpStatusCodes.OK); + + // expect(response).toSatisfyApiSpec(); // TODO: + expect(response.body).toMatchObject({ + type: 'FeatureCollection', + features: [], + }); + }); + }); + describe('Bad Path', function () { + // All requests with status code of 400 + it('Should return 400 status code and meessage "request/query must have required property \'command_name\'"', async function () { + const message = "request/query must have required property 'command_name'"; + + const response = await requestSender.getRoutes(); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message }); + expect(response).toSatisfyApiSpec(); + }); + it('Should return 400 status code for unknown parameter', async function () { + const parameter = 'test1234'; + const message = `Unknown query parameter '${parameter}'`; + + const response = await requestSender.getRoutes({ [parameter]: parameter } as unknown as GetRoutesQueryParams); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message }); + expect(response).toSatisfyApiSpec(); + }); + }); + describe('Sad Path', function () { + // All requests with status code 4XX-5XX + }); +}); From f0b63d586a1ec22eda7294305bc50ba26d6550ed Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Mon, 6 May 2024 16:31:21 +0300 Subject: [PATCH 11/73] added empty response test --- tests/integration/tile/tile.spec.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tests/integration/tile/tile.spec.ts b/tests/integration/tile/tile.spec.ts index 8dc966f4..001bd4bb 100644 --- a/tests/integration/tile/tile.spec.ts +++ b/tests/integration/tile/tile.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import jsLogger from '@map-colonies/js-logger'; import { trace } from '@opentelemetry/api'; import httpStatusCodes from 'http-status-codes'; @@ -6,11 +7,10 @@ import { SERVICES } from '../../../src/common/constants'; import { GetTilesQueryParams } from '../../../src/tile/controllers/tileController'; import { TileRequestSender } from './helpers/requestSender'; -describe('resourceName', function () { +describe('/tiles', function () { let requestSender: TileRequestSender; beforeEach(async function () { - // elasticClient = await initElasticsearchClient(elasticDataSourceOptions); const app = await getApp({ override: [ { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, @@ -22,12 +22,28 @@ describe('resourceName', function () { }); describe('Happy Path', function () { - it('should return 200 status code and the resource', async function () { + it('should return 200 status code and the tile', async function () { const response = await requestSender.getTiles({ tile: 'בעל' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); }); + it('should return 200 status code and the subtile', async function () { + const response = await requestSender.getTiles({ tile: 'יהם', sub_tile: '65' }); + + expect(response.status).toBe(httpStatusCodes.OK); + expect(response).toSatisfyApiSpec(); + }); + it('should return 200 status code and response empty array', async function () { + const response = await requestSender.getTiles({ tile: 'אבג' }); + + expect(response.status).toBe(httpStatusCodes.OK); + expect(response).toSatisfyApiSpec(); + expect(response.body).toMatchObject({ + type: 'FeatureCollection', + features: [], + }); + }); }); describe('Bad Path', function () { // All requests with status code of 400 From 444acb5dfe581f6463e2b9124e0c6d746932fd31 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Tue, 7 May 2024 10:06:54 +0300 Subject: [PATCH 12/73] changed tile --- tests/integration/tile/tile.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/tile/tile.spec.ts b/tests/integration/tile/tile.spec.ts index 001bd4bb..f7dab3de 100644 --- a/tests/integration/tile/tile.spec.ts +++ b/tests/integration/tile/tile.spec.ts @@ -23,19 +23,19 @@ describe('/tiles', function () { describe('Happy Path', function () { it('should return 200 status code and the tile', async function () { - const response = await requestSender.getTiles({ tile: 'בעל' }); + const response = await requestSender.getTiles({ tile: 'abc' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); }); it('should return 200 status code and the subtile', async function () { - const response = await requestSender.getTiles({ tile: 'יהם', sub_tile: '65' }); + const response = await requestSender.getTiles({ tile: 'abc', sub_tile: '65' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); }); it('should return 200 status code and response empty array', async function () { - const response = await requestSender.getTiles({ tile: 'אבג' }); + const response = await requestSender.getTiles({ tile: 'abc' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); From d2f887b91e30f8e03ab646aa554e28ffdfcb6c29 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Tue, 7 May 2024 10:07:47 +0300 Subject: [PATCH 13/73] fixed test case --- tests/integration/tile/tile.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/tile/tile.spec.ts b/tests/integration/tile/tile.spec.ts index f7dab3de..967bd7db 100644 --- a/tests/integration/tile/tile.spec.ts +++ b/tests/integration/tile/tile.spec.ts @@ -35,7 +35,7 @@ describe('/tiles', function () { expect(response).toSatisfyApiSpec(); }); it('should return 200 status code and response empty array', async function () { - const response = await requestSender.getTiles({ tile: 'abc' }); + const response = await requestSender.getTiles({ tile: 'xyz' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); From f2d92dbd1b134e51f975cb0faa6dd2d2f67cd8b8 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 13:33:39 +0300 Subject: [PATCH 14/73] updated default password --- config/default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/default.json b/config/default.json index 6218fe53..ef8c0e52 100644 --- a/config/default.json +++ b/config/default.json @@ -44,7 +44,7 @@ "host": "localhost", "port": 5432, "username": "postgres", - "password": "test1234", + "password": "postgres", "enableSslAuth": false, "sslPaths": { "ca": "", From e4d12a15ae43b7c11fa17107cff6014dd7560703 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 13:52:26 +0300 Subject: [PATCH 15/73] added config to tests enviorment --- config/test.json | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/config/test.json b/config/test.json index 0967ef42..486b9524 100644 --- a/config/test.json +++ b/config/test.json @@ -1 +1,32 @@ -{} +{ + "db": { + "elastic": { + "node": "http://localhost:9200", + "auth": { + "username": "elastic", + "password": "changeme" + }, + "requestTimeout": 60000, + "properties": { + "controlIndex": "geocoder_control_tests", + "nlpIndex": "geocoder_control_tests", + "size": 3 + } + }, + "postgresql": { + "type": "postgres", + "host": "localhost", + "port": 5432, + "username": "postgres", + "password": "test1234", + "enableSslAuth": false, + "sslPaths": { + "ca": "", + "key": "", + "cert": "" + }, + "database": "postgres", + "schema": "geocoder" + } + } +} From 7271dbbff4a9fb3860db9c2b8603eec902a23883 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 13:52:43 +0300 Subject: [PATCH 16/73] created dev scripts with mock data --- devScripts/elasticsearchData.json | 145 ++++++++++++++++++++++++++++++ devScripts/importDataToElastic.ts | 20 +++++ devScripts/index.ts | 5 ++ 3 files changed, 170 insertions(+) create mode 100644 devScripts/elasticsearchData.json create mode 100644 devScripts/importDataToElastic.ts create mode 100644 devScripts/index.ts diff --git a/devScripts/elasticsearchData.json b/devScripts/elasticsearchData.json new file mode 100644 index 00000000..6cdbb1ae --- /dev/null +++ b/devScripts/elasticsearchData.json @@ -0,0 +1,145 @@ +[ + { + "_id": "CONTROL.ITEMS", + "_score": 1, + "_source": { + "type": "Feature", + "id": 27, + "geometry": { + "coordinates": [ + [ + [98.96871358832425, 18.77187541003238], + [98.96711613001014, 18.772012912146167], + [98.9668257091372, 18.77957500633211], + [98.96517988589727, 18.783516234000658], + [98.96305002071, 18.786174113473763], + [98.96222710028087, 18.786036643850125], + [98.9615009529004, 18.784478609414165], + [98.96096850521184, 18.78324114944766], + [98.96058105300438, 18.74932410944021], + [98.96029062202649, 18.747169677704846], + [98.9619364723165, 18.74666541646775], + [98.96479250629358, 18.7514784826093], + [98.96401797557468, 18.75193687161918], + [98.96614791571238, 18.754412116891245], + [98.96639000300826, 18.75940841151673], + [98.96779381973744, 18.759133392649602], + [98.96798745662056, 18.76018763174328], + [98.96789063809456, 18.761746062357858], + [98.96905242991687, 18.763487833908357], + [98.96871358832425, 18.77187541003238] + ] + ], + "type": "Polygon" + }, + "properties": { + "OBJECTID": 27, + "F_CODE": 2300, + "F_ATT": 602, + "VIEW_SCALE_50K_CONTROL": 604, + "NAME": null, + "GFID": "{93C8C8E2-6AAB-4A84-BBF0-5B10E6F90938}", + "OBJECT_COMMAND_NAME": "4805", + "SUB_TILE_NAME": null, + "TILE_NAME": "DEF", + "TILE_ID": "36, 7300, 3560", + "SUB_TILE_ID": "36", + "SHAPE.AREA": 2.65, + "SHAPE.LEN": 0.0044192097656775, + "LAYER_NAME": "CONTROL.ITEMS", + "ENTITY_HEB": "airport", + "TYPE": "ITEM" + } + } + }, + { + "_id": "CONTROL.SUB_TILES", + "_score": 1, + "_source": { + "type": "Feature", + "id": 13668, + "geometry": { + "coordinates": [ + [ + [27.149158174343427, 35.63159611670335], + [27.149274355343437, 35.64061707270338], + [27.138786228343463, 35.640716597703374], + [27.13867103934342, 35.631695606703374], + [27.149158174343427, 35.63159611670335] + ] + ], + "type": "Polygon" + }, + "properties": { + "OBJECTID": 13668, + "SUB_TILE_ID": "65", + "TILE_NAME": "GRC", + "NAME": "somePlace", + "ZON": 36, + "LAYER_NAME": "CONTROL.SUB_TILES", + "TYPE": "SUB_TILE" + } + } + }, + { + "_id": "CONTROL.ROUTES", + "_score": 1, + "_source": { + "type": "Feature", + "id": 2, + "geometry": { + "coordinates": [ + [13.448493352142947, 52.31016611400918], + [13.447219581381603, 52.313370282889224], + [13.448088381125075, 52.31631514453963], + [13.450458681234068, 52.31867376333767], + [13.451112278530388, 52.32227665244022], + [13.449728938644029, 52.32463678850752], + [13.445021899434977, 52.32863442881066], + [13.444723882330948, 52.340023400115086], + [13.446229682887974, 52.34532799609971] + ], + "type": "LineString" + }, + "properties": { + "OBJECTID": 2, + "OBJECT_COMMAND_NAME": "route96", + "FIRST_GFID": null, + "SHAPE_Length": 4.1, + "F_CODE": 8754, + "F_ATT": 951, + "LAYER_NAME": "CONTROL.ROUTES", + "ENTITY_HEB": "route96", + "TYPE": "ROUTE" + } + } + }, + { + "_id": "CONTROL.TILES", + "_score": 1, + "_source": { + "type": "Feature", + "id": 52, + "geometry": { + "coordinates": [ + [ + [12.539507865186607, 41.851751203650096], + [12.536787075186538, 41.94185043165008], + [12.42879133518656, 41.93952837265009], + [12.431625055186686, 41.84943698365008], + [12.539507865186607, 41.851751203650096] + ] + ], + "type": "Polygon" + }, + "properties": { + "OBJECTID": 52, + "ZONE": "37", + "TILE_NAME": "RIT", + "TILE_ID": null, + "LAYER_NAME": "CONTROL.TILES", + "TYPE": "TILE" + } + } + } +] diff --git a/devScripts/importDataToElastic.ts b/devScripts/importDataToElastic.ts new file mode 100644 index 00000000..9836e52d --- /dev/null +++ b/devScripts/importDataToElastic.ts @@ -0,0 +1,20 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/naming-convention */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +import { Client } from '@elastic/elasticsearch'; +import config from '../config/test.json'; +import data from './elasticsearchData.json'; + +const main = async (): Promise => { + const client = new Client({ node: config.db.elastic.node as string }); + + for (const item of data) { + await client.index({ + index: config.db.elastic.properties.controlIndex as string, + id: item._id as string, + body: item._source, + }); + } +}; + +export default main; diff --git a/devScripts/index.ts b/devScripts/index.ts new file mode 100644 index 00000000..1e50e7bd --- /dev/null +++ b/devScripts/index.ts @@ -0,0 +1,5 @@ +import importDataToElastic from './importDataToElastic'; + +importDataToElastic() + .then(() => console.log('Success import data to elastic')) + .catch(console.error); From 8e4320e1dcc9a85e179c9191f2d796a4079d0077 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 13:53:15 +0300 Subject: [PATCH 17/73] fix: changed parameters according to the new mock data --- tests/integration/route/route.spec.ts | 2 +- tests/integration/tile/tile.spec.ts | 55 ++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/tests/integration/route/route.spec.ts b/tests/integration/route/route.spec.ts index 93b1500a..db0747ca 100644 --- a/tests/integration/route/route.spec.ts +++ b/tests/integration/route/route.spec.ts @@ -23,7 +23,7 @@ describe('/routes', function () { describe('Happy Path', function () { it('should return 200 status code and the route', async function () { - const response = await requestSender.getRoutes({ command_name: 'abc' }); + const response = await requestSender.getRoutes({ command_name: 'route96' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); diff --git a/tests/integration/tile/tile.spec.ts b/tests/integration/tile/tile.spec.ts index 967bd7db..abd5bd6e 100644 --- a/tests/integration/tile/tile.spec.ts +++ b/tests/integration/tile/tile.spec.ts @@ -23,17 +23,68 @@ describe('/tiles', function () { describe('Happy Path', function () { it('should return 200 status code and the tile', async function () { - const response = await requestSender.getTiles({ tile: 'abc' }); + const response = await requestSender.getTiles({ tile: 'RIT' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); + expect(response.body).toMatchObject({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + coordinates: [ + [ + [12.539507865186607, 41.851751203650096], + [12.536787075186538, 41.94185043165008], + [12.42879133518656, 41.93952837265009], + [12.431625055186686, 41.84943698365008], + [12.539507865186607, 41.851751203650096], + ], + ], + type: 'Polygon', + }, + properties: { + TILE_NAME: 'RIT', + TYPE: 'TILE', + }, + }, + ], + }); }); + it('should return 200 status code and the subtile', async function () { - const response = await requestSender.getTiles({ tile: 'abc', sub_tile: '65' }); + const response = await requestSender.getTiles({ tile: 'GRC', sub_tile: '65' }); expect(response.status).toBe(httpStatusCodes.OK); expect(response).toSatisfyApiSpec(); + expect(response.body).toMatchObject({ + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + coordinates: [ + [ + [27.149158174343427, 35.63159611670335], + [27.149274355343437, 35.64061707270338], + [27.138786228343463, 35.640716597703374], + [27.13867103934342, 35.631695606703374], + [27.149158174343427, 35.63159611670335], + ], + ], + type: 'Polygon', + }, + properties: { + SUB_TILE_ID: '65', + TILE_NAME: 'GRC', + TYPE: 'SUB_TILE', + }, + }, + ], + }); }); + it('should return 200 status code and response empty array', async function () { const response = await requestSender.getTiles({ tile: 'xyz' }); From 4fb40b526414af4499e331ea2d262cac66d69e1a Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 13:54:43 +0300 Subject: [PATCH 18/73] feat(package.json): added dev:scripts script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9495eec4..1b7f4fae 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "start:dev": "npm run build && cd dist && node --enable-source-maps ./index.js", "assets:copy": "copyfiles -f ./config/* ./dist/config && copyfiles -f ./openapi3.yaml ./dist/ && copyfiles ./package.json dist", "clean": "rimraf dist", - "install": "npx husky install" + "install": "npx husky install", + "dev:scripts": "npx ts-node ./devScripts/index.ts" }, "directories": { "test": "tests" From d609b890c22042974f7d4c078013bf53684de712 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 13:55:03 +0300 Subject: [PATCH 19/73] fix(tsconfig): added resolveJsonModule: true --- tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index f5df9461..59326bc4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,8 @@ "allowSyntheticDefaultImports": true, "moduleResolution": "node", "experimentalDecorators": true, - "emitDecoratorMetadata": true + "emitDecoratorMetadata": true, + "resolveJsonModule": true, }, "include": ["src"], "exclude": ["node_modules", "dist", "tests"] From be1a615f9f6affc6ff01038606eeccee4521ee57 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 13:55:26 +0300 Subject: [PATCH 20/73] fix(openapi3): changed oneOf to anyOf --- openapi3.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openapi3.yaml b/openapi3.yaml index e56149f3..b8f59c88 100644 --- a/openapi3.yaml +++ b/openapi3.yaml @@ -95,7 +95,7 @@ paths: content: application/json: schema: - oneOf: + anyOf: - $ref: "#/components/schemas/tilesSchema" - $ref: "#/components/schemas/routesSchema" - $ref: "#/components/schemas/itemsSchema" @@ -226,7 +226,7 @@ paths: content: application/json: schema: - oneOf: + anyOf: - $ref: "#/components/schemas/routesSchema" - $ref: "#/components/schemas/itemsSchema" 400: From 197a9102fc71ea0e2a9c2980612a3e2d833e31fb Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:41:45 +0300 Subject: [PATCH 21/73] fix: updated password --- config/test.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/test.json b/config/test.json index 486b9524..bd56b86e 100644 --- a/config/test.json +++ b/config/test.json @@ -18,7 +18,7 @@ "host": "localhost", "port": 5432, "username": "postgres", - "password": "test1234", + "password": "postgres", "enableSslAuth": false, "sslPaths": { "ca": "", From 6c4af8908f376682d97fec6a6bd542f032ce4ca7 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:42:08 +0300 Subject: [PATCH 22/73] fixed zone --- devScripts/elasticsearchData.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devScripts/elasticsearchData.json b/devScripts/elasticsearchData.json index 6cdbb1ae..856ca077 100644 --- a/devScripts/elasticsearchData.json +++ b/devScripts/elasticsearchData.json @@ -75,7 +75,7 @@ "SUB_TILE_ID": "65", "TILE_NAME": "GRC", "NAME": "somePlace", - "ZON": 36, + "ZON": 35, "LAYER_NAME": "CONTROL.SUB_TILES", "TYPE": "SUB_TILE" } From 8f71971e5981f3ba59ea302f637dfaa9d5dd2cd5 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:42:29 +0300 Subject: [PATCH 23/73] feat: exported query params interfaces --- src/latLon/controllers/latLonController.ts | 46 ++++++++++++---------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/latLon/controllers/latLonController.ts b/src/latLon/controllers/latLonController.ts index 95c8208e..563c72af 100644 --- a/src/latLon/controllers/latLonController.ts +++ b/src/latLon/controllers/latLonController.ts @@ -15,10 +15,7 @@ type GetLatLonToTileHandler = RequestHandler< subTileNumber: string[]; }, undefined, - { - lat: number; - lon: number; - } + GetLatLonToTileQueryParams >; type GetTileToLatLonHandler = RequestHandler< @@ -33,33 +30,40 @@ type GetTileToLatLonHandler = RequestHandler< }; }, undefined, - { - tile: string; - sub_tile_number: number[]; - } + GetTileToLatLonQueryParams >; -type GetLatLonToMgrsHandler = RequestHandler< - undefined, - { mgrs: string }, - undefined, - { - lat: number; - lon: number; - accuracy?: number; - } ->; +type GetLatLonToMgrsHandler = RequestHandler; -type getMgrsToLatLonHandler = RequestHandler< +type GetMgrsToLatLonHandler = RequestHandler< undefined, { lat: number; lon: number; }, undefined, - { mgrs: string } + GetMgrsToLatLonQueryParams >; +export interface GetLatLonToTileQueryParams { + lat: number; + lon: number; +} + +export interface GetTileToLatLonQueryParams { + tile: string; + sub_tile_number: number[]; +} + +export interface GetLatLonToMgrsQueryParams { + lat: number; + lon: number; + accuracy?: number; +} +export interface GetMgrsToLatLonQueryParams { + mgrs: string; +} + @injectable() export class LatLonController { private readonly createdResourceCounter: BoundCounter; @@ -112,7 +116,7 @@ export class LatLonController { } }; - public mgrsToLatlon: getMgrsToLatLonHandler = (req, res, next) => { + public mgrsToLatlon: GetMgrsToLatLonHandler = (req, res, next) => { try { const { mgrs } = req.query; From 0ffc2c7094d2eb80a7e7f205e8578a29c2e3d975 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:42:50 +0300 Subject: [PATCH 24/73] feat: added types and testTimeout increased to 15000 --- tests/configurations/unit/jest.config.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/configurations/unit/jest.config.js b/tests/configurations/unit/jest.config.js index 68d6af7b..3516bfcf 100644 --- a/tests/configurations/unit/jest.config.js +++ b/tests/configurations/unit/jest.config.js @@ -1,4 +1,5 @@ -module.exports = { +/** @type {import('jest').Config} */ +const config = { transform: { '^.+\\.ts$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }], }, @@ -31,4 +32,7 @@ module.exports = { statements: -10, }, }, + testTimeout: 15000, }; + +module.exports = config; From f22552b47fc09b28af362afb409a3b8ee785d8fe Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:43:17 +0300 Subject: [PATCH 25/73] fix: updated openapi3 to return the right type --- openapi3.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openapi3.yaml b/openapi3.yaml index b8f59c88..16e208ea 100644 --- a/openapi3.yaml +++ b/openapi3.yaml @@ -396,7 +396,12 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/tilesSchema" + type: object + properties: + lat: + type: number + lon: + type: number 400: "$ref": "#/components/responses/BadRequest" 401: From 40332d996ef5ccbb28c99fe0e7fb1b2716460ce3 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:44:01 +0300 Subject: [PATCH 26/73] added dataSource.ts for typeorm migration --- dataSource.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 dataSource.ts diff --git a/dataSource.ts b/dataSource.ts new file mode 100644 index 00000000..ad31f0f6 --- /dev/null +++ b/dataSource.ts @@ -0,0 +1,13 @@ +import config from 'config'; +import { DataSource } from 'typeorm'; +import { createConnectionOptions } from './src/common/postgresql'; +import { PostgresDbConfig } from './src/common/interfaces'; + +const connectionOptions = config.get('db.postgresql'); + +export const appDataSource = new DataSource({ + ...createConnectionOptions(connectionOptions), + entities: ['src/**/DAL/*.ts'], + migrationsTableName: 'migrations_table', + migrations: ['db/migrations/*.ts'], +}); From 6605d294378691743985ff6f3db9a779623f6741 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:44:33 +0300 Subject: [PATCH 27/73] feat: added latLon integration testing --- .../latLon/helpers/requestSender.ts | 49 +++++++ tests/integration/latLon/latLon.spec.ts | 124 ++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 tests/integration/latLon/helpers/requestSender.ts create mode 100644 tests/integration/latLon/latLon.spec.ts diff --git a/tests/integration/latLon/helpers/requestSender.ts b/tests/integration/latLon/helpers/requestSender.ts new file mode 100644 index 00000000..1cada784 --- /dev/null +++ b/tests/integration/latLon/helpers/requestSender.ts @@ -0,0 +1,49 @@ +import * as supertest from 'supertest'; +import { + GetLatLonToTileQueryParams, + GetTileToLatLonQueryParams, + GetLatLonToMgrsQueryParams, + GetMgrsToLatLonQueryParams, +} from '../../../../src/latLon/controllers/latLonController'; + +const PREFIX = '/lookup'; + +export class LatLonRequestSender { + public constructor(private readonly app: Express.Application) {} + + public async getLatlonToTile(queryParams?: GetLatLonToTileQueryParams): Promise { + return supertest + .agent(this.app) + .get(`${PREFIX}/latlonToTile`) + .set('Content-Type', 'application/json') + .set('X-API-Key', 'abc123') + .query(queryParams ?? {}); + } + + public async getTileToLatLon(queryParams?: GetTileToLatLonQueryParams): Promise { + return supertest + .agent(this.app) + .get(`${PREFIX}/tileToLatLon`) + .set('Content-Type', 'application/json') + .set('X-API-Key', 'abc123') + .query(queryParams ?? {}); + } + + public async getLatlonToMgrs(queryParams?: GetLatLonToMgrsQueryParams): Promise { + return supertest + .agent(this.app) + .get(`${PREFIX}/latlonToMgrs`) + .set('Content-Type', 'application/json') + .set('X-API-Key', 'abc123') + .query(queryParams ?? {}); + } + + public async getMgrsToLatlon(queryParams?: GetMgrsToLatLonQueryParams): Promise { + return supertest + .agent(this.app) + .get(`${PREFIX}/mgrsToLatLon`) + .set('Content-Type', 'application/json') + .set('X-API-Key', 'abc123') + .query(queryParams ?? {}); + } +} diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts new file mode 100644 index 00000000..cb44de7b --- /dev/null +++ b/tests/integration/latLon/latLon.spec.ts @@ -0,0 +1,124 @@ +/* eslint-disable @typescript-eslint/unbound-method */ +/* eslint-disable @typescript-eslint/naming-convention */ +import jsLogger from '@map-colonies/js-logger'; +import { trace } from '@opentelemetry/api'; +import httpStatusCodes from 'http-status-codes'; +import supertest from 'supertest'; +import { getApp } from '../../../src/app'; +import { SERVICES } from '../../../src/common/constants'; +import { LatLonRequestSender } from './helpers/requestSender'; + +describe('/latLon', function () { + let requestSender: LatLonRequestSender; + + beforeEach(async function () { + const app = await getApp({ + override: [ + { token: SERVICES.LOGGER, provider: { useValue: jsLogger({ enabled: false }) } }, + { token: SERVICES.TRACER, provider: { useValue: trace.getTracer('testTracer') } }, + ], + useChild: true, + }); + requestSender = new LatLonRequestSender(app.app); + }, 20000); + + describe('Happy Path', function () { + it('should return 200 status code and lat-lon from mgrs', async function () { + const response = await requestSender.getMgrsToLatlon({ mgrs: '18TWL8565011369' }); + + expect(response.status).toBe(httpStatusCodes.OK); + expect(response).toSatisfyApiSpec(); + expect(response.body).toMatchObject({ + lat: 40.74882151233783, + lon: -73.98543192220956, + }); + }); + + it('should return 200 status code and mgrs from lat-lon', async function () { + const reponse = await requestSender.getLatlonToMgrs({ + lat: 40.74882151233783, + lon: -73.98543192220956, + }); + + expect(reponse.status).toBe(httpStatusCodes.OK); + expect(reponse).toSatisfyApiSpec(); + expect(reponse.body).toMatchObject({ + mgrs: '18TWL8565011369', + }); + }); + }); + describe('Bad Path', function () { + // All requests with status code of 400 + // describe('Check for missing required parameters', () => { + // test.each([ + // [requestSender.getLatlonToMgrs, ['lat', 'lon']], + // [requestSender.getMgrsToLatlon, ['mgrs']], + // [requestSender.getLatlonToTile, ['lat', 'lon']], + // [requestSender.getTileToLatLon, ['tile', 'sub_tile_number']], + // ])( + // 'Should return 400 status code and meessage "request/query must have required property \'%s\'"', + // async function (request, missingProperties) { + // const message = 'request/query must have required property'; + + // const response = await request(); + + // expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + // expect(response.body).toMatchObject({ message: missingProperties.map((txt) => `${message} '${txt}'`).join(', ') }); + // expect(response).toSatisfyApiSpec(); + // } + // ); + // }); + + it('abc', async function () { + const arr = [ + { + request: requestSender.getLatlonToMgrs, + missingProperties: ['lat', 'lon'], + }, + { + request: requestSender.getMgrsToLatlon, + missingProperties: ['mgrs'], + }, + { + request: requestSender.getLatlonToTile, + missingProperties: ['lat', 'lon'], + }, + { + request: requestSender.getTileToLatLon, + missingProperties: ['tile', 'sub_tile_number'], + }, + ]; + + for (const { request, missingProperties } of arr) { + const message = 'request/query must have required property'; + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + const response: supertest.Response = await request(); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message: missingProperties.map((txt) => `${message} '${txt}'`).join(', ') }); + expect(response).toSatisfyApiSpec(); + } + }); + + // describe('Check for invalid parameters', () => { + // test.each([[requestSender.getLatlonToMgrs], [requestSender.getMgrsToLatlon], [requestSender.getLatlonToTile], [requestSender.getTileToLatLon]])( + // 'Should return 400 status code for unknown parameter', + // async function (request) { + // const parameter = 'test1234'; + // const message = `Unknown query parameter '${parameter}'`; + + // const response = await request({ [parameter]: parameter } as never); + + // expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + // expect(response.body).toMatchObject({ message }); + // expect(response).toSatisfyApiSpec(); + // } + // ); + // }); + }); + describe('Sad Path', function () { + // All requests with status code 4XX-5XX + }); +}); From ce1efde6bd6991a9af743074a84e4274ba0c2b5a Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Wed, 8 May 2024 18:44:51 +0300 Subject: [PATCH 28/73] feat: added typeorm migration scripts --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b7f4fae..f2dd2c26 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,11 @@ "assets:copy": "copyfiles -f ./config/* ./dist/config && copyfiles -f ./openapi3.yaml ./dist/ && copyfiles ./package.json dist", "clean": "rimraf dist", "install": "npx husky install", - "dev:scripts": "npx ts-node ./devScripts/index.ts" + "dev:scripts": "npx ts-node ./devScripts/index.ts", + "typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js -d dataSource.ts", + "migration:create": "npm run typeorm migration:generate", + "migration:run": "npm run typeorm migration:run", + "migration:revert": "npm run typeorm migration:revert" }, "directories": { "test": "tests" From 5ac81d3cebeed629b585e84fae5635784b3c404a Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 08:36:34 +0300 Subject: [PATCH 29/73] fix: fixed test cases for missing required properties and invalid ones --- tests/integration/latLon/latLon.spec.ts | 72 +++++++++++-------------- 1 file changed, 31 insertions(+), 41 deletions(-) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index cb44de7b..12e0aedd 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -49,42 +49,22 @@ describe('/latLon', function () { }); describe('Bad Path', function () { // All requests with status code of 400 - // describe('Check for missing required parameters', () => { - // test.each([ - // [requestSender.getLatlonToMgrs, ['lat', 'lon']], - // [requestSender.getMgrsToLatlon, ['mgrs']], - // [requestSender.getLatlonToTile, ['lat', 'lon']], - // [requestSender.getTileToLatLon, ['tile', 'sub_tile_number']], - // ])( - // 'Should return 400 status code and meessage "request/query must have required property \'%s\'"', - // async function (request, missingProperties) { - // const message = 'request/query must have required property'; - - // const response = await request(); - - // expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); - // expect(response.body).toMatchObject({ message: missingProperties.map((txt) => `${message} '${txt}'`).join(', ') }); - // expect(response).toSatisfyApiSpec(); - // } - // ); - // }); - - it('abc', async function () { + it('Check for missing required parameters', async function () { const arr = [ { - request: requestSender.getLatlonToMgrs, + request: requestSender.getLatlonToMgrs(), missingProperties: ['lat', 'lon'], }, { - request: requestSender.getMgrsToLatlon, + request: requestSender.getMgrsToLatlon(), missingProperties: ['mgrs'], }, { - request: requestSender.getLatlonToTile, + request: requestSender.getLatlonToTile(), missingProperties: ['lat', 'lon'], }, { - request: requestSender.getTileToLatLon, + request: requestSender.getTileToLatLon(), missingProperties: ['tile', 'sub_tile_number'], }, ]; @@ -92,9 +72,7 @@ describe('/latLon', function () { for (const { request, missingProperties } of arr) { const message = 'request/query must have required property'; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - const response: supertest.Response = await request(); + const response: supertest.Response = await request; expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); expect(response.body).toMatchObject({ message: missingProperties.map((txt) => `${message} '${txt}'`).join(', ') }); @@ -102,21 +80,33 @@ describe('/latLon', function () { } }); - // describe('Check for invalid parameters', () => { - // test.each([[requestSender.getLatlonToMgrs], [requestSender.getMgrsToLatlon], [requestSender.getLatlonToTile], [requestSender.getTileToLatLon]])( - // 'Should return 400 status code for unknown parameter', - // async function (request) { - // const parameter = 'test1234'; - // const message = `Unknown query parameter '${parameter}'`; + it('abc', async function () { + const parameter = 'test1234'; + const message = `Unknown query parameter '${parameter}'`; + + const arr = [ + { + request: requestSender.getLatlonToMgrs({ [parameter]: parameter } as never), + }, + { + request: requestSender.getMgrsToLatlon({ [parameter]: parameter } as never), + }, + { + request: requestSender.getLatlonToTile({ [parameter]: parameter } as never), + }, + { + request: requestSender.getTileToLatLon({ [parameter]: parameter } as never), + }, + ]; - // const response = await request({ [parameter]: parameter } as never); + for (const { request } of arr) { + const response = await request; - // expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); - // expect(response.body).toMatchObject({ message }); - // expect(response).toSatisfyApiSpec(); - // } - // ); - // }); + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message }); + expect(response).toSatisfyApiSpec(); + } + }); }); describe('Sad Path', function () { // All requests with status code 4XX-5XX From e87b598a6420c7e56d998ad4bcd149c50f295a26 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 08:51:52 +0300 Subject: [PATCH 30/73] fix: updated returned schema on /lookup/latLonToTile --- openapi3.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi3.yaml b/openapi3.yaml index 16e208ea..53c2a6e1 100644 --- a/openapi3.yaml +++ b/openapi3.yaml @@ -269,7 +269,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/subTileSchema" + $ref: "#/components/schemas/tilesSchema" 400: "$ref": "#/components/responses/BadRequest" 401: From 6cbebe4c186154b44db818ffde15b5beb2a51f28 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 08:53:35 +0300 Subject: [PATCH 31/73] fix: ignoring .DS_Store file when developing on macos --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index db58f04b..943c2001 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,6 @@ dist # Jest jest_html_reporters.html reports + +# for MacOS Developers +.DS_Store From 95c5b9a23170c502f6cd24eac69ff48c9c89e613 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 15:05:03 +0300 Subject: [PATCH 32/73] feat: created mock data script for tile_lat_lon --- devScripts/importToPostgres.ts | 45 ++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 devScripts/importToPostgres.ts diff --git a/devScripts/importToPostgres.ts b/devScripts/importToPostgres.ts new file mode 100644 index 00000000..1580282a --- /dev/null +++ b/devScripts/importToPostgres.ts @@ -0,0 +1,45 @@ +import { DataSource } from 'typeorm'; +import { createConnectionOptions } from '../src/common/postgresql'; +import config from '../config/test.json'; +import { PostgresDbConfig } from '../src/common/interfaces'; + +export default async function createDatabaseClient(): Promise { + const connectionOptions = config.db.postgresql as PostgresDbConfig; + const connection = new DataSource({ + ...createConnectionOptions(connectionOptions), + }); + + await connection.initialize(); + + await connection.query(` + CREATE TABLE IF NOT EXISTS ${config.db.postgresql.schema}.tile_lat_lon + ( + pk integer NOT NULL, + tile_name text COLLATE pg_catalog."default", + zone text COLLATE pg_catalog."default", + min_x text COLLATE pg_catalog."default", + min_y text COLLATE pg_catalog."default", + ext_min_x integer, + ext_min_y integer, + ext_max_x integer, + ext_max_y integer, + CONSTRAINT tile_lat_lon_pkey PRIMARY KEY (pk) + ) + `); + + await connection.query(` + INSERT INTO ${config.db.postgresql.schema}.tile_lat_lon( + pk, tile_name, zone, min_x, min_y, ext_min_x, ext_min_y, ext_max_x, ext_max_y) + VALUES (1, 'BRN', '33', '360000', '5820000', 360000, 5820000, 370000, 5830000); + `); + + await connection.query(` + INSERT INTO ${config.db.postgresql.schema}.tile_lat_lon( + pk, tile_name, zone, min_x, min_y, ext_min_x, ext_min_y, ext_max_x, ext_max_y) + VALUES (2, 'BMN', '32', '480000', '5880000', 480000, 5880000, 490000, 5890000); + `); + + console.log('PGSQL: Table created and data inserted'); + + await connection.destroy(); +} From 486d1ac0346c0907bffec976b53381f037e35aba Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 15:05:20 +0300 Subject: [PATCH 33/73] fix: changed schema name --- config/test.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/test.json b/config/test.json index bd56b86e..3654706c 100644 --- a/config/test.json +++ b/config/test.json @@ -26,7 +26,7 @@ "cert": "" }, "database": "postgres", - "schema": "geocoder" + "schema": "geocoder_test" } } } From 569c8f761b3367564b55584e72b77243860163cb Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 15:06:20 +0300 Subject: [PATCH 34/73] feat: updated dev scripts to init import data to postgresql --- devScripts/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/devScripts/index.ts b/devScripts/index.ts index 1e50e7bd..1ec5acdc 100644 --- a/devScripts/index.ts +++ b/devScripts/index.ts @@ -1,5 +1,10 @@ import importDataToElastic from './importDataToElastic'; +import importToPostgres from './importToPostgres'; importDataToElastic() .then(() => console.log('Success import data to elastic')) .catch(console.error); + +importToPostgres() + .then(() => console.log('Success import data to postgres')) + .catch(console.error); From 3d2e5dc76c3d88d3c8e5a01306969dd366ce5f36 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 15:06:49 +0300 Subject: [PATCH 35/73] fix: increaded timeout and added types --- tests/configurations/integration/jest.config.js | 2 ++ tests/configurations/unit/jest.config.js | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/configurations/integration/jest.config.js b/tests/configurations/integration/jest.config.js index 59a7646e..e9531ea6 100644 --- a/tests/configurations/integration/jest.config.js +++ b/tests/configurations/integration/jest.config.js @@ -1,3 +1,4 @@ +/** @type {import('jest').Config} */ module.exports = { transform: { '^.+\\.ts$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }], @@ -28,4 +29,5 @@ module.exports = { statements: -10, }, }, + testTimeout: 15000, }; diff --git a/tests/configurations/unit/jest.config.js b/tests/configurations/unit/jest.config.js index 3516bfcf..09d50dd6 100644 --- a/tests/configurations/unit/jest.config.js +++ b/tests/configurations/unit/jest.config.js @@ -1,5 +1,5 @@ /** @type {import('jest').Config} */ -const config = { +module.exports = { transform: { '^.+\\.ts$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }], }, @@ -34,5 +34,3 @@ const config = { }, testTimeout: 15000, }; - -module.exports = config; From 384ef1b802ed8912f17174f373ca8994e299427e Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 15:27:36 +0300 Subject: [PATCH 36/73] feat: added tests for lat-lon to tile --- tests/integration/latLon/latLon.spec.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index 12e0aedd..5212f451 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -46,6 +46,20 @@ describe('/latLon', function () { mgrs: '18TWL8565011369', }); }); + + it('should return 200 status code and tile from lat-lon', async function () { + const reponse = await requestSender.getLatlonToTile({ + lat: 52.57326537485767, + lon: 12.948781146422107, + }); + + expect(reponse.status).toBe(httpStatusCodes.OK); + expect(reponse).toSatisfyApiSpec(); + expect(reponse.body).toMatchObject({ + tileName: 'BRN', + subTileNumber: ['00', '00', '00'], + }); + }); }); describe('Bad Path', function () { // All requests with status code of 400 From a2b28e57c6fec75abb23a0bd1bc69e490f684424 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 15:27:58 +0300 Subject: [PATCH 37/73] feat: added test tile to lat-lon --- tests/integration/latLon/latLon.spec.ts | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index 5212f451..a35c2326 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -60,6 +60,36 @@ describe('/latLon', function () { subTileNumber: ['00', '00', '00'], }); }); + + it('should return 200 status code and lat-lon from tile', async function () { + const reponse = await requestSender.getTileToLatLon({ + tile: 'BRN', + sub_tile_number: [10, 10, 10], + }); + + expect(reponse.status).toBe(httpStatusCodes.OK); + expect(reponse).toSatisfyApiSpec(); + expect(reponse.body).toMatchObject({ + geometry: { + coordinates: [ + [ + [12.953293384350397, 52.512399536846765], + [12.953440643865289, 52.512402084451686], + [12.953436468347887, 52.51249192878939], + [12.95328920853307, 52.512489381176245], + [12.953293384350397, 52.512399536846765], + ], + ], + type: 'Polygon', + }, + type: 'Feature', + properties: { + TYPE: 'TILE', + SUB_TILE_NUMBER: [10, 10, 10], + TILE_NAME: 'BRN', + }, + }); + }); }); describe('Bad Path', function () { // All requests with status code of 400 From 2b3e856a6b948bd111162bfd0d0643380d9ccfd9 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 15:28:22 +0300 Subject: [PATCH 38/73] fix: updated description --- tests/integration/latLon/latLon.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index a35c2326..2de05eb0 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -124,7 +124,7 @@ describe('/latLon', function () { } }); - it('abc', async function () { + it('test for checking unspecified query parameter', async function () { const parameter = 'test1234'; const message = `Unknown query parameter '${parameter}'`; From ec86020ec7cafa0554aa5abb0cb180faff508c37 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 16:36:30 +0300 Subject: [PATCH 39/73] feat: added test cases for status code 400 --- tests/integration/latLon/latLon.spec.ts | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index 2de05eb0..59d62d12 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -151,6 +151,46 @@ describe('/latLon', function () { expect(response).toSatisfyApiSpec(); } }); + + it('should return 400 and check that all numbers are positive', async function () { + const message = "Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers"; + + for (let i = 0; i < 3; i++) { + const arr = new Array(3).fill(10); + arr[i] = 0; + + const response = await requestSender.getTileToLatLon({ + tile: 'BRN', + sub_tile_number: [0, 0, 0], + }); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ + message, + }); + expect(response).toSatisfyApiSpec(); + } + }); + + it('should return 400 for lat-lon that outside the grid extent', async function () { + const response = await requestSender.getLatlonToTile({ lat: 1, lon: 1 }); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ + message: 'The coordinate is outside the grid extent', + }); + expect(response).toSatisfyApiSpec(); + }); + + it('should return 400 for tile not found', async function () { + const response = await requestSender.getTileToLatLon({ tile: 'XXX', sub_tile_number: [10, 10, 10] }); + + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ + message: 'Tile not found', + }); + expect(response).toSatisfyApiSpec(); + }); }); describe('Sad Path', function () { // All requests with status code 4XX-5XX From 499f856d977e47a59e95e1175dac21cb791ccde3 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 16:36:55 +0300 Subject: [PATCH 40/73] fix: fixed description --- tests/integration/latLon/latLon.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index 59d62d12..b536b3a7 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -93,7 +93,7 @@ describe('/latLon', function () { }); describe('Bad Path', function () { // All requests with status code of 400 - it('Check for missing required parameters', async function () { + it('should return 400 and message for missing required parameters', async function () { const arr = [ { request: requestSender.getLatlonToMgrs(), @@ -124,7 +124,7 @@ describe('/latLon', function () { } }); - it('test for checking unspecified query parameter', async function () { + it('should return 400 and message unknown query parameter', async function () { const parameter = 'test1234'; const message = `Unknown query parameter '${parameter}'`; From 834b19117e63c5879bb0ff028c1538f563c13aef Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 16:37:24 +0300 Subject: [PATCH 41/73] fix: changed response objects to correct ones --- tests/integration/latLon/latLon.spec.ts | 42 ++++++++++++++----------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index b536b3a7..3934d783 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -57,7 +57,7 @@ describe('/latLon', function () { expect(reponse).toSatisfyApiSpec(); expect(reponse.body).toMatchObject({ tileName: 'BRN', - subTileNumber: ['00', '00', '00'], + subTileNumber: [0, 0, 0], }); }); @@ -70,24 +70,28 @@ describe('/latLon', function () { expect(reponse.status).toBe(httpStatusCodes.OK); expect(reponse).toSatisfyApiSpec(); expect(reponse.body).toMatchObject({ - geometry: { - coordinates: [ - [ - [12.953293384350397, 52.512399536846765], - [12.953440643865289, 52.512402084451686], - [12.953436468347887, 52.51249192878939], - [12.95328920853307, 52.512489381176245], - [12.953293384350397, 52.512399536846765], - ], - ], - type: 'Polygon', - }, - type: 'Feature', - properties: { - TYPE: 'TILE', - SUB_TILE_NUMBER: [10, 10, 10], - TILE_NAME: 'BRN', - }, + type: 'FeatureCollection', + features: [ + { + geometry: { + coordinates: [ + [ + [12.953293384350397, 52.512399536846765], + [12.953440643865289, 52.512402084451686], + [12.953436468347887, 52.51249192878939], + [12.95328920853307, 52.512489381176245], + [12.953293384350397, 52.512399536846765], + ], + ], + type: 'Polygon', + }, + properties: { + TYPE: 'TILE', + SUB_TILE_NUMBER: [10, 10, 10], + TILE_NAME: 'BRN', + }, + }, + ], }); }); }); From e972cc50879dc7b4ab6999ae8b7510753f44c31d Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 16:37:42 +0300 Subject: [PATCH 42/73] fix: increased test timeout --- tests/configurations/integration/jest.config.js | 2 +- tests/configurations/unit/jest.config.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/configurations/integration/jest.config.js b/tests/configurations/integration/jest.config.js index e9531ea6..3ae834e9 100644 --- a/tests/configurations/integration/jest.config.js +++ b/tests/configurations/integration/jest.config.js @@ -29,5 +29,5 @@ module.exports = { statements: -10, }, }, - testTimeout: 15000, + testTimeout: 25000, }; diff --git a/tests/configurations/unit/jest.config.js b/tests/configurations/unit/jest.config.js index 09d50dd6..07af12e5 100644 --- a/tests/configurations/unit/jest.config.js +++ b/tests/configurations/unit/jest.config.js @@ -32,5 +32,5 @@ module.exports = { statements: -10, }, }, - testTimeout: 15000, + testTimeout: 25000, }; From 081818987e68634f0b4ccbb425518078ae48bd1d Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 16:37:56 +0300 Subject: [PATCH 43/73] fix: fixed returned schema to correct one --- openapi3.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi3.yaml b/openapi3.yaml index 53c2a6e1..16e208ea 100644 --- a/openapi3.yaml +++ b/openapi3.yaml @@ -269,7 +269,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/tilesSchema" + $ref: "#/components/schemas/subTileSchema" 400: "$ref": "#/components/responses/BadRequest" 401: From 729e3e158ffd48bbbffe33255fdc12f8c20dbf3d Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 16:38:12 +0300 Subject: [PATCH 44/73] fix: removed comment --- tests/integration/route/route.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/route/route.spec.ts b/tests/integration/route/route.spec.ts index db0747ca..6e195f95 100644 --- a/tests/integration/route/route.spec.ts +++ b/tests/integration/route/route.spec.ts @@ -33,7 +33,7 @@ describe('/routes', function () { expect(response.status).toBe(httpStatusCodes.OK); - // expect(response).toSatisfyApiSpec(); // TODO: + expect(response).toSatisfyApiSpec(); expect(response.body).toMatchObject({ type: 'FeatureCollection', features: [], From 17301436c1abc6224db26a28ba23edba9a0429ac Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Thu, 9 May 2024 16:38:33 +0300 Subject: [PATCH 45/73] fix: changed type to correct one --- src/latLon/controllers/latLonController.ts | 16 ++++---- src/latLon/models/latLonManager.ts | 36 ++++++++-------- src/latLon/utlis/index.ts | 48 ++++++++++++---------- 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/src/latLon/controllers/latLonController.ts b/src/latLon/controllers/latLonController.ts index 563c72af..bf1a2c60 100644 --- a/src/latLon/controllers/latLonController.ts +++ b/src/latLon/controllers/latLonController.ts @@ -12,7 +12,7 @@ type GetLatLonToTileHandler = RequestHandler< undefined, { tileName: string; - subTileNumber: string[]; + subTileNumber: number[]; }, undefined, GetLatLonToTileQueryParams @@ -21,13 +21,15 @@ type GetLatLonToTileHandler = RequestHandler< type GetTileToLatLonHandler = RequestHandler< undefined, { - geometry: Polygon; type: string; - properties: { - TYPE: string; - SUB_TILE_NUMBER?: number[] | undefined; - TILE_NAME?: string | undefined; - }; + features: { + geometry: Polygon; + properties: { + TYPE: string; + SUB_TILE_NUMBER?: number[] | undefined; + TILE_NAME?: string | undefined; + }; + }[]; }, undefined, GetTileToLatLonQueryParams diff --git a/src/latLon/models/latLonManager.ts b/src/latLon/models/latLonManager.ts index 4093b291..e76c379f 100644 --- a/src/latLon/models/latLonManager.ts +++ b/src/latLon/models/latLonManager.ts @@ -23,7 +23,7 @@ export class LatLonManager { public async latLonToTile({ lat, lon }: { lat: number; lon: number }): Promise<{ tileName: string; - subTileNumber: string[]; + subTileNumber: number[]; }> { if (!validateWGS84Coordinate({ lat, lon })) { this.logger.warn("LatLonManager.latLonToTile: Invalid lat lon, check 'lat' and 'lon' keys exists and their values are legal"); @@ -60,36 +60,36 @@ export class LatLonManager { return { tileName: tileCoordinateData.tileName, subTileNumber: new Array(3).fill('').map(function (value, i) { - return xNumber[i] + yNumber[i]; + return +(xNumber[i] + yNumber[i]); }), }; } public async tileToLatLon({ tileName, subTileNumber }: { tileName: string; subTileNumber: number[] }): Promise<{ - geometry: Polygon; type: string; - properties: { - /* eslint-disable @typescript-eslint/naming-convention */ - TYPE: string; - SUB_TILE_NUMBER?: number[] | undefined; - TILE_NAME?: string | undefined; - /* eslint-enable @typescript-eslint/naming-convention */ - }; + features: { + geometry: Polygon; + properties: { + /* eslint-disable @typescript-eslint/naming-convention */ + TYPE: string; + SUB_TILE_NUMBER?: number[] | undefined; + TILE_NAME?: string | undefined; + /* eslint-enable @typescript-eslint/naming-convention */ + }; + }[]; }> { if (!validateTile({ tileName, subTileNumber })) { - this.logger.warn( - "LatLonManager.tileToLatLon: Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers" - ); - throw new BadRequestError( - "Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers" - ); + const message = "Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers"; + this.logger.warn(`LatLonManager.tileToLatLon: ${message}`); + throw new BadRequestError(message); } const tile = await this.latLonRepository.tileToLatLon(tileName); if (!tile) { - this.logger.warn('LatLonManager.tileToLatLon: Tile not found'); - throw new NotFoundError('Tile not found'); + const meessage = 'Tile not found'; + this.logger.warn(`LatLonManager.tileToLatLon: ${meessage}`); + throw new BadRequestError(meessage); } const utmCoor = convertTilesToUTM({ tileName, subTileNumber }, tile); diff --git a/src/latLon/utlis/index.ts b/src/latLon/utlis/index.ts index 00b542ca..425e8083 100644 --- a/src/latLon/utlis/index.ts +++ b/src/latLon/utlis/index.ts @@ -1,28 +1,34 @@ import { Polygon } from 'geojson'; -import { NotFoundError } from '../../common/errors'; +import { BadRequestError } from '../../common/errors'; import { convertUTMToWgs84 } from '../../common/utils'; import { LatLon } from '../DAL/latLon'; /* eslint-disable @typescript-eslint/naming-convention */ const geoJsonObjectTemplate = (): { - geometry: Polygon; type: string; - properties: { - TYPE: string; - SUB_TILE_NUMBER?: number[]; - TILE_NAME?: string; - }; + features: { + geometry: Polygon; + properties: { + TYPE: string; + SUB_TILE_NUMBER?: number[]; + TILE_NAME?: string; + }; + }[]; } => ({ - geometry: { - coordinates: [[]], - type: 'Polygon', - }, - type: 'Feature', - properties: { - TYPE: 'TILE', - SUB_TILE_NUMBER: undefined, - TILE_NAME: undefined, - }, + type: 'FeatureCollection', + features: [ + { + geometry: { + coordinates: [[]], + type: 'Polygon', + }, + properties: { + TYPE: 'TILE', + SUB_TILE_NUMBER: undefined, + TILE_NAME: undefined, + }, + }, + ], }); /* eslint-enable @typescript-eslint/naming-convention */ @@ -60,7 +66,7 @@ export const validateResult = ( } ): void => { if (tile.extMinX > utmCoor.x || tile.extMaxX < utmCoor.x || tile.extMinY > utmCoor.y || tile.extMaxY < utmCoor.y) { - throw new NotFoundError("Tile is found, sub tile is not in tile's extent"); + throw new BadRequestError("Tile is found, sub tile is not in tile's extent"); } }; @@ -86,11 +92,11 @@ export const getSubTileByBottomLeftUtmCoor = ( if (typeof coordiante === 'string') { throw new Error('coordinate is string'); } - result.geometry.coordinates[0].push([coordiante.lng, coordiante.lat]); + result.features[0].geometry.coordinates[0].push([coordiante.lng, coordiante.lat]); } - result.properties.TILE_NAME = tile.tileName; - result.properties.SUB_TILE_NUMBER = tile.subTileNumber; + result.features[0].properties.TILE_NAME = tile.tileName; + result.features[0].properties.SUB_TILE_NUMBER = tile.subTileNumber; return result; }; From 01ddcf077fea010a18b92071a2ee1b62c26d9a11 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 10:22:53 +0300 Subject: [PATCH 46/73] chore: changed test from having for-loop to jest's test.each loop so if one fails the other won't --- tests/integration/latLon/latLon.spec.ts | 71 +++++++------------------ 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index 3934d783..3c0b8996 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -3,7 +3,6 @@ import jsLogger from '@map-colonies/js-logger'; import { trace } from '@opentelemetry/api'; import httpStatusCodes from 'http-status-codes'; -import supertest from 'supertest'; import { getApp } from '../../../src/app'; import { SERVICES } from '../../../src/common/constants'; import { LatLonRequestSender } from './helpers/requestSender'; @@ -96,65 +95,33 @@ describe('/latLon', function () { }); }); describe('Bad Path', function () { - // All requests with status code of 400 - it('should return 400 and message for missing required parameters', async function () { - const arr = [ - { - request: requestSender.getLatlonToMgrs(), - missingProperties: ['lat', 'lon'], - }, - { - request: requestSender.getMgrsToLatlon(), - missingProperties: ['mgrs'], - }, - { - request: requestSender.getLatlonToTile(), - missingProperties: ['lat', 'lon'], - }, - { - request: requestSender.getTileToLatLon(), - missingProperties: ['tile', 'sub_tile_number'], - }, - ]; - - for (const { request, missingProperties } of arr) { - const message = 'request/query must have required property'; - - const response: supertest.Response = await request; + test.each<[keyof typeof requestSender, string[]]>([ + ['getLatlonToMgrs', ['lat', 'lon']], + ['getMgrsToLatlon', ['mgrs']], + ['getLatlonToTile', ['lat', 'lon']], + ['getTileToLatLon', ['tile', 'sub_tile_number']], + ])('should return 400 and message for missing required parameters', async (request, missingProperties) => { + const message = 'request/query must have required property'; + const response = await requestSender[request](); - expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); - expect(response.body).toMatchObject({ message: missingProperties.map((txt) => `${message} '${txt}'`).join(', ') }); - expect(response).toSatisfyApiSpec(); - } + expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); + expect(response.body).toMatchObject({ message: missingProperties.map((txt) => `${message} '${txt}'`).join(', ') }); + expect(response).toSatisfyApiSpec(); }); - it('should return 400 and message unknown query parameter', async function () { - const parameter = 'test1234'; - const message = `Unknown query parameter '${parameter}'`; - - const arr = [ - { - request: requestSender.getLatlonToMgrs({ [parameter]: parameter } as never), - }, - { - request: requestSender.getMgrsToLatlon({ [parameter]: parameter } as never), - }, - { - request: requestSender.getLatlonToTile({ [parameter]: parameter } as never), - }, - { - request: requestSender.getTileToLatLon({ [parameter]: parameter } as never), - }, - ]; - - for (const { request } of arr) { - const response = await request; + test.each<[keyof typeof requestSender]>([['getLatlonToMgrs'], ['getMgrsToLatlon'], ['getLatlonToTile'], ['getTileToLatLon']])( + 'should return 400 and message unknown query parameter', + async (request) => { + const parameter = 'test1234'; + const message = `Unknown query parameter '${parameter}'`; + + const response = await requestSender[request]({ [parameter]: parameter } as never); expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); expect(response.body).toMatchObject({ message }); expect(response).toSatisfyApiSpec(); } - }); + ); it('should return 400 and check that all numbers are positive', async function () { const message = "Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers"; From ef277ba7f27050236725566b5ddd072feeca0725 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:41:48 +0300 Subject: [PATCH 47/73] feat: created new FeatureCollection type --- src/common/interfaces.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/interfaces.ts b/src/common/interfaces.ts index fad5959a..7d98367f 100644 --- a/src/common/interfaces.ts +++ b/src/common/interfaces.ts @@ -1,5 +1,6 @@ import { ClientOptions } from '@elastic/elasticsearch'; import { DataSourceOptions } from 'typeorm'; +import { Feature, FeatureCollection as GeoJSONFeatureCollection } from 'geojson'; export interface IConfig { get: (setting: string) => T; @@ -31,3 +32,7 @@ export interface Geometry { type: string; coordinates: number[][][]; } + +export interface FeatureCollection extends GeoJSONFeatureCollection { + features: T[]; +} From bc3d3b491484f8fb5c63f86373ef4f28d66548dd Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:43:17 +0300 Subject: [PATCH 48/73] fix(item.ts): updated type to extend @types/geojson Feature --- src/item/models/item.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/item/models/item.ts b/src/item/models/item.ts index ed8a5328..4dc58f5a 100644 --- a/src/item/models/item.ts +++ b/src/item/models/item.ts @@ -1,4 +1,4 @@ -import { Geometry } from '../../common/interfaces'; +import { Feature, Geometry } from 'geojson'; /* eslint-disable @typescript-eslint/naming-convention */ interface Properties { @@ -20,9 +20,4 @@ interface Properties { TYPE: string; } -export interface Item { - type: string; - id: number; - geometry: Geometry; - properties: Properties; -} +export interface Item extends Feature {} From cb54e198d4d7fbce98d142c2fc3e477eeadf1291 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:43:29 +0300 Subject: [PATCH 49/73] fix(route.ts): updated type to extend @types/geojson Feature --- src/route/models/route.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/route/models/route.ts b/src/route/models/route.ts index 1ac3133f..b02799db 100644 --- a/src/route/models/route.ts +++ b/src/route/models/route.ts @@ -1,4 +1,4 @@ -import { Geometry } from '../../common/interfaces'; +import { Feature, Geometry } from 'geojson'; /* eslint-disable @typescript-eslint/naming-convention */ interface Properties { @@ -13,9 +13,4 @@ interface Properties { TYPE: string; } -export interface Route { - type: string; - id: number; - geometry: Geometry; - properties: Properties; -} +export interface Route extends Feature {} From 16752f7b241e4035d66a4a70cc37a1f8fb3e8ea8 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:43:38 +0300 Subject: [PATCH 50/73] fix(tile.ts): updated type to extend @types/geojson Feature --- src/tile/models/tile.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/tile/models/tile.ts b/src/tile/models/tile.ts index 2e73b796..1dce501a 100644 --- a/src/tile/models/tile.ts +++ b/src/tile/models/tile.ts @@ -1,4 +1,4 @@ -import { Geometry } from '../../common/interfaces'; +import { Geometry, Feature } from 'geojson'; /* eslint-disable @typescript-eslint/naming-convention */ interface Properties { @@ -11,9 +11,4 @@ interface Properties { TYPE: string; } -export interface Tile { - type: string; - id: number; - geometry: Geometry; - properties: Properties; -} +export interface Tile extends Feature {} From 02047cd3fd15061379e084c40865aa9896e05f33 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:44:35 +0300 Subject: [PATCH 51/73] fix: updated formatResponse returned object to FeatureCollection --- src/common/utils.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/common/utils.ts b/src/common/utils.ts index d398e765..fcfd2ae9 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -6,16 +6,12 @@ import { Tile } from '../tile/models/tile'; import { Route } from '../route/models/route'; import { FIELDS } from './constants'; import { utmProjection, wgs84Projection } from './projections'; +import { FeatureCollection } from './interfaces'; -export const formatResponse = ( - elasticResponse: estypes.SearchResponse -): { - type: string; - features: (T | undefined)[]; -} => ({ +export const formatResponse = (elasticResponse: estypes.SearchResponse): FeatureCollection => ({ type: 'FeatureCollection', features: [ - ...elasticResponse.hits.hits.map((item) => { + ...(elasticResponse.hits.hits.map((item) => { const source = item._source; if (source) { Object.keys(source.properties).forEach((key) => { @@ -26,7 +22,7 @@ export const formatResponse = ( }); } return source; - }), + }) as T[]), ], }); From 3be50257a020a6ce2b279dfaf8aa7fcabaea969a Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:45:37 +0300 Subject: [PATCH 52/73] fix(itemManager): updated returned type --- src/item/models/itemManager.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/item/models/itemManager.ts b/src/item/models/itemManager.ts index 421e8e90..1ee3776a 100644 --- a/src/item/models/itemManager.ts +++ b/src/item/models/itemManager.ts @@ -6,6 +6,7 @@ import { SERVICES } from '../../common/constants'; import { ITEM_REPOSITORY_SYMBOL, ItemRepository } from '../DAL/itemRepository'; import { ItemQueryParams } from '../DAL/queries'; import { formatResponse } from '../../common/utils'; +import { FeatureCollection } from '../../common/interfaces'; import { Item } from './item'; @injectable() @@ -16,14 +17,7 @@ export class ItemManager { @inject(ITEM_REPOSITORY_SYMBOL) private readonly itemRepository: ItemRepository ) {} - public async getItems( - itemQueryParams: ItemQueryParams, - reduceFuzzyMatch = false, - size?: number - ): Promise<{ - type: string; - features: (Item | undefined)[]; - }> { + public async getItems(itemQueryParams: ItemQueryParams, reduceFuzzyMatch = false, size?: number): Promise> { let elasticResponse: estypes.SearchResponse | undefined = undefined; elasticResponse = await this.itemRepository.getItems(itemQueryParams, size ?? this.config.get('db.elastic.properties.size')); From 20b75495c0030c495322766a71daf232a32c4129 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:46:10 +0300 Subject: [PATCH 53/73] delete(latLonManager): removed unused import --- src/latLon/models/latLonManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/latLon/models/latLonManager.ts b/src/latLon/models/latLonManager.ts index e76c379f..517a428a 100644 --- a/src/latLon/models/latLonManager.ts +++ b/src/latLon/models/latLonManager.ts @@ -7,7 +7,7 @@ import { SERVICES } from '../../common/constants'; import { LATLON_CUSTOM_REPOSITORY_SYMBOL, LatLonRepository } from '../DAL/latLonRepository'; import { convertWgs84ToUTM, validateTile, validateWGS84Coordinate } from '../../common/utils'; import { convertTilesToUTM, getSubTileByBottomLeftUtmCoor, validateResult } from '../utlis'; -import { BadRequestError, NotFoundError } from '../../common/errors'; +import { BadRequestError } from '../../common/errors'; @injectable() export class LatLonManager { From 6388265f48ed92e6b8324b1ece8a802f14c890ea Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:46:25 +0300 Subject: [PATCH 54/73] fix(routeManager): updated returned type --- src/route/models/routeManager.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/route/models/routeManager.ts b/src/route/models/routeManager.ts index a188bbfd..472c9b87 100644 --- a/src/route/models/routeManager.ts +++ b/src/route/models/routeManager.ts @@ -6,6 +6,7 @@ import { SERVICES } from '../../common/constants'; import { ROUTE_REPOSITORY_SYMBOL, RouteRepository } from '../DAL/routeRepository'; import { RouteQueryParams } from '../DAL/queries'; import { formatResponse } from '../../common/utils'; +import { FeatureCollection } from '../../common/interfaces'; import { Route } from './route'; @injectable() @@ -16,14 +17,7 @@ export class RouteManager { @inject(ROUTE_REPOSITORY_SYMBOL) private readonly routeRepository: RouteRepository ) {} - public async getRoutes( - routeQueryParams: RouteQueryParams, - reduceFuzzyMatch = false, - size?: number - ): Promise<{ - type: string; - features: (Route | undefined)[]; - }> { + public async getRoutes(routeQueryParams: RouteQueryParams, reduceFuzzyMatch = false, size?: number): Promise> { let elasticResponse: estypes.SearchResponse | undefined = undefined; if (routeQueryParams.controlPoint ?? 0) { elasticResponse = await this.routeRepository.getControlPointInRoute( From 13daf1f7bff78703784919b04e71f0b94ee1cbf6 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:46:53 +0300 Subject: [PATCH 55/73] fix(tileManager): updated returned type --- src/tile/models/tileManager.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/tile/models/tileManager.ts b/src/tile/models/tileManager.ts index b07e9bed..75c00063 100644 --- a/src/tile/models/tileManager.ts +++ b/src/tile/models/tileManager.ts @@ -6,6 +6,7 @@ import { SERVICES } from '../../common/constants'; import { TILE_REPOSITORY_SYMBOL, TileRepository } from '../DAL/tileRepository'; import { formatResponse } from '../../common/utils'; import { TileQueryParams } from '../DAL/queries'; +import { FeatureCollection } from '../../common/interfaces'; import { Tile } from './tile'; @injectable() @@ -16,14 +17,7 @@ export class TileManager { @inject(TILE_REPOSITORY_SYMBOL) private readonly tileRepository: TileRepository ) {} - public async getTiles( - tileQueryParams: TileQueryParams, - reduceFuzzyMatch = false, - size?: number - ): Promise<{ - type: string; - features: (Tile | undefined)[]; - }> { + public async getTiles(tileQueryParams: TileQueryParams, reduceFuzzyMatch = false, size?: number): Promise> { let elasticResponse: estypes.SearchResponse | undefined = undefined; const numberOfResults = size ?? this.config.get('db.elastic.properties.size'); if (tileQueryParams.subTile ?? 0) { From de2a51210023bb405d9db61207df9e7e0f3f3c37 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:47:14 +0300 Subject: [PATCH 56/73] delete: removed boilerplate code --- .../models/anotherResourceManager.spec.ts | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 tests/unit/anotherResource/models/anotherResourceManager.spec.ts diff --git a/tests/unit/anotherResource/models/anotherResourceManager.spec.ts b/tests/unit/anotherResource/models/anotherResourceManager.spec.ts deleted file mode 100644 index 846845e6..00000000 --- a/tests/unit/anotherResource/models/anotherResourceManager.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import jsLogger from '@map-colonies/js-logger'; -import { AnotherResourceManager } from '../../../../src/anotherResource/models/anotherResourceManager'; - -let anotherResourceManager: AnotherResourceManager; - -describe('ResourceNameManager', () => { - beforeEach(function () { - anotherResourceManager = new AnotherResourceManager(jsLogger({ enabled: false })); - }); - describe('#getResource', () => { - it('should return resource of kind avi', function () { - // action - const resource = anotherResourceManager.getResource(); - - // expectation - expect(resource.kind).toBe('avi'); - expect(resource.isAlive).toBe(false); - }); - }); -}); From 83c6c2919dc2262ba08f9a766217655f53cffb35 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:47:44 +0300 Subject: [PATCH 57/73] feat: created mock data for formatResponse unit testing --- tests/unit/common/objects.ts | 271 +++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 tests/unit/common/objects.ts diff --git a/tests/unit/common/objects.ts b/tests/unit/common/objects.ts new file mode 100644 index 00000000..3ef7ec5b --- /dev/null +++ b/tests/unit/common/objects.ts @@ -0,0 +1,271 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ +/* eslint-disable @typescript-eslint/naming-convention */ +import { estypes } from '@elastic/elasticsearch'; +import { FeatureCollection } from 'geojson'; + +/* ------------------- Objects for testing common/utils.ts: formatResponse() - ITEM type -------------------*/ +export const itemElasticResponse: Pick = { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 1.89712, + hits: [ + { + _index: 'control_gil_v5', + _id: 'CONTROL.ITEMS', + _score: 1.89712, + _source: { + type: 'Feature', + geometry: { + coordinates: [ + [ + [98.96871358832425, 18.77187541003238], + [98.96711613001014, 18.772012912146167], + [98.9668257091372, 18.77957500633211], + [98.96517988589727, 18.783516234000658], + [98.96305002071, 18.786174113473763], + [98.96222710028087, 18.786036643850125], + [98.9615009529004, 18.784478609414165], + [98.96096850521184, 18.78324114944766], + [98.96058105300438, 18.74932410944021], + [98.96029062202649, 18.747169677704846], + [98.9619364723165, 18.74666541646775], + [98.96479250629358, 18.7514784826093], + [98.96401797557468, 18.75193687161918], + [98.96614791571238, 18.754412116891245], + [98.96639000300826, 18.75940841151673], + [98.96779381973744, 18.759133392649602], + [98.96798745662056, 18.76018763174328], + [98.96789063809456, 18.761746062357858], + [98.96905242991687, 18.763487833908357], + [98.96871358832425, 18.77187541003238], + ], + ], + type: 'Polygon', + }, + properties: { + OBJECT_COMMAND_NAME: '4805', + TILE_NAME: 'DEF', + SUB_TILE_ID: '36', + ENTITY_HEB: 'airport', + TYPE: 'ITEM', + }, + }, + }, + ], + }, +}; + +export const itemExpectedFormattedResponse: FeatureCollection = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + coordinates: [ + [ + [98.96871358832425, 18.77187541003238], + [98.96711613001014, 18.772012912146167], + [98.9668257091372, 18.77957500633211], + [98.96517988589727, 18.783516234000658], + [98.96305002071, 18.786174113473763], + [98.96222710028087, 18.786036643850125], + [98.9615009529004, 18.784478609414165], + [98.96096850521184, 18.78324114944766], + [98.96058105300438, 18.74932410944021], + [98.96029062202649, 18.747169677704846], + [98.9619364723165, 18.74666541646775], + [98.96479250629358, 18.7514784826093], + [98.96401797557468, 18.75193687161918], + [98.96614791571238, 18.754412116891245], + [98.96639000300826, 18.75940841151673], + [98.96779381973744, 18.759133392649602], + [98.96798745662056, 18.76018763174328], + [98.96789063809456, 18.761746062357858], + [98.96905242991687, 18.763487833908357], + [98.96871358832425, 18.77187541003238], + ], + ], + type: 'Polygon', + }, + properties: { + OBJECT_COMMAND_NAME: '4805', + TILE_NAME: 'DEF', + SUB_TILE_ID: '36', + ENTITY_HEB: 'airport', + TYPE: 'ITEM', + }, + }, + ], +}; + +/* ------------------- Objects for testing common/utils.ts: formatResponse() - TILE type -------------------*/ + +export const tileElasticResponse: Pick = { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 2.184802, + hits: [ + { + _index: 'control_gil_v5', + _id: 'CONTROL.TILES', + _score: 2.184802, + _source: { + type: 'Feature', + geometry: { + coordinates: [ + [ + [12.539507865186607, 41.851751203650096], + [12.536787075186538, 41.94185043165008], + [12.42879133518656, 41.93952837265009], + [12.431625055186686, 41.84943698365008], + [12.539507865186607, 41.851751203650096], + ], + ], + type: 'Polygon', + }, + properties: { TILE_NAME: 'RIT', TYPE: 'TILE' }, + }, + }, + ], + }, +}; + +export const tileExpectedFormattedResponse: FeatureCollection = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + coordinates: [ + [ + [12.539507865186607, 41.851751203650096], + [12.536787075186538, 41.94185043165008], + [12.42879133518656, 41.93952837265009], + [12.431625055186686, 41.84943698365008], + [12.539507865186607, 41.851751203650096], + ], + ], + type: 'Polygon', + }, + properties: { TILE_NAME: 'RIT', TYPE: 'TILE' }, + }, + ], +}; + +/* ------------------- Objects for testing common/utils.ts: formatResponse() - SUB_TILE type -------------------*/ + +export const subTileElasticResponse: Pick = { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 2.877949, + hits: [ + { + _index: 'control_gil_v5', + _id: 'CONTROL.SUB_TILES', + _score: 2.877949, + _source: { + type: 'Feature', + geometry: { + coordinates: [ + [ + [27.149158174343427, 35.63159611670335], + [27.149274355343437, 35.64061707270338], + [27.138786228343463, 35.640716597703374], + [27.13867103934342, 35.631695606703374], + [27.149158174343427, 35.63159611670335], + ], + ], + type: 'Polygon', + }, + properties: { SUB_TILE_ID: '65', TILE_NAME: 'GRC', TYPE: 'SUB_TILE' }, + }, + }, + ], + }, +}; +export const subTileExpectedFormattedResponse: FeatureCollection = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + coordinates: [ + [ + [27.149158174343427, 35.63159611670335], + [27.149274355343437, 35.64061707270338], + [27.138786228343463, 35.640716597703374], + [27.13867103934342, 35.631695606703374], + [27.149158174343427, 35.63159611670335], + ], + ], + type: 'Polygon', + }, + properties: { SUB_TILE_ID: '65', TILE_NAME: 'GRC', TYPE: 'SUB_TILE' }, + }, + ], +}; + +/* ------------------- Objects for testing common/utils.ts: formatResponse() - ROUTE type -------------------*/ + +export const routeElasticResponse: Pick = { + hits: { + total: { value: 1, relation: 'eq' }, + max_score: 1.89712, + hits: [ + { + _index: 'control_gil_v5', + _id: 'CONTROL.ROUTES', + _score: 1.89712, + _source: { + type: 'Feature', + geometry: { + coordinates: [ + [13.448493352142947, 52.31016611400918], + [13.447219581381603, 52.313370282889224], + [13.448088381125075, 52.31631514453963], + [13.450458681234068, 52.31867376333767], + [13.451112278530388, 52.32227665244022], + [13.449728938644029, 52.32463678850752], + [13.445021899434977, 52.32863442881066], + [13.444723882330948, 52.340023400115086], + [13.446229682887974, 52.34532799609971], + ], + type: 'LineString', + }, + properties: { + OBJECT_COMMAND_NAME: 'route96', + ENTITY_HEB: 'route96', + TYPE: 'ROUTE', + }, + }, + }, + ], + }, +}; +export const routeExpectedFormattedResponse: FeatureCollection = { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + coordinates: [ + [13.448493352142947, 52.31016611400918], + [13.447219581381603, 52.313370282889224], + [13.448088381125075, 52.31631514453963], + [13.450458681234068, 52.31867376333767], + [13.451112278530388, 52.32227665244022], + [13.449728938644029, 52.32463678850752], + [13.445021899434977, 52.32863442881066], + [13.444723882330948, 52.340023400115086], + [13.446229682887974, 52.34532799609971], + ], + type: 'LineString', + }, + properties: { + OBJECT_COMMAND_NAME: 'route96', + ENTITY_HEB: 'route96', + TYPE: 'ROUTE', + }, + }, + ], +}; From 102f5513032f9326714f711b527669eb4db94444 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 13:47:59 +0300 Subject: [PATCH 58/73] feat: created formatResponse unit testing --- tests/unit/common/utils.spec.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/unit/common/utils.spec.ts diff --git a/tests/unit/common/utils.spec.ts b/tests/unit/common/utils.spec.ts new file mode 100644 index 00000000..800239f8 --- /dev/null +++ b/tests/unit/common/utils.spec.ts @@ -0,0 +1,31 @@ +import { estypes } from '@elastic/elasticsearch'; +import { + formatResponse, + additionalSearchProperties, + convertUTMToWgs84, + convertWgs84ToUTM, + validateTile, + validateWGS84Coordinate, +} from '../../../src/common/utils'; +import { + itemElasticResponse, + itemExpectedFormattedResponse, + tileElasticResponse, + tileExpectedFormattedResponse, + subTileElasticResponse, + subTileExpectedFormattedResponse, + routeElasticResponse, + routeExpectedFormattedResponse, +} from './objects'; + +describe('utils', () => { + test.each([ + [itemElasticResponse, itemExpectedFormattedResponse], + [tileElasticResponse, tileExpectedFormattedResponse], + [subTileElasticResponse, subTileExpectedFormattedResponse], + [routeElasticResponse, routeExpectedFormattedResponse], + ])('should convert ElasticSearch query response to FeatureCollection', (elasticResponse, formattedResponse) => { + const result = formatResponse(elasticResponse as estypes.SearchResponse); + expect(result).toMatchObject(formattedResponse); + }); +}); From aa9a4058ba99d18c4601043aa6b045984bd75693 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:12:54 +0300 Subject: [PATCH 59/73] fix: fixed if statement --- src/common/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/utils.ts b/src/common/utils.ts index fcfd2ae9..e618aa7c 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -13,10 +13,10 @@ export const formatResponse = (elasticResponse: e features: [ ...(elasticResponse.hits.hits.map((item) => { const source = item._source; - if (source) { + if (source?.properties) { Object.keys(source.properties).forEach((key) => { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (source.properties[key as keyof typeof source.properties] == null) { + if (source.properties !== null && source.properties[key as keyof typeof source.properties] == null) { delete source.properties[key as keyof typeof source.properties]; } }); From 63fc5f9fe7c9fb9e89cab14d59918caea3924fc8 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:13:36 +0300 Subject: [PATCH 60/73] fix(item): removed properties. now we accept every key as a property --- src/item/models/item.ts | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/item/models/item.ts b/src/item/models/item.ts index 4dc58f5a..3869c449 100644 --- a/src/item/models/item.ts +++ b/src/item/models/item.ts @@ -1,23 +1,3 @@ -import { Feature, Geometry } from 'geojson'; +import { Feature } from 'geojson'; -/* eslint-disable @typescript-eslint/naming-convention */ -interface Properties { - OBJECTID: number; - F_CODE: number; - F_ATT: number; - VIEW_SCALE_50K_CONTROL: number; - NAME: null; // TODO: Check if this is correct - GFID: string; - OBJECT_COMMAND_NAME: string; - SUB_TILE_NAME: null; // TODO: Check if this is correct - TILE_NAME: string; - TILE_ID: null | string; - SUB_TILE_ID?: string; - 'SHAPE.AREA': number; - 'SHAPE.LEN': number; - LAYER_NAME: string; - ENTITY_HEB: string; - TYPE: string; -} - -export interface Item extends Feature {} +export interface Item extends Feature {} From 4adaf7826edecb5d51ec3d2147bad3abe93d96f4 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:13:47 +0300 Subject: [PATCH 61/73] fix(route): removed properties. now we accept every key as a property --- src/route/models/route.ts | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/route/models/route.ts b/src/route/models/route.ts index b02799db..4860b131 100644 --- a/src/route/models/route.ts +++ b/src/route/models/route.ts @@ -1,16 +1,3 @@ -import { Feature, Geometry } from 'geojson'; +import { Feature } from 'geojson'; -/* eslint-disable @typescript-eslint/naming-convention */ -interface Properties { - OBJECTID: number; - OBJECT_COMMAND_NAME: string; - FIRST_GFID: null; // TODO: findout real type - SHAPE_Length: number; - F_CODE: number; - F_ATT: number; - LAYER_NAME: string; - ENTITY_HEB: string; - TYPE: string; -} - -export interface Route extends Feature {} +export interface Route extends Feature {} From 4b4d853a22375f8183fdb19c1e15dbdedd8cf223 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:13:57 +0300 Subject: [PATCH 62/73] fix(tile): removed properties. now we accept every key as a property --- src/tile/models/tile.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/tile/models/tile.ts b/src/tile/models/tile.ts index 1dce501a..91cc6452 100644 --- a/src/tile/models/tile.ts +++ b/src/tile/models/tile.ts @@ -1,14 +1,3 @@ -import { Geometry, Feature } from 'geojson'; +import { Feature } from 'geojson'; -/* eslint-disable @typescript-eslint/naming-convention */ -interface Properties { - OBJECTID: number; - ZONE: string; - TILE_NAME: string; - SUB_TILE_ID?: string; - TILE_ID: null | string; - LAYER_NAME: string; - TYPE: string; -} - -export interface Tile extends Feature {} +export interface Tile extends Feature {} From 75f1a8ab62fcb0de9a10df75814b4b708a547d9f Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:14:50 +0300 Subject: [PATCH 63/73] fix(itemManager): added optional chain as property now could be null --- src/item/models/itemManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/item/models/itemManager.ts b/src/item/models/itemManager.ts index 1ee3776a..7833e7de 100644 --- a/src/item/models/itemManager.ts +++ b/src/item/models/itemManager.ts @@ -24,7 +24,7 @@ export class ItemManager { const formattedResponse = formatResponse(elasticResponse); if (reduceFuzzyMatch && formattedResponse.features.length > 0) { - const filterFunction = (hit: Item | undefined): hit is Item => hit?.properties.OBJECT_COMMAND_NAME === itemQueryParams.commandName; + const filterFunction = (hit: Item | undefined): hit is Item => hit?.properties?.OBJECT_COMMAND_NAME === itemQueryParams.commandName; formattedResponse.features = formattedResponse.features.filter(filterFunction); } From 7c417b01501ef97d07d4918e0768bebed72e90fa Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:16:05 +0300 Subject: [PATCH 64/73] fix(latLonManager): added optional chain as property now could be null --- src/latLon/models/latLonManager.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/latLon/models/latLonManager.ts b/src/latLon/models/latLonManager.ts index 517a428a..b6b0d480 100644 --- a/src/latLon/models/latLonManager.ts +++ b/src/latLon/models/latLonManager.ts @@ -2,12 +2,13 @@ import { IConfig } from 'config'; import { Logger } from '@map-colonies/js-logger'; import { inject, injectable } from 'tsyringe'; import * as mgrs from 'mgrs'; -import { Polygon } from 'geojson'; import { SERVICES } from '../../common/constants'; import { LATLON_CUSTOM_REPOSITORY_SYMBOL, LatLonRepository } from '../DAL/latLonRepository'; import { convertWgs84ToUTM, validateTile, validateWGS84Coordinate } from '../../common/utils'; import { convertTilesToUTM, getSubTileByBottomLeftUtmCoor, validateResult } from '../utlis'; import { BadRequestError } from '../../common/errors'; +import { Tile } from '../../tile/models/tile'; +import { FeatureCollection } from '../../common/interfaces'; @injectable() export class LatLonManager { @@ -65,19 +66,8 @@ export class LatLonManager { }; } - public async tileToLatLon({ tileName, subTileNumber }: { tileName: string; subTileNumber: number[] }): Promise<{ - type: string; - features: { - geometry: Polygon; - properties: { - /* eslint-disable @typescript-eslint/naming-convention */ - TYPE: string; - SUB_TILE_NUMBER?: number[] | undefined; - TILE_NAME?: string | undefined; - /* eslint-enable @typescript-eslint/naming-convention */ - }; - }[]; - }> { + public async tileToLatLon({ tileName, subTileNumber }: { tileName: string; subTileNumber: number[] }): Promise> { + console.log('tileToLatLon', tileName, subTileNumber); if (!validateTile({ tileName, subTileNumber })) { const message = "Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers"; this.logger.warn(`LatLonManager.tileToLatLon: ${message}`); From 0eb518aa1049833425370b97c17134d607557d76 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:16:16 +0300 Subject: [PATCH 65/73] fix(tileManager): added optional chain as property now could be null --- src/tile/models/tileManager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tile/models/tileManager.ts b/src/tile/models/tileManager.ts index 75c00063..881217dc 100644 --- a/src/tile/models/tileManager.ts +++ b/src/tile/models/tileManager.ts @@ -32,8 +32,8 @@ export class TileManager { const filterFunction = tileQueryParams.subTile ?? 0 ? (hit: Tile | undefined): hit is Tile => - hit?.properties.SUB_TILE_ID === tileQueryParams.subTile && hit?.properties.TILE_NAME === tileQueryParams.tile - : (hit: Tile | undefined): hit is Tile => hit?.properties.TILE_NAME === tileQueryParams.tile; + hit?.properties?.SUB_TILE_ID === tileQueryParams.subTile && hit?.properties?.TILE_NAME === tileQueryParams.tile + : (hit: Tile | undefined): hit is Tile => hit?.properties?.TILE_NAME === tileQueryParams.tile; formattedResponse.features = formattedResponse.features.filter(filterFunction); } From 3a44952b5c7863200802a97e6e1fdf4e87c4ed4e Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:16:28 +0300 Subject: [PATCH 66/73] fix(routeManager): added optional chain as property now could be null --- src/route/models/routeManager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/route/models/routeManager.ts b/src/route/models/routeManager.ts index 472c9b87..31a47127 100644 --- a/src/route/models/routeManager.ts +++ b/src/route/models/routeManager.ts @@ -33,8 +33,8 @@ export class RouteManager { if (reduceFuzzyMatch && formattedResponse.features.length > 0) { const filterFunction = routeQueryParams.controlPoint ?? 0 - ? (hit: Route | undefined): hit is Route => hit?.properties.OBJECT_COMMAND_NAME === routeQueryParams.controlPoint - : (hit: Route | undefined): hit is Route => hit?.properties.OBJECT_COMMAND_NAME === routeQueryParams.commandName; + ? (hit: Route | undefined): hit is Route => hit?.properties?.OBJECT_COMMAND_NAME === routeQueryParams.controlPoint + : (hit: Route | undefined): hit is Route => hit?.properties?.OBJECT_COMMAND_NAME === routeQueryParams.commandName; formattedResponse.features = formattedResponse.features.filter(filterFunction); } From 4765db505c423db4a8b17a2162776fa939bfebf0 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:17:09 +0300 Subject: [PATCH 67/73] fix: fixed functions types --- src/latLon/utlis/index.ts | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/latLon/utlis/index.ts b/src/latLon/utlis/index.ts index 425e8083..ae6e67de 100644 --- a/src/latLon/utlis/index.ts +++ b/src/latLon/utlis/index.ts @@ -2,30 +2,21 @@ import { Polygon } from 'geojson'; import { BadRequestError } from '../../common/errors'; import { convertUTMToWgs84 } from '../../common/utils'; import { LatLon } from '../DAL/latLon'; +import { FeatureCollection } from '../../common/interfaces'; +import { Tile } from '../../tile/models/tile'; /* eslint-disable @typescript-eslint/naming-convention */ -const geoJsonObjectTemplate = (): { - type: string; - features: { - geometry: Polygon; - properties: { - TYPE: string; - SUB_TILE_NUMBER?: number[]; - TILE_NAME?: string; - }; - }[]; -} => ({ +const geoJsonObjectTemplate = (): FeatureCollection => ({ type: 'FeatureCollection', features: [ { + type: 'Feature', geometry: { - coordinates: [[]], type: 'Polygon', + coordinates: [[]], }, properties: { TYPE: 'TILE', - SUB_TILE_NUMBER: undefined, - TILE_NAME: undefined, }, }, ], @@ -77,8 +68,9 @@ export const getSubTileByBottomLeftUtmCoor = ( zone: number; }, tile: { tileName: string; subTileNumber: number[] } -) => { +): FeatureCollection => { const result = geoJsonObjectTemplate(); + const multiplyByOrder = [ [0, 0], [1, 0], @@ -87,16 +79,22 @@ export const getSubTileByBottomLeftUtmCoor = ( [0, 0], ]; // bottom left -> bottom right -> top right -> top left -> bottom left const distance = 10; // 10 meters + const polygon: Polygon = { + type: 'Polygon', + coordinates: [[]], + }; + for (const multiply of multiplyByOrder) { const coordiante = convertUTMToWgs84(utmCoor.x + distance * multiply[0], utmCoor.y + distance * multiply[1], utmCoor.zone); if (typeof coordiante === 'string') { throw new Error('coordinate is string'); } - result.features[0].geometry.coordinates[0].push([coordiante.lng, coordiante.lat]); + polygon.coordinates[0].push([coordiante.lng, coordiante.lat]); } - result.features[0].properties.TILE_NAME = tile.tileName; - result.features[0].properties.SUB_TILE_NUMBER = tile.subTileNumber; + result.features[0].geometry = polygon; + // eslint-disable-next-line @typescript-eslint/naming-convention + result.features[0].properties = { ...result.features[0].properties, TILE_NAME: tile.tileName, SUB_TILE_NUMBER: tile.subTileNumber }; return result; }; From f94cb57815a4a7eeed322987adb18ff2ff6d623a Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:17:37 +0300 Subject: [PATCH 68/73] fix(latLonController): fixed returned type --- src/latLon/controllers/latLonController.ts | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/latLon/controllers/latLonController.ts b/src/latLon/controllers/latLonController.ts index bf1a2c60..ae1ca70f 100644 --- a/src/latLon/controllers/latLonController.ts +++ b/src/latLon/controllers/latLonController.ts @@ -4,9 +4,10 @@ import { BoundCounter, Meter } from '@opentelemetry/api-metrics'; import { RequestHandler } from 'express'; import httpStatus from 'http-status-codes'; import { injectable, inject } from 'tsyringe'; -import { Polygon } from 'geojson'; import { SERVICES } from '../../common/constants'; import { LatLonManager } from '../models/latLonManager'; +import { Tile } from '../../tile/models/tile'; +import { FeatureCollection } from '../../common/interfaces'; type GetLatLonToTileHandler = RequestHandler< undefined, @@ -18,22 +19,7 @@ type GetLatLonToTileHandler = RequestHandler< GetLatLonToTileQueryParams >; -type GetTileToLatLonHandler = RequestHandler< - undefined, - { - type: string; - features: { - geometry: Polygon; - properties: { - TYPE: string; - SUB_TILE_NUMBER?: number[] | undefined; - TILE_NAME?: string | undefined; - }; - }[]; - }, - undefined, - GetTileToLatLonQueryParams ->; +type GetTileToLatLonHandler = RequestHandler, undefined, GetTileToLatLonQueryParams>; type GetLatLonToMgrsHandler = RequestHandler; From 203cc9756755c4ff2a7c544d1c5b8c9dc2f324be Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:22:02 +0300 Subject: [PATCH 69/73] fix: added "type" key to returned tilesSchema --- openapi3.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openapi3.yaml b/openapi3.yaml index 16e208ea..32a381dd 100644 --- a/openapi3.yaml +++ b/openapi3.yaml @@ -504,6 +504,9 @@ components: items: type: "object" properties: + type: + type: "string" + enum: ["Feature"] geometry: $ref: "#/components/schemas/Geometry" properties: From 51ced62cec9d24375871de26455bd1028ef71281 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:22:56 +0300 Subject: [PATCH 70/73] feat: added test cases --- tests/unit/common/utils.spec.ts | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/unit/common/utils.spec.ts b/tests/unit/common/utils.spec.ts index 800239f8..62076f0b 100644 --- a/tests/unit/common/utils.spec.ts +++ b/tests/unit/common/utils.spec.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { estypes } from '@elastic/elasticsearch'; import { formatResponse, @@ -7,6 +8,8 @@ import { validateTile, validateWGS84Coordinate, } from '../../../src/common/utils'; +import config from '../../../config/test.json'; +import { FIELDS } from '../../../src/common/constants'; import { itemElasticResponse, itemExpectedFormattedResponse, @@ -28,4 +31,42 @@ describe('utils', () => { const result = formatResponse(elasticResponse as estypes.SearchResponse); expect(result).toMatchObject(formattedResponse); }); + + it('should return additional search properties', () => { + const size = 10; + const result = additionalSearchProperties(size); + expect(result).toMatchObject({ size, index: config.db.elastic.properties.controlIndex, _source: FIELDS }); + }); + + it('should convert UTM to WGS84', () => { + const result = convertUTMToWgs84(630048, 4330433, 29); + expect(result).toMatchObject({ lat: 39.11335578352079, lng: -7.495780486809503 }); + }); + + it('should convert WGS84 to UTM', () => { + const result = convertWgs84ToUTM(39.11335712352982, -7.495784527093747); + expect(result).toMatchObject({ Easting: 630048, Northing: 4330433, ZoneNumber: 29 }); + }); + + test.each([ + [{ tileName: 'BRN', subTileNumber: [10, 10, 10] }, true], + [{ tileName: 'BRN', subTileNumber: [0, 10, 10] }, false], + [{ tileName: 'BRN', subTileNumber: [10, 0, 10] }, false], + [{ tileName: 'BRN', subTileNumber: [10, 10, 0] }, false], + [{ tileName: 'BRN', subTileNumber: [10, 10, 100] }, false], + [{ tileName: 'BRN', subTileNumber: [10, 10] }, false], + [{ tileName: '', subTileNumber: [10, 10, 10] }, false], + ])(`should validate tile`, (tile, expected) => { + expect(validateTile(tile as never)).toBe(expected); + }); + + test.each([ + [{ lon: 50, lat: 50 }, true], + [{ lon: 190, lat: 50 }, false], + [{ lon: 50, lat: 190 }, false], + [{ lon: -10, lat: 50 }, false], + [{ lon: 50, lat: -10 }, false], + ])('should validate WGS84 coordinate', (coordinate, expected) => { + expect(validateWGS84Coordinate(coordinate as never)).toBe(expected); + }); }); From c3168c203eaf33a97546a9594605f7312edac47d Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:24:30 +0300 Subject: [PATCH 71/73] fix: changed test to properly check the assignment of arr[i] = 0 and it's failure --- tests/integration/latLon/latLon.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/latLon/latLon.spec.ts b/tests/integration/latLon/latLon.spec.ts index 3c0b8996..c656effb 100644 --- a/tests/integration/latLon/latLon.spec.ts +++ b/tests/integration/latLon/latLon.spec.ts @@ -127,12 +127,12 @@ describe('/latLon', function () { const message = "Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers"; for (let i = 0; i < 3; i++) { - const arr = new Array(3).fill(10); + const arr: number[] = [10, 10, 10]; arr[i] = 0; const response = await requestSender.getTileToLatLon({ tile: 'BRN', - sub_tile_number: [0, 0, 0], + sub_tile_number: arr, }); expect(response.status).toBe(httpStatusCodes.BAD_REQUEST); From 34df5a30f9b129d1cc0fa7cbdfbd90b2c0a695e2 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:33:00 +0300 Subject: [PATCH 72/73] delete: removed console.log --- src/latLon/models/latLonManager.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/latLon/models/latLonManager.ts b/src/latLon/models/latLonManager.ts index b6b0d480..cbe322e5 100644 --- a/src/latLon/models/latLonManager.ts +++ b/src/latLon/models/latLonManager.ts @@ -67,7 +67,6 @@ export class LatLonManager { } public async tileToLatLon({ tileName, subTileNumber }: { tileName: string; subTileNumber: number[] }): Promise> { - console.log('tileToLatLon', tileName, subTileNumber); if (!validateTile({ tileName, subTileNumber })) { const message = "Invalid tile, check that 'tileName' and 'subTileNumber' exists and subTileNumber is array of size 3 with positive integers"; this.logger.warn(`LatLonManager.tileToLatLon: ${message}`); From 915b970caf621167fdbdee90d3b0ff55772630b7 Mon Sep 17 00:00:00 2001 From: Niv Greenstein Date: Sun, 12 May 2024 16:36:12 +0300 Subject: [PATCH 73/73] WIP : commited only to be deleted later --- .../models/resourceNameModel.spec.ts | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/tests/unit/resourceName/models/resourceNameModel.spec.ts b/tests/unit/resourceName/models/resourceNameModel.spec.ts index a23d2e78..323e639d 100644 --- a/tests/unit/resourceName/models/resourceNameModel.spec.ts +++ b/tests/unit/resourceName/models/resourceNameModel.spec.ts @@ -1,33 +1,40 @@ -import jsLogger from '@map-colonies/js-logger'; -import { ResourceNameManager } from '../../../../src/resourceName/models/resourceNameManager'; +// import jsLogger from '@map-colonies/js-logger'; +// import { ResourceNameManager } from '../../../../src/resourceName/models/resourceNameManager'; -let resourceNameManager: ResourceNameManager; +// let resourceNameManager: ResourceNameManager; -describe('ResourceNameManager', () => { - beforeEach(function () { - resourceNameManager = new ResourceNameManager(jsLogger({ enabled: false })); - }); - describe('#getResource', () => { - it('return the resource of id 1', function () { - // action - const resource = resourceNameManager.getResource(); +// describe('ResourceNameManager', () => { +// beforeEach(function () { +// resourceNameManager = new ResourceNameManager(jsLogger({ enabled: false })); +// }); +// describe('#getResource', () => { +// it('return the resource of id 1', function () { +// // action +// const resource = resourceNameManager.getResource(); - // expectation - expect(resource.id).toBe(1); - expect(resource.name).toBe('ronin'); - expect(resource.description).toBe('can you do a logistics run?'); - }); - }); - describe('#createResource', () => { - it('return the resource of id 1', function () { - // action - const resource = resourceNameManager.createResource({ description: 'meow', name: 'cat' }); +// // expectation +// expect(resource.id).toBe(1); +// expect(resource.name).toBe('ronin'); +// expect(resource.description).toBe('can you do a logistics run?'); +// }); +// }); +// describe('#createResource', () => { +// it('return the resource of id 1', function () { +// // action +// const resource = resourceNameManager.createResource({ description: 'meow', name: 'cat' }); + +// // expectation +// expect(resource.id).toBeLessThanOrEqual(100); +// expect(resource.id).toBeGreaterThanOrEqual(0); +// expect(resource).toHaveProperty('name', 'cat'); +// expect(resource).toHaveProperty('description', 'meow'); +// }); +// }); +// }); - // expectation - expect(resource.id).toBeLessThanOrEqual(100); - expect(resource.id).toBeGreaterThanOrEqual(0); - expect(resource).toHaveProperty('name', 'cat'); - expect(resource).toHaveProperty('description', 'meow'); - }); +describe('need to delete', () => { + it('should pass', () => { + const a = true; + expect(a).toBe(true); }); });