From 90aa9dd35583cc5392a16def2ef8f49a7dd228ed Mon Sep 17 00:00:00 2001 From: alexeh Date: Wed, 6 Mar 2024 12:21:08 +0300 Subject: [PATCH] geo-features tests --- api/test/common-steps/given-geo-region.ts | 16 +++ .../eudr/eudr-admin-region-filters.spec.ts | 2 +- api/test/e2e/eudr/fixtures.ts | 4 - api/test/e2e/geo-regions/fixtures.ts | 111 +++++++++++------- api/test/e2e/geo-regions/geo-features.spec.ts | 55 +++++++++ api/test/entity-mocks.ts | 3 +- ...random-name.ts => generate-random-name.ts} | 2 +- api/test/utils/test-manager.ts | 12 +- 8 files changed, 152 insertions(+), 53 deletions(-) create mode 100644 api/test/common-steps/given-geo-region.ts create mode 100644 api/test/e2e/geo-regions/geo-features.spec.ts rename api/test/utils/{random-name.ts => generate-random-name.ts} (79%) diff --git a/api/test/common-steps/given-geo-region.ts b/api/test/common-steps/given-geo-region.ts new file mode 100644 index 000000000..49259ca43 --- /dev/null +++ b/api/test/common-steps/given-geo-region.ts @@ -0,0 +1,16 @@ +import { createGeoRegion } from '../entity-mocks'; +import { GeoRegion } from '../../src/modules/geo-regions/geo-region.entity'; + +const wkt = require('wellknown'); + +const geomstring = + 'MULTIPOLYGON (((-74.94038756755259 -8.789917036555973, -74.9404292564128 -8.78987345274758, -74.94037947090003 -8.789320280383404, -74.94007769168027 -8.78832128710426, -74.94014586742746 -8.788218619928239, -74.94016386858105 -8.78780352397087, -74.94010104117281 -8.787799975977926, -74.94010288471793 -8.78778799293464, -74.9395829026956 -8.787693953632717, -74.93871995380748 -8.787450557792479, -74.93826369227841 -8.787672292367361, -74.93588217957925 -8.78758885088354, -74.93581959017885 -8.787667135197673, -74.9357715871026 -8.788277919312772, -74.93494257105218 -8.78845185941805, -74.93498553672873 -8.788177110353425, -74.93374345713029 -8.788556626292976, -74.9326813890679 -8.788562556226449, -74.93185593961496 -8.788775235806332, -74.93064363729047 -8.789016035583105, -74.92945984843114 -8.789701969314692, -74.92933888309716 -8.79004576552706, -74.92900915373343 -8.790418620740047, -74.92907515796331 -8.791877374183946, -74.92920716642304 -8.792695696771696, -74.92975920180011 -8.793276823308746, -74.9315893190828 -8.793092997666013, -74.93331142944389 -8.792891382340077, -74.93551357056765 -8.792594889014318, -74.93895179090532 -8.79218572783506, -74.9395578297432 -8.79241699290495, -74.9406559001128 -8.79224502658469, -74.94093191780134 -8.79210863944635, -74.94088391472505 -8.79196039249988, -74.94060189665201 -8.791729127144945, -74.94034388011707 -8.791438562776397, -74.94015186781199 -8.791088699254734, -74.94014586742746 -8.790721045706444, -74.94026587511813 -8.790288162835186, -74.9404098843469 -8.78997980760475, -74.94038756755259 -8.789917036555973), (-74.9373868084098 -8.7894253831326, -74.9374531890935 -8.789707501038329, -74.93732595944972 -8.789840262405733, -74.93722085670055 -8.789856857576657, -74.93708256360951 -8.789541549329078, -74.9373868084098 -8.7894253831326)))'; + +export const GivenGeoRegionWithGeometry = async ( + additionalData?: Partial, +): Promise => { + return await createGeoRegion({ + theGeom: wkt.parse(geomstring), + ...additionalData, + }); +}; diff --git a/api/test/e2e/eudr/eudr-admin-region-filters.spec.ts b/api/test/e2e/eudr/eudr-admin-region-filters.spec.ts index 17e2a74d4..d7fdaf65a 100644 --- a/api/test/e2e/eudr/eudr-admin-region-filters.spec.ts +++ b/api/test/e2e/eudr/eudr-admin-region-filters.spec.ts @@ -4,7 +4,7 @@ describe('Admin Regions EUDR Filters (e2e)', () => { let testManager: EUDRTestManager; beforeAll(async () => { - testManager = await EUDRTestManager.load(); + testManager = await EUDRTestManager.load(EUDRTestManager); }); beforeEach(async () => { diff --git a/api/test/e2e/eudr/fixtures.ts b/api/test/e2e/eudr/fixtures.ts index e776fe852..de379245c 100644 --- a/api/test/e2e/eudr/fixtures.ts +++ b/api/test/e2e/eudr/fixtures.ts @@ -16,10 +16,6 @@ export class EUDRTestManager extends TestManager { super(manager.testApp, manager.jwtToken, manager.dataSource); } - static async load() { - return new EUDRTestManager(await this.createManager()); - } - GivenAdminRegionsOfSourcingLocations = async () => { const adminRegion = await createAdminRegion({ name: 'Regular AdminRegion', diff --git a/api/test/e2e/geo-regions/fixtures.ts b/api/test/e2e/geo-regions/fixtures.ts index 3c4745df6..cc57ff2ff 100644 --- a/api/test/e2e/geo-regions/fixtures.ts +++ b/api/test/e2e/geo-regions/fixtures.ts @@ -1,63 +1,90 @@ -import { createGeoRegion, createSourcingLocation } from '../../entity-mocks'; -import { TestApplication } from '../../utils/application-manager'; +import { createSourcingLocation } from '../../entity-mocks'; import * as request from 'supertest'; import { GeoRegion } from '../../../src/modules/geo-regions/geo-region.entity'; import { LOCATION_TYPES } from '../../../src/modules/sourcing-locations/sourcing-location.entity'; +import { TestManager } from '../../utils/test-manager'; +import { Feature, Geometry } from 'geojson'; +import { GivenGeoRegionWithGeometry } from '../../common-steps/given-geo-region'; -export const geoRegionFixtures = () => ({ - GivenGeoRegionsOfSourcingLocations: async () => { - const geoRegion = await createGeoRegion({ - name: 'Regular GeoRegion', +export class GeoRegionsTestManager extends TestManager { + constructor(manager: TestManager) { + super(manager.testApp, manager.jwtToken, manager.dataSource); + } + + GivenRegularSourcingLocationsWithGeoRegions = async () => { + const geoRegion = await GivenGeoRegionWithGeometry(); + const geoRegion2 = await GivenGeoRegionWithGeometry(); + const sourcingLocation1 = await createSourcingLocation({ + geoRegionId: geoRegion.id, + locationType: LOCATION_TYPES.ADMINISTRATIVE_REGION_OF_PRODUCTION, }); - const geoRegion2 = await createGeoRegion({ - name: 'Regular GeoRegion 2', + const sourcingLocation2 = await createSourcingLocation({ + geoRegionId: geoRegion2.id, + locationType: LOCATION_TYPES.PRODUCTION_AGGREGATION_POINT, }); - await createSourcingLocation({ geoRegionId: geoRegion.id }); - await createSourcingLocation({ geoRegionId: geoRegion2.id }); return { + sourcingLocations: [sourcingLocation1, sourcingLocation2], geoRegions: [geoRegion, geoRegion2], }; - }, - GivenEUDRGeoRegions: async () => { - const geoRegion = await createGeoRegion({ - name: 'EUDR GeoRegion', - }); - const geoRegion2 = await createGeoRegion({ - name: 'EUDR GeoRegion 2', - }); - await createSourcingLocation({ + }; + + GivenEUDRSourcingLocationsWithGeoRegions = async () => { + const geoRegion = await GivenGeoRegionWithGeometry(); + const geoRegion2 = await GivenGeoRegionWithGeometry(); + const sourcingLocation1 = await createSourcingLocation({ geoRegionId: geoRegion.id, locationType: LOCATION_TYPES.EUDR, }); - await createSourcingLocation({ + const sourcingLocation2 = await createSourcingLocation({ geoRegionId: geoRegion2.id, locationType: LOCATION_TYPES.EUDR, }); return { eudrGeoRegions: [geoRegion, geoRegion2], + eudrSourcingLocations: [sourcingLocation1, sourcingLocation2], }; - }, - WhenIRequestEUDRGeoRegions: async (options: { - app: TestApplication; - jwtToken: string; - }) => { - return request(options.app.getHttpServer()) - .get(`/api/v1/geo-regions/eudr`) - .set('Authorization', `Bearer ${options.jwtToken}`); - }, - ThenIShouldOnlyReceiveEUDRGeoRegions: ( - response: request.Response, + }; + + WhenIRequestEUDRGeoFeatures = async (filters: { + 'geoRegionIds[]': string[]; + collection?: boolean; + }): Promise => { + this.response = await request(this.testApp.getHttpServer()) + .get('/api/v1/eudr/geo-features') + .query(filters) + .set('Authorization', `Bearer ${this.jwtToken}`); + }; + + WhenIRequestEUDRGeoFeatureCollection = async (filters: { + 'geoRegionIds[]': string[]; + }): Promise => { + this.response = await request(this.testApp.getHttpServer()) + .get('/api/v1/eudr/geo-features/collection') + .query(filters) + .set('Authorization', `Bearer ${this.jwtToken}`); + }; + + ThenIShouldOnlyRecieveCorrespondingGeoFeatures = ( eudrGeoRegions: GeoRegion[], + collection?: boolean, ) => { - expect(response.status).toBe(200); - expect(response.body.data.length).toBe(eudrGeoRegions.length); - for (const geoRegion of eudrGeoRegions) { - expect( - response.body.data.find( - (geoRegionResponse: GeoRegion) => - geoRegionResponse.id === geoRegion.id, - ), - ).toBeDefined(); + expect(this.response!.status).toBe(200); + if (collection) { + expect(this.response!.body.geojson.type).toEqual('FeatureCollection'); + expect(this.response!.body.geojson.features.length).toBe( + eudrGeoRegions.length, + ); + } else { + expect(this.response!.body[0].geojson.type).toEqual('Feature'); + expect(this.response!.body.length).toBe(eudrGeoRegions.length); + for (const geoRegion of eudrGeoRegions) { + expect( + this.response!.body.find( + (geoRegionResponse: { geojson: Feature }) => + geoRegionResponse.geojson.properties?.id === geoRegion.id, + ), + ).toBeDefined(); + } } - }, -}); + }; +} diff --git a/api/test/e2e/geo-regions/geo-features.spec.ts b/api/test/e2e/geo-regions/geo-features.spec.ts new file mode 100644 index 000000000..b335a9403 --- /dev/null +++ b/api/test/e2e/geo-regions/geo-features.spec.ts @@ -0,0 +1,55 @@ +import { GeoRegionsTestManager } from './fixtures'; + +describe('Admin Regions EUDR Filters (e2e)', () => { + let testManager: GeoRegionsTestManager; + + beforeAll(async () => { + testManager = await GeoRegionsTestManager.load(GeoRegionsTestManager); + }); + + beforeEach(async () => { + await testManager.refreshState(); + }); + + afterEach(async () => { + await testManager.clearDatabase(); + }); + + afterAll(async () => { + await testManager.close(); + }); + + test('should only get geo-features that are part of EUDR data', async () => { + await testManager.GivenRegularSourcingLocationsWithGeoRegions(); + const { eudrGeoRegions } = + await testManager.GivenEUDRSourcingLocationsWithGeoRegions(); + await testManager.WhenIRequestEUDRGeoFeatures({ + 'geoRegionIds[]': eudrGeoRegions.map((r) => r.id), + }); + testManager.ThenIShouldOnlyRecieveCorrespondingGeoFeatures(eudrGeoRegions); + }); + + test('should only get geo-features that are part of EUDR data and are filtered by geo region id', async () => { + await testManager.GivenRegularSourcingLocationsWithGeoRegions(); + const { eudrGeoRegions } = + await testManager.GivenEUDRSourcingLocationsWithGeoRegions(); + await testManager.WhenIRequestEUDRGeoFeatures({ + 'geoRegionIds[]': [eudrGeoRegions[0].id], + }); + testManager.ThenIShouldOnlyRecieveCorrespondingGeoFeatures([ + eudrGeoRegions[0], + ]); + }); + test('sould only get EUDR geo-features as a FeatureCollection', async () => { + await testManager.GivenRegularSourcingLocationsWithGeoRegions(); + const { eudrGeoRegions } = + await testManager.GivenEUDRSourcingLocationsWithGeoRegions(); + await testManager.WhenIRequestEUDRGeoFeatureCollection({ + 'geoRegionIds[]': eudrGeoRegions.map((r) => r.id), + }); + testManager.ThenIShouldOnlyRecieveCorrespondingGeoFeatures( + eudrGeoRegions, + true, + ); + }); +}); diff --git a/api/test/entity-mocks.ts b/api/test/entity-mocks.ts index 4bd5670bf..2d7acf432 100644 --- a/api/test/entity-mocks.ts +++ b/api/test/entity-mocks.ts @@ -39,6 +39,7 @@ import { User } from '../src/modules/users/user.entity'; import { faker } from '@faker-js/faker'; import { genSalt, hash } from 'bcrypt'; import { v4 as uuidv4 } from 'uuid'; +import { generateRandomName } from './utils/generate-random-name'; async function createAdminRegion( additionalData: Partial = {}, @@ -305,7 +306,7 @@ async function createGeoRegion( '861203a4fffffff', ], h3FlatLength: 7, - name: 'ABC', + name: generateRandomName(), }; const geoRegion = GeoRegion.merge( diff --git a/api/test/utils/random-name.ts b/api/test/utils/generate-random-name.ts similarity index 79% rename from api/test/utils/random-name.ts rename to api/test/utils/generate-random-name.ts index 578ed2a64..690749949 100644 --- a/api/test/utils/random-name.ts +++ b/api/test/utils/generate-random-name.ts @@ -1,4 +1,4 @@ -export const randomName = (length = 10): string => { +export const generateRandomName = (length = 10): string => { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; let result = ''; for (let i = 0; i < length; i++) { diff --git a/api/test/utils/test-manager.ts b/api/test/utils/test-manager.ts index d6190f14a..b6530cbe3 100644 --- a/api/test/utils/test-manager.ts +++ b/api/test/utils/test-manager.ts @@ -11,7 +11,7 @@ import { import { Material } from 'modules/materials/material.entity'; import { Supplier } from 'modules/suppliers/supplier.entity'; import { GeoRegion } from 'modules/geo-regions/geo-region.entity'; -import { randomName } from './random-name'; +import { generateRandomName } from './generate-random-name'; export class TestManager { testApp: TestApplication; @@ -28,6 +28,10 @@ export class TestManager { this.dataSource = dataSource; } + static async load(manager: any) { + return new manager(await this.createManager()); + } + static async createManager() { const testApplication = await ApplicationManager.init(); const dataSource = testApplication.get(DataSource); @@ -68,7 +72,7 @@ export class TestManager { } async createMaterials(names?: string[]) { - const namesToCreate = names || [randomName()]; + const namesToCreate = names || [generateRandomName()]; const createdMaterials: Material[] = []; for (let i = 0; i < namesToCreate.length; i++) { createdMaterials.push(await createMaterial({ name: namesToCreate[i] })); @@ -78,7 +82,7 @@ export class TestManager { } async createSuppliers(names?: string[]) { - const namesToCreate = names || [randomName()]; + const namesToCreate = names || [generateRandomName()]; const createdSuppliers: Supplier[] = []; for (let i = 0; i < namesToCreate.length; i++) { createdSuppliers.push(await createSupplier({ name: namesToCreate[i] })); @@ -88,7 +92,7 @@ export class TestManager { } async createGeoRegions(names?: string[]) { - const namesToCreate = names || [randomName()]; + const namesToCreate = names || [generateRandomName()]; const createdGeoRegions: GeoRegion[] = []; for (let i = 0; i < namesToCreate.length; i++) { createdGeoRegions.push(await createGeoRegion({ name: namesToCreate[i] }));