Skip to content

Commit

Permalink
HARMONY-1889: Add EDR endpoint testing of the averagingType parameter.
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-durbin committed Sep 25, 2024
1 parent cfe00bf commit 3446b9d
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 79 deletions.
2 changes: 1 addition & 1 deletion services/harmony/app/models/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -870,13 +870,13 @@ const allFilterFns = [
filterConcatenationMatches,
filterVariableSubsettingMatches,
filterSpatialSubsettingMatches,
filterShapefileSubsettingMatches,
filterTemporalSubsettingMatches,
filterDimensionSubsettingMatches,
filterReprojectionMatches,
filterExtendMatches,
filterAreaAveragingMatches,
filterTimeAveragingMatches,
filterShapefileSubsettingMatches,
// This filter must be last because it chooses a format based on the accepted MimeTypes and
// the remaining services that could support the operation. If it ran earlier we could
// potentially eliminate services that a different accepted MimeType would have allowed. We
Expand Down
13 changes: 13 additions & 0 deletions services/harmony/test/helpers/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Partially applies a function by pre-filling some arguments.
*
* @param fn - The original function to partially apply.
* @param presetArgs - Arguments to pre-fill when calling the function.
*
* @returns A new function that takes the remaining arguments and calls the original function
* with both the preset and remaining arguments.
*
*/
export function partialApply(fn: (...args: unknown[]) => void, ...presetArgs: unknown[]) {
return (...laterArgs: unknown[]): void => fn(...presetArgs, ...laterArgs);
}
183 changes: 105 additions & 78 deletions services/harmony/test/parameters/averaging_type.ts
Original file line number Diff line number Diff line change
@@ -1,107 +1,134 @@
// Note that there are currently no time or area averaging services in services.yml
// which is why several of the assertions are using `xit`. Once there are services to
// support it we should enable the assertions and uncomment out the code to follow
// the redirects.

import { expect } from 'chai';
// import { hookRedirect } from '../helpers/hooks';
import { hookRangesetRequest } from '../helpers/ogc-api-coverages';
import hookServersStartStop from '../helpers/servers';
import StubService from '../helpers/stub-service';
import { hookEdrRequest } from '../helpers/ogc-api-edr';
import { partialApply } from '../helpers/util';
// import { hookRedirect } from '../helpers/hooks';

// Note that there are currently no time or area averaging services in services.yml
// which is why several of the assertions are using `xit`. Once there are services to
// support it we should enable the assertions and uncomment out the code to follow
// the redirects.
describe('averagingType', function () {
const collection = 'C1233800302-EEDTEST';
hookServersStartStop();

describe('when making a request with averagingType time', function () {
const averagingTimeQuery = {
averagingType: 'time',
};

describe('for a collection that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
hookRangesetRequest('1.0.0', collection, 'all', { query: { ...averagingTimeQuery } });
// hookRedirect('anonymous');

xit('returns a 200 status code for the request', async function () {
expect(this.res.status).to.equal(200);
});
const collection = 'C1233800302-EEDTEST';
const edrVersion = '1.1.0';

// We want to test the averagingType parameter on each of the following APIs, so we'll
// run the same tests against each in a loop
const endpointFunctions = [{
label: 'OGC Coverages',
endpointFn: partialApply(hookRangesetRequest, '1.0.0', collection, 'all'),
extraArgs: {},
}, {
label: 'EDR area',
endpointFn: partialApply(hookEdrRequest, 'area', edrVersion, collection),
extraArgs: { coords: 'POLYGON ((-65.3 -13.2, -29.8 -50.9, 17.9 30.1, -65.3 -13.2))' },
}, {
label: 'EDR position',
endpointFn: partialApply(hookEdrRequest, 'position', edrVersion, collection),
extraArgs: { coords: 'POINT (-40 10)' },
}, {
label: 'EDR trajectory',
endpointFn: partialApply(hookEdrRequest, 'trajectory', edrVersion, collection),
extraArgs: { coords: 'LINESTRING (-40 10, 30 10)' },
}, {
label: 'EDR cube',
endpointFn: partialApply(hookEdrRequest, 'cube', edrVersion, collection),
extraArgs: { bbox: '-20.1,0,20,10' },
}];

for (const { label, endpointFn, extraArgs } of endpointFunctions) {
describe(`averagingType for ${label} API`, function () {
hookServersStartStop();

describe('when making a request with averagingType time', function () {
const averagingTimeQuery = {
averagingType: 'time',
};

xit('specifies to perform time averaging in the operation', async function () {
expect(this.service.operation.averagingType).to.equal('time');
});
});
describe('for a collection that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
endpointFn({ query: { ...averagingTimeQuery, ...extraArgs } });
// hookRedirect('anonymous');

describe('for a collection that has no service that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
hookRangesetRequest('1.0.0', collection, 'all', { query: { ...averagingTimeQuery } });
xit('returns a 200 status code for the request', async function () {
expect(this.res.status).to.equal(200);
});

xit('returns a 400 status code for the request', async function () {
expect(this.res.status).to.equal(400);
xit('specifies to perform time averaging in the operation', async function () {
expect(this.service.operation.averagingType).to.equal('time');
});
});

xit('returns a message indicating that no service supports time averaging', async function () {
const errorMessage = {
'code': 'harmony.UnsupportedOperation',
'description': 'Error: the requested combination of operations: time averaging on C1233800302-EEDTEST is unsupported',
};
expect(this.res.body).to.eql(errorMessage);
describe('for a collection that has no service that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
endpointFn({ query: { ...averagingTimeQuery, ...extraArgs } });

it('returns a 422 status code for the request', async function () {
expect(this.res.status).to.equal(422);
});

it('returns a message indicating that no service supports time averaging', async function () {
const error = this.res.body;
expect(error.code).to.equal('harmony.UnsupportedOperation');
expect(error.description).to.include('time averaging');
});
});
});
});

describe('when making a request with averagingType area', function () {
const averagingAreaQuery = {
averagingType: 'area',
};
describe('when making a request with averagingType area', function () {
const averagingAreaQuery = {
averagingType: 'area',
};

describe('for a collection that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
hookRangesetRequest('1.0.0', collection, 'all', { query: { ...averagingAreaQuery } });
// hookRedirect('anonymous');
describe('for a collection that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
endpointFn({ query: { ...averagingAreaQuery, ...extraArgs } });
// hookRedirect('anonymous');

xit('returns a 200 status code for the request', async function () {
expect(this.res.status).to.equal(200);
xit('returns a 200 status code for the request', async function () {
expect(this.res.status).to.equal(200);
});

xit('specifies to perform area averaging in the operation', async function () {
expect(this.service.operation.averagingType).to.equal('area');
});
});

xit('specifies to perform area averaging in the operation', async function () {
expect(this.service.operation.averagingType).to.equal('area');
describe('for a collection that has no service that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
endpointFn({ query: { ...averagingAreaQuery, ...extraArgs } });

it('returns a 422 status code for the request', async function () {
expect(this.res.status).to.equal(422);
});

it('returns a message indicating that no service supports area averaging', async function () {
const error = this.res.body;
expect(error.code).to.equal('harmony.UnsupportedOperation');
expect(error.description).to.include('area averaging');
});
});
});

describe('for a collection that has no service that can support it', function () {
StubService.hook({ params: { redirect: 'http://example.com' } });
hookRangesetRequest('1.0.0', collection, 'all', { query: { ...averagingAreaQuery } });
describe('when making a request with an invalid averagingType', function () {
const badAveragingQuery = {
averagingType: 'no not that',
};
endpointFn({ query: { ...badAveragingQuery, ...extraArgs } });

it('returns a 422 status code for the request', async function () {
expect(this.res.status).to.equal(422);
it('returns a 400 status code for the request', async function () {
expect(this.res.status).to.equal(400);
});

it('returns a message indicating that no service supports area averaging', async function () {
it('returns a message indicating that the averagingType value is invalid', async function () {
const errorMessage = {
'code': 'harmony.UnsupportedOperation',
'description': 'Error: the requested combination of operations: area averaging on C1233800302-EEDTEST is unsupported',
'code': 'harmony.RequestValidationError',
'description': 'Error: query parameter "averagingType" must be either "time" or "area"',
};
expect(this.res.body).to.eql(errorMessage);
});
});
});

describe('when making a request with an invalid averagingType', function () {
const badAveragingQuery = {
averagingType: 'no not that',
};
hookRangesetRequest('1.0.0', collection, 'all', { query: { ...badAveragingQuery } });

it('returns a 400 status code for the request', async function () {
expect(this.res.status).to.equal(400);
});

it('returns a message indicating that the averagingType value is invalid', async function () {
const errorMessage = {
'code': 'harmony.RequestValidationError',
'description': 'Error: query parameter "averagingType" must be either "time" or "area"',
};
expect(this.res.body).to.eql(errorMessage);
});
});
});
}

0 comments on commit 3446b9d

Please sign in to comment.