Skip to content

Commit

Permalink
Add geo test for Cost Surface Piece Exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
yulia-bel committed Oct 4, 2023
1 parent 3366b9d commit 7b762b5
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 0 deletions.
51 changes: 51 additions & 0 deletions api/apps/geoprocessing/test/integration/cloning/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Readable, Transform } from 'stream';
import { DeepPartial, EntityManager, In } from 'typeorm';
import { v4 } from 'uuid';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { CostSurfacePuDataEntity } from "@marxan/cost-surfaces";

export type TestSpecification = {
id: string;
Expand Down Expand Up @@ -595,6 +596,56 @@ export async function GivenOutputScenarioFeaturesData(
.execute();
}

export async function GivenCostSurfaces(
em: EntityManager,
min: number,
max: number,
name: string,
projectId: string,
) {
const costSurface = Array({
id: v4(), min, max, name, project_id: projectId,
})

await Promise.all(
costSurface.map((values) =>
em
.createQueryBuilder()
.insert()
.into('cost_surfaces')
.values(values)
.execute(),
),
);

return costSurface[0];
}

export async function GivenCostSurfaceData(
em: EntityManager,
projectId: string,
costSurfaceId: string,
): Promise<{ id: string; hash: string; feature_id: string }[]> {

const projectPus = await GivenProjectPus(em, projectId, 10);
const insertValues = projectPus.map((pu, index) => ({
id: v4(),
costSurfaceId: costSurfaceId,
projectsPuId: pu.id,
cost: index + 1,

}));

const result = await em
.createQueryBuilder()
.insert()
.into(CostSurfacePuDataEntity)
.values(insertValues)
.returning(['id', 'cost', 'costSurfaceId'])
.execute();

return result.raw;
}
export async function GivenSpecifications(
em: EntityManager,
featuresIds: string[],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { geoprocessingConnections } from '@marxan-geoprocessing/ormconfig';
import { ClonePiece, ExportJobInput } from '@marxan/cloning';
import { ResourceKind } from '@marxan/cloning/domain';
import { ProjectCustomFeaturesContent } from '@marxan/cloning/infrastructure/clone-piece-data/project-custom-features';
import { CloningFilesRepository } from '@marxan/cloning-files-repository';
import { GeoFeatureGeometry } from '@marxan/geofeatures';
import { FixtureType } from '@marxan/utils/tests/fixture-type';
import { Test } from '@nestjs/testing';
import { getEntityManagerToken, TypeOrmModule } from '@nestjs/typeorm';
import { isLeft, Right } from 'fp-ts/lib/Either';
import { Readable } from 'stream';
import { EntityManager, In } from 'typeorm';
import { v4 } from 'uuid';
import {
DeleteProjectAndOrganization, GivenCostSurfaceData, GivenCostSurfaces,
GivenFeatures,
GivenFeaturesData,
GivenProjectExists,
readSavedFile
} from "../fixtures";
import { GeoCloningFilesRepositoryModule } from '@marxan-geoprocessing/modules/cloning-files-repository';
import { FakeLogger } from '@marxan-geoprocessing/utils/__mocks__/fake-logger';
import {
ProjectCostSurfacesPieceExporter
} from "@marxan-geoprocessing/export/pieces-exporters/project-cost-surfaces.piece-exporter";
import { CostSurfacePuDataEntity } from "@marxan/cost-surfaces";
import { ProjectCostSurfacesContent } from "@marxan/cloning/infrastructure/clone-piece-data/project-cost-surfaces";

let fixtures: FixtureType<typeof getFixtures>;

describe(ProjectCostSurfacesPieceExporter, () => {
beforeEach(async () => {
fixtures = await getFixtures();
}, 10_000);

afterEach(async () => {
await fixtures?.cleanUp();
});

it('saves successfully cost surfaces data', async () => {
const input = fixtures.GivenAProjectCostSurfacesExportJob();
await fixtures.GivenProjectExist();
await fixtures.GivenCostSurfacesForProject();
await fixtures
.WhenPieceExporterIsInvoked(input)
.ThenAProjectCostSurfacesFileIsSaved();
});
});

const getFixtures = async () => {
const sandbox = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
...geoprocessingConnections.apiDB,
keepConnectionAlive: true,
logging: false,
}),
TypeOrmModule.forRoot({
...geoprocessingConnections.default,
keepConnectionAlive: true,
logging: false,
}),
TypeOrmModule.forFeature([GeoFeatureGeometry]),
GeoCloningFilesRepositoryModule,
],
providers: [ProjectCostSurfacesPieceExporter],
}).compile();

await sandbox.init();
sandbox.useLogger(new FakeLogger());

const projectId = v4();
const organizationId = v4();
const sut = sandbox.get(ProjectCostSurfacesPieceExporter);
const apiEntityManager: EntityManager = sandbox.get(
getEntityManagerToken(geoprocessingConnections.apiDB),
);
const geoEntityManager: EntityManager = sandbox.get(
getEntityManagerToken(geoprocessingConnections.default),
);
const costSurfacesDataRepo = geoEntityManager.getRepository(CostSurfacePuDataEntity);
const fileRepository = sandbox.get(CloningFilesRepository);


return {
cleanUp: async () => {
await DeleteProjectAndOrganization(
apiEntityManager,
projectId,
organizationId,
);
await costSurfacesDataRepo.delete({});

},
GivenAProjectCostSurfacesExportJob: (): ExportJobInput => {
return {
allPieces: [
{ resourceId: projectId, piece: ClonePiece.ProjectMetadata },
{
resourceId: projectId,
piece: ClonePiece.ProjectCostSurfaces,
},
],
componentId: v4(),
exportId: v4(),
piece: ClonePiece.ProjectCostSurfaces,
resourceId: projectId,
resourceKind: ResourceKind.Project,
};
},
GivenProjectExist: async () => {
return GivenProjectExists(apiEntityManager, projectId, organizationId);
},
GivenCostSurfacesForProject: async () => {
const costSurface = await GivenCostSurfaces(
apiEntityManager,
1, 10, 'Cost Surface', projectId
);

await GivenCostSurfaceData(
geoEntityManager,
projectId,
costSurface.id,
);
return costSurface.id;
},
GivenTagOnFeature: async (featureId: string, tag: string) =>
await apiEntityManager.query(`INSERT INTO project_feature_tags
(project_id, feature_id, tag)
VALUES
('${projectId}', '${featureId}', '${tag}' ) `),

WhenPieceExporterIsInvoked: (input: ExportJobInput) => {
return {
ThenAProjectCostSurfacesFileIsSaved: async () => {
const result = await sut.run(input);
const file = await fileRepository.get(result.uris[0].uri);
expect((file as Right<Readable>).right).toBeDefined();
if (isLeft(file)) throw new Error();
const savedStrem = file.right;
const content = await readSavedFile<ProjectCostSurfacesContent>(
savedStrem,
);
expect(content.costSurfaces).toHaveLength(1);
const costSurfacesExported = content.costSurfaces;



expect(
costSurfacesExported.every(
({ name, data, min, max }) =>
name === 'cost surface' &&
data.length === 10
),
);
},
};
},
};
};

0 comments on commit 7b762b5

Please sign in to comment.