Skip to content

Commit

Permalink
feat(@aws-amplify/geo): add geofence APIs (aws-amplify#9743)
Browse files Browse the repository at this point in the history
* feat(@aws-amplify/geo): add geofence APIs (aws-amplify#9278)

* feat(@aws-amplify/geo): verify coordinates

* chore(@aws-amplify/geo): remove unused file

* feat(@aws-amplify/geo): add initial types for geofences

* chore(@aws-amplify/geo): add types and validation utils

* feat(@aws-amplify/geo): add createGeofence to provider

* feat(@aws-amplify/geo): add createGeofence to Geo

* fix(@aws-amplify/geo): remove bad import

* fix(@aws-amplify/geo): update jsdoc on createGeofence

Co-authored-by: Amplifiyer <51211245+Amplifiyer@users.noreply.github.com>

* fix(@aws-amplify/geo): update jsdoc on createGeofence in provider

Co-authored-by: Amplifiyer <51211245+Amplifiyer@users.noreply.github.com>

* fix(@aws-amplify/geo): update error message for bad polygon

Co-authored-by: Amplifiyer <51211245+Amplifiyer@users.noreply.github.com>

* fix(@aws-amplify/geo): first update from PR comments

* fix(@aws-amplify/geo): update #2 from PR comments

* fix(@aws-amplify/geo): update types and batch calls

* Update packages/geo/src/types/Geo.ts

Co-authored-by: Amplifiyer <51211245+Amplifiyer@users.noreply.github.com>

* fix(geo): update types from PR feedback

* chore(geo): add error handling on failed API call

* test(geo): add test for batch API calls

* test(geo): add test for bad api call in createGeofences

feat(geo): add getGeofence api (aws-amplify#9309)

* feat(@aws-amplify/geo): verify coordinates

* chore(@aws-amplify/geo): add types and validation utils

* feat(@aws-amplify/geo): add createGeofence to provider

* feat(@aws-amplify/geo): add createGeofence to provider

* feat(geo): add getGeofence api

* chore(geo): combine some try/catch blocks

* chore(geo): add > to jsdoc comment

feat(geo): add listGeofences api (aws-amplify#9310)

feat(geo): add updateGeofences api (aws-amplify#9312)

* feat(geo): add listGeofences api

* feat(geo): add initial updateGeofences api

* refactor(geo): optimize _batchPutGeofence function

feat(geo): add deleteGeofences api (aws-amplify#9314)

* feat(@aws-amplify/geo): verify coordinates

* feat(geo): batch deleteGeofences call

* chore(geo): fix issue with response

refactor(geo): update loggers and remove unused code

refactor(geo): create/updateGeofences => saveGeofences

chore(geo): split out testData and testFunctions

* fix(geo): update validations and error messages (aws-amplify#9670)

* chore(geo): remove unused `logger` function

* fix(geo): update validation error messages

* fix(geo): add validation for empty input arrays

* fix(geo): polygon if statement and nits

* fix(geo): get rid of that really bad extra space in comment

* fix(geo): fix nextToken type

* fix(geo): fix missspelling

* fix(geo): update batch array naming and types

* fix(geo): add GeofenceId type

* fix(geo): add test for tooManyVertices
  • Loading branch information
TreTuna authored Apr 4, 2022
1 parent a300b38 commit c1ea4e1
Show file tree
Hide file tree
Showing 13 changed files with 2,023 additions and 89 deletions.
174 changes: 170 additions & 4 deletions packages/geo/__tests__/Geo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,18 @@ import {
awsConfig,
TestPlacePascalCase,
testPlaceCamelCase,
} from './data';
validGeometry,
validGeofences,
validGeofence1,
singleGeofenceCamelcaseResults,
batchGeofencesCamelcaseResults,
} from './testData';

import {
mockBatchPutGeofenceCommand,
mockGetGeofenceCommand,
mockListGeofencesCommand,
} from './testUtils';

LocationClient.prototype.send = jest.fn(async command => {
if (
Expand Down Expand Up @@ -134,7 +145,7 @@ describe('Geo', () => {
geo.configure({});

expect(() => geo.getAvailableMaps()).toThrow(
"No map resources found in amplify config, run 'amplify add geo' to create them and run `amplify push` after"
"No map resources found in amplify config, run 'amplify add geo' to create one and run `amplify push` after"
);
});

Expand All @@ -159,7 +170,7 @@ describe('Geo', () => {
geo.configure({});

expect(() => geo.getDefaultMap()).toThrow(
"No map resources found in amplify config, run 'amplify add geo' to create them and run `amplify push` after"
"No map resources found in amplify config, run 'amplify add geo' to create one and run `amplify push` after"
);
});

Expand Down Expand Up @@ -309,7 +320,7 @@ describe('Geo', () => {
});

describe('searchByCoordinates', () => {
const testCoordinates: Coordinates = [12345, 67890];
const testCoordinates: Coordinates = [45, 90];

test('should search with just coordinate input', async () => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
Expand Down Expand Up @@ -371,4 +382,159 @@ describe('Geo', () => {
);
});
});

describe('saveGeofences', () => {
test('saveGeofences with a single geofence', async () => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return Promise.resolve(credentials);
});

LocationClient.prototype.send = jest
.fn()
.mockImplementationOnce(mockBatchPutGeofenceCommand);

const geo = new GeoClass();
geo.configure(awsConfig);

// Check that results are what's expected
const results = await geo.saveGeofences(validGeofence1);
expect(results).toEqual(singleGeofenceCamelcaseResults);

// Expect that the API was called with the proper input
const spyon = jest.spyOn(LocationClient.prototype, 'send');
const input = spyon.mock.calls[0][0].input;
const output = {
Entries: [
{
GeofenceId: validGeofence1.geofenceId,
Geometry: {
Polygon: validGeofence1.geometry.polygon,
},
},
],
CollectionName: 'geofenceCollectionExample',
};
expect(input).toEqual(output);
});

test('saveGeofences with multiple geofences', async () => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return Promise.resolve(credentials);
});

LocationClient.prototype.send = jest
.fn()
.mockImplementation(mockBatchPutGeofenceCommand);

const geo = new GeoClass();
geo.configure(awsConfig);

// Check that results are what's expected
const results = await geo.saveGeofences(validGeofences);
expect(results).toEqual(batchGeofencesCamelcaseResults);

// Expect that the API was called the right amount of times
const expectedNumberOfCalls = Math.floor(validGeofences.length / 10) + 1;
expect(LocationClient.prototype.send).toHaveBeenCalledTimes(
expectedNumberOfCalls
);
});

test('should fail if there is no provider', async () => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return Promise.resolve(credentials);
});

const geo = new GeoClass();
geo.configure(awsConfig);
geo.removePluggable('AmazonLocationService');

await expect(geo.saveGeofences(validGeofence1)).rejects.toThrow(
'No plugin found in Geo for the provider'
);
});
});

describe('getGeofence', () => {
test('getGeofence returns the right geofence', async () => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return Promise.resolve(credentials);
});

LocationClient.prototype.send = jest
.fn()
.mockImplementationOnce(mockGetGeofenceCommand);

const geo = new GeoClass();
geo.configure(awsConfig);

// Check that results are what's expected
const results = await geo.getGeofence('testGeofenceId');
const expected = {
geofenceId: 'testGeofenceId',
geometry: validGeometry,
createTime: '2020-04-01T21:00:00.000Z',
updateTime: '2020-04-01T21:00:00.000Z',
status: 'ACTIVE',
};
expect(results).toEqual(expected);

// Expect that the API was called with the proper input
const spyon = jest.spyOn(LocationClient.prototype, 'send');
const input = spyon.mock.calls[0][0].input;
const output = {
GeofenceId: 'testGeofenceId',
CollectionName: 'geofenceCollectionExample',
};
expect(input).toEqual(output);
});
});

describe('listGeofences', () => {
test('listGeofences gets the first 100 geofences when no arguments are given', async () => {
jest.spyOn(Credentials, 'get').mockImplementationOnce(() => {
return Promise.resolve(credentials);
});

LocationClient.prototype.send = jest
.fn()
.mockImplementationOnce(mockListGeofencesCommand);

const geo = new GeoClass();
geo.configure(awsConfig);

// Check that results are what's expected
const results = await geo.listGeofences();
expect(results.entries.length).toEqual(100);
});

test('listGeofences gets the second 100 geofences when nextToken is passed', async () => {
jest.spyOn(Credentials, 'get').mockImplementation(() => {
return Promise.resolve(credentials);
});

LocationClient.prototype.send = jest
.fn()
.mockImplementation(mockListGeofencesCommand);

const geo = new GeoClass();
geo.configure(awsConfig);

// Check that results are what's expected

const first100Geofences = await geo.listGeofences();

const second100Geofences = await geo.listGeofences({
nextToken: first100Geofences.nextToken,
});

expect(second100Geofences.entries.length).toEqual(100);
expect(second100Geofences.entries[0].geofenceId).toEqual(
'validGeofenceId100'
);
expect(second100Geofences.entries[99].geofenceId).toEqual(
'validGeofenceId199'
);
});
});
});
Loading

0 comments on commit c1ea4e1

Please sign in to comment.