From 0bc9b014741f6310d61a64c4dbecf65669ffaa6c Mon Sep 17 00:00:00 2001 From: Andrew Whillans Date: Thu, 3 Jan 2019 11:20:15 -0800 Subject: [PATCH] Add tests for new tantalis api calls in application POST and Search --- api/test/application.test.js | 231 ++++++-- .../fixtures/tantalis_api_cl_response.json | 79 +++ api/test/helpers/utils.test.js | 498 ++++++++++++++++++ api/test/search.test.js | 152 ++++++ 4 files changed, 920 insertions(+), 40 deletions(-) create mode 100644 api/test/fixtures/tantalis_api_cl_response.json create mode 100644 api/test/helpers/utils.test.js diff --git a/api/test/application.test.js b/api/test/application.test.js index 80301c9..db2d02a 100644 --- a/api/test/application.test.js +++ b/api/test/application.test.js @@ -7,6 +7,7 @@ const nock = require('nock'); const tantalisResponse = require('./fixtures/tantalis_response.json'); const fieldNames = ['description', 'tantalisID']; const _ = require('lodash'); +const Utils = require('../helpers/utils'); const applicationController = require('../controllers/application.js'); @@ -238,22 +239,82 @@ describe('DELETE /application/id', () => { }); }); -describe.skip('POST /application', () => { - - const bcgwDomain = 'https://openmaps.gov.bc.ca'; - const searchPath = '/geo/pub/WHSE_TANTALIS.TA_CROWN_TENURES_SVW/ows?service=wfs&version=2.0.0&request=getfeature&typename=PUB:WHSE_TANTALIS.TA_CROWN_TENURES_SVW&outputFormat=json&srsName=EPSG:4326&CQL_FILTER=DISPOSITION_TRANSACTION_SID='; +describe('POST /application', () => { let applicationObj = { name: 'Victoria', description: 'victoria', tantalisID: 999999 }; - const bcgw = nock(bcgwDomain); - let urlEncodedTantalisId = `%27${applicationObj.tantalisID}%27`; + let searchResult = { + DISPOSITION_TRANSACTION_SID: 999999, + interestedParties: [ + { + interestedPartyType: 'O', + legalName: 'Megacorp' + }, + { + interestedPartyType: 'I', + firstName: 'Ajit', + lastName: 'Pai' + } + ], + parcels: [ + { + type: 'Feature', + properties: { + TENURE_LEGAL_DESCRIPTION: 'READ THESE BORING LEGAL TERMS.', + TENURE_AREA_IN_HECTARES: 3.333, + INTRID_SID: 12345, + TENURE_EXPIRY: 1527878179000, + FEATURE_CODE: 'FL98000100', + FEATURE_AREA_SQM: 33855.6279054274, + FEATURE_LENGTH_M: 740.122691165678 + }, + crs: { + properties: { + name: 'urn:ogc:def:crs:EPSG::4326' + } + } + } + + ], + areaHectares: 80000, + centroid: [ -128.6704671493984, 58.28816863259513 ], + TENURE_PURPOSE: 'To rule the world', + TENURE_SUBPURPOSE: 'And all of the chocolates', + TENURE_TYPE: 'EVIL', + TENURE_SUBTYPE: 'LANDLORD', + TENURE_STATUS: 'PENDING', + TENURE_STAGE: 'LEFT', + TENURE_LOCATION: 'Megalopolis', + RESPONSIBLE_BUSINESS_UNIT: 'Not present', + CROWN_LANDS_FILE: 7654321, + }; + describe('when the ttls api login call returns successfully', () => { + let loginPromise = new Promise(function(resolve, reject) { + resolve('ACCESS_TOKEN'); + }); + + let appDispSearchPromise = new Promise(function(resolve, reject) { + resolve(searchResult); + }); - describe('when bcgw finds a matching object', () => { beforeEach(() => { - return bcgw.get(searchPath + urlEncodedTantalisId) - .reply(200, tantalisResponse); + spyOn(Utils, 'loginWebADE') + .and.returnValue(loginPromise); + + spyOn(Utils, 'getApplicationByDispositionID') + .and.returnValue(appDispSearchPromise); + }); + + test('logs in and then retrieves the application with that access token', done => { + request(app).post('/api/application') + .send(applicationObj) + .expect(200).then(response => { + expect(Utils.loginWebADE).toHaveBeenCalled(); + expect(Utils.getApplicationByDispositionID).toHaveBeenCalledWith('ACCESS_TOKEN', 999999); + done(); + }); }); test('creates a new application', done => { @@ -269,86 +330,176 @@ describe.skip('POST /application', () => { }); }); - test('sets geographical properties', done => { + test('defaults to sysadmin for tags and review tags', done => { request(app).post('/api/application') .send(applicationObj) .expect(200).then(response => { expect(response.body).toHaveProperty('_id'); Application.findById(response.body['_id']).exec(function(error, application) { - expect(application.areaHectares).not.toBeNull(); - expect(application.areaHectares).toBeGreaterThan(1); + expect(application).not.toBeNull(); - expect(application.centroid).toBeDefined(); - expect(application.centroid.length).toBe(2); + expect(application.tags.length).toEqual(1) + expect(application.tags[0]).toEqual(expect.arrayContaining(['sysadmin'])); done(); }); }); }); - test('it sets the _addedBy to the person creating the application', done => { + test('it sets the _createdBy to the person creating the application', done => { request(app).post('/api/application') .send(applicationObj) .expect(200).then(response => { expect(response.body).toHaveProperty('_id'); Application.findOne({description: 'victoria'}).exec(function(error, application) { expect(application).not.toBeNull(); - expect(application._addedBy).not.toBeNull(); - expect(application._addedBy).toEqual(idirUsername); + expect(application._createdBy).not.toBeNull(); + expect(application._createdBy).toEqual(idirUsername); done(); }); }); }); - test('defaults to sysadmin for tags and review tags', done => { - request(app).post('/api/application') + describe('saved application properties', () => { + test('saves the tenure properties correctly', done => { + request(app).post('/api/application') .send(applicationObj) .expect(200).then(response => { expect(response.body).toHaveProperty('_id'); - Application.findById(response.body['_id']).exec(function(error, application) { - expect(application).not.toBeNull(); + Application.findOne({description: 'victoria'}).exec(function(error, application) { + expect(application).toBeDefined(); + expect(application.purpose).toBe('To rule the world'); + expect(application.subpurpose).toBe('And all of the chocolates'); + expect(application.type).toBe('EVIL'); + expect(application.subtype).toBe('LANDLORD'); + expect(application.status).toBe('PENDING'); + expect(application.tenureStage).toBe('LEFT'); + expect(application.location).toBe('Megalopolis'); + done(); + }); + }); + }); - expect(application.tags.length).toEqual(1) - expect(application.tags[0]).toEqual(expect.arrayContaining(['sysadmin'])); + test('sets the geographical properties correctly', done => { + request(app).post('/api/application') + .send(applicationObj) + .expect(200).then(response => { + expect(response.body).toHaveProperty('_id'); + Application.findOne({description: 'victoria'}).exec(function(error, application) { + expect(application).toBeDefined(); + expect(application.areaHectares).toBe(80000); + expect(application.centroid[0]).toEqual(-128.6704671493984); + expect(application.centroid[1]).toEqual(58.28816863259513); + done(); + }); + }); + }); + test('saves the additional properties correctly', done => { + request(app).post('/api/application') + .send(applicationObj) + .expect(200).then(response => { + expect(response.body).toHaveProperty('_id'); + Application.findOne({description: 'victoria'}).exec(function(error, application) { + expect(application).toBeDefined(); + expect(application.businessUnit).toBe('Not present'); + expect(application.cl_file).toBe(7654321); + expect(application.tantalisID).toBe(999999); done(); }); }); - }); + }); - test('saves features on the application', done => { - request(app).post('/api/application') + test('sets the client to the interestedParties name fields', done => { + request(app).post('/api/application') .send(applicationObj) .expect(200).then(response => { expect(response.body).toHaveProperty('_id'); - Feature.findOne({applicationID: response.body['_id']}).exec(function(error, feature) { - expect(feature).not.toBeNull(); - expect(feature.INTRID_SID).not.toBeNull(); + Application.findOne({description: 'victoria'}).exec(function(error, application) { + expect(application).toBeDefined(); + expect(application.client).toEqual('Megacorp, Ajit Pai'); + + done(); + }); + }); + }); + + test('saves features on the application', done => { + request(app).post('/api/application') + .send(applicationObj) + .expect(200).then(response => { + expect(response.body).toHaveProperty('_id'); + Feature.findOne({applicationID: response.body['_id']}).exec(function(error, feature) { + expect(feature).not.toBeNull(); + console.log(feature); + let featureProperties = feature.properties; + expect(featureProperties).toBeDefined(); + expect(featureProperties.INTRID_SID).toEqual(12345); + expect(featureProperties.TENURE_EXPIRY).toEqual('1527878179000'); + expect(featureProperties.TENURE_LEGAL_DESCRIPTION).toEqual('READ THESE BORING LEGAL TERMS.'); + + done(); + }); + }); + }); + + test('strips unwanted attributes', done => { + let objectWithForbiddenAttrs = { + name: 'Evil plan', + description: 'Plan to corrupt this database! ', + tantalisID: 987654, + areaHectares: 10000000, + centroid: [[58], [58]], + purpose: 'To hack this app', + status: 'Beginning', + tenureStage: 'My stage', + location: 'Detroit', + businessUnit: 'Strata', + cl_file: 88888888, + client: 'Dr Strangelove' + }; + + request(app).post('/api/application') + .send(objectWithForbiddenAttrs) + .expect(200).then(response => { + expect(response.body).toHaveProperty('_id'); + Application.findOne({name: 'Evil plan'}).exec(function(error, application) { + expect(application).toBeDefined(); + + expect(application.areaHectares).not.toEqual(10000000); + expect(application.purpose).not.toEqual('To hack this app'); + expect(application.status).not.toEqual('Beginning'); + expect(application.tenureStage).not.toEqual('My stage'); + expect(application.location).not.toEqual('Detroit'); + expect(application.businessUnit).not.toEqual('Strata'); + expect(application.cl_file).not.toEqual(88888888); + expect(application.client).not.toEqual('Dr Strangelove'); + done(); }); }); + }); }); }); - describe('when bcgw returns an error response', () => { - beforeEach(() => { - return bcgw.get(searchPath + urlEncodedTantalisId) - .reply(500, {"error": "Something went wrong"}); + describe('when the login call fails', () => { + let loginPromise = new Promise(function(resolve, reject) { + reject({statusCode: 503, message: 'Ooh boy something went wrong'}); }); - test.skip('throws 500 when an error is caught', done => { + beforeEach(() => { + spyOn(Utils, 'loginWebADE').and.returnValue(loginPromise); + }); + test('returns that error response and a 400 status code', done => { request(app).post('/api/application') .send(applicationObj) - .expect(500) - .catch(errorResponse => { + .expect(400) + .then(response => { + expect(response.body.message).toEqual('Ooh boy something went wrong'); done(); }); }); - - test.skip('handles a 404 correctly', done => { - done(); - }); }); }); diff --git a/api/test/fixtures/tantalis_api_cl_response.json b/api/test/fixtures/tantalis_api_cl_response.json new file mode 100644 index 0000000..04ca9e6 --- /dev/null +++ b/api/test/fixtures/tantalis_api_cl_response.json @@ -0,0 +1,79 @@ +{ + "@type": "LandUseApplicationResources", + "links": [ + { + "@type": "RelLink", + "rel": "self", + "href": "https://api.nrs.gov.bc.ca/ttls-api/v1/landUseApplications?fileNumber=7410005&stage=&status=&type=&purpose=&location=&received=&updated=&pageNumber=1&pageRowCount=1", + "method": "GET" + } + ], + "pageNumber": 1, + "pageRowCount": 1, + "totalRowCount": 1, + "totalPageCount": 1, + "elements": [ + { + "@type": "LandUseApplicationResource", + "links": [], + "landUseApplicationId": 933056, + "clientReferenceNumber": "100246965", + "receivedDate": 1525417200000, + "fileNumber": "7410005", + "locationDescription": "ESKER LAKE", + "lastUpdated": 1533051208000, + "stageCode": { + "@type": "StageCodeResource", + "links": [], + "code": "T", + "description": "TENURE" + }, + "businessUnit": { + "@type": "BusinessUnitResource", + "links": [], + "id": 7, + "name": "OM - LAND MGMNT - NORTHERN SERVICE REGION" + }, + "statusCode": { + "@type": "StatusCodeResource", + "links": [], + "code": "GS", + "description": "DISPOSITION IN GOOD STANDING" + }, + "landUseTypeCode": { + "@type": "LandUseTypeCodeResource", + "links": [], + "code": "7", + "description": "LICENCE", + "landUseSubTypeCodes": [ + { + "@type": "LandUseSubTypeCodeResource", + "links": [], + "code": "2", + "description": "TEMPORARY LICENCE" + } + ] + }, + "purposeCode": { + "@type": "PurposeCodeResource", + "links": [], + "code": "3", + "description": "INDUSTRIAL", + "subPurposeCodes": [ + { + "@type": "SubPurposeCodeResource", + "links": [], + "code": "6", + "description": "MISCELLANEOUS" + } + ] + }, + "documents": [], + "interestedParties": [], + "shapes": [], + "interestParcels": [], + "statusHistory": [], + "parkReasonHistory": [] + } + ] +} \ No newline at end of file diff --git a/api/test/helpers/utils.test.js b/api/test/helpers/utils.test.js new file mode 100644 index 0000000..7926e73 --- /dev/null +++ b/api/test/helpers/utils.test.js @@ -0,0 +1,498 @@ +const Utils = require('../../helpers/utils'); +const nock = require('nock'); +var _ = require('lodash'); + +describe('utils', () => { + const nrsApiDomain = 'https://api.nrs.gov.bc.ca'; + const loginPath = '/oauth2/v1/oauth/token?grant_type=client_credentials&disableDeveloperFilter=true'; + const headers = { + reqheaders: { + authorization: 'Basic VFRMUy1FWFQ6eA==', + } + }; + + describe('loginWebADE', () => { + const nrsApi = nock(nrsApiDomain, headers); + const webAdeResponse = { + access_token: 'ACCESS_TOKEN', + token_type: 'bearer', + expires_in: 43199 + }; + + describe('When the webADE call returns successfully', () => { + beforeEach(() => { + nrsApi.get(loginPath) + .reply(200, webAdeResponse); + }); + + test('returns the access token', done => { + Utils.loginWebADE() + .then(response => { + expect(response).toEqual('ACCESS_TOKEN'); + done(); + }); + }); + }); + + describe('When the webADE call returns with a non-200 status code', () => { + let webADEErrorResponse = { + msg: 'Beep boop, something went wrong' + }; + beforeEach(() => { + nrsApi.get(loginPath) + .reply(400, webADEErrorResponse); + }); + + test('rejects the promise', done => { + Utils.loginWebADE() + .catch(response => { + done(); + }); + }); + }); + }); + + describe('getApplicationByFilenumber', () => { + const nrsApi = nock(nrsApiDomain); + const accessToken = 'ACCESS_TOKEN'; + const fileNumber = '99999' + + const fileSearchPath = '/ttls-api/v1/landUseApplications?fileNumber=99999'; + const ttlsApiResponse = { + "@type": "LandUseApplicationResources", + "links": [ + { + "@type": "RelLink", + "rel": "self", + "href": "https://api.nrs.gov.bc.ca/ttls-api/v1/landUseApplications?fileNumber=7410005&stage=&status=&type=&purpose=&location=&received=&updated=&pageNumber=1&pageRowCount=1", + "method": "GET" + } + ], + "pageNumber": 1, + "pageRowCount": 1, + "totalRowCount": 1, + "totalPageCount": 1, + "elements": [ + { + "@type": "LandUseApplicationResource", + "links": [], + "landUseApplicationId": 777777, + "clientReferenceNumber": "100246965", + "receivedDate": 1525417200000, + "fileNumber": "888888", + "locationDescription": "Over the River and through the woods", + "lastUpdated": 1533051208000, + "stageCode": { + "@type": "StageCodeResource", + "links": [], + "code": "T", + "description": "TENURE" + }, + "businessUnit": { + "@type": "BusinessUnitResource", + "links": [], + "id": 7, + "name": "Super evil corporation" + }, + "statusCode": { + "@type": "StatusCodeResource", + "links": [], + "code": "GS", + "description": "DISPOSITION IN GOOD STANDING" + }, + "landUseTypeCode": { + "@type": "LandUseTypeCodeResource", + "links": [], + "code": "7", + "description": "Yes, this is the land use type code", + "landUseSubTypeCodes": [ + { + "@type": "LandUseSubTypeCodeResource", + "links": [], + "code": "2", + "description": "First land use sub type" + } + ] + }, + "purposeCode": { + "@type": "PurposeCodeResource", + "links": [], + "code": "3", + "description": "I have a very important purpose in life!", + "subPurposeCodes": [ + { + "@type": "SubPurposeCodeResource", + "links": [], + "code": "6", + "description": "This is the first subpurpose description" + } + ] + }, + "documents": [], + "interestedParties": [], + "shapes": [], + "interestParcels": [], + "statusHistory": [], + "parkReasonHistory": [] + } + ] + }; + + describe('When the api call returns successfully', () => { + beforeEach(() => { + nrsApi.get(fileSearchPath) + .reply(200, ttlsApiResponse); + }); + + test('returns an application with the right tenure types and purposes', done => { + Utils.getApplicationByFilenumber(accessToken, fileNumber) + .then(response => { + expect(response.length).toEqual(1); + let firstApplication = response[0]; + expect(firstApplication.TENURE_PURPOSE).toEqual('I have a very important purpose in life!'); + expect(firstApplication.TENURE_SUBPURPOSE).toEqual('This is the first subpurpose description'); + expect(firstApplication.TENURE_TYPE).toEqual('Yes, this is the land use type code'); + expect(firstApplication.TENURE_SUBTYPE).toEqual('First land use sub type'); + + done(); + }); + }); + + test('returns an application with the expected tenure status, stage, and location attrs', done => { + Utils.getApplicationByFilenumber(accessToken, fileNumber) + .then(response => { + expect(response.length).toEqual(1); + let firstApplication = response[0]; + + expect(firstApplication.TENURE_STATUS).toEqual('DISPOSITION IN GOOD STANDING'); + expect(firstApplication.TENURE_STAGE).toEqual('TENURE'); + expect(firstApplication.TENURE_LOCATION).toEqual('Over the River and through the woods'); + + done(); + }); + }); + + test('returns an application with the correct additional attributes', done => { + Utils.getApplicationByFilenumber(accessToken, fileNumber) + .then(response => { + expect(response.length).toEqual(1); + let firstApplication = response[0]; + expect(firstApplication.RESPONSIBLE_BUSINESS_UNIT).toEqual('Super evil corporation'); + expect(firstApplication.CROWN_LANDS_FILE).toEqual('888888'); + expect(firstApplication.DISPOSITION_TRANSACTION_SID).toEqual(777777); + + done(); + }); + }); + }); + }); + + describe('getApplicationByDispositionID', () => { + const nrsApi = nock(nrsApiDomain); + const accessToken = 'ACCESS_TOKEN'; + const dispId = '666666' + const individualPartyObj = { + "@type": "ApplicationInterestedPartyResource", + "links": [], + "interestedPartyId": 293927, + "interestedPartyType": "I", + "individual": { + "firstName": "John", + "lastName": "Doe" + } + }; + const organizationPartyObj = { + "@type": "ApplicationInterestedPartyResource", + "links": [], + "interestedPartyId": 293927, + "interestedPartyType": "O", + "individual": null, + "organization": { + "divisionBranch": "Brasil Tax Evasion", + "legalName": "Operation Car Wash" + } + }; + + const landUseAppSearchPath = '/ttls-api/v1/landUseApplications/666666'; + const ttlsApiResponse = { + "@type": "LandUseApplicationResource", + "links": [ + { + "@type": "RelLink", + "rel": "self", + "href": "https://api.nrs.gov.bc.ca/ttls-api/v1/landUseApplications/933249", + "method": "GET" + } + ], + "landUseApplicationId": 666666, + "clientReferenceNumber": "100244978", + "receivedDate": 1525676400000, + "fileNumber": "888888", + "locationDescription": "Over the River and through the woods", + "lastUpdated": 1527878179000, + "stageCode": { + "@type": "StageCodeResource", + "links": [], + "code": "A", + "description": "TENURE" + }, + "businessUnit": { + "@type": "BusinessUnitResource", + "links": [], + "id": 6, + "name": "Super evil corporation" + }, + "statusCode": { + "@type": "StatusCodeResource", + "links": [], + "code": "AC", + "description": "DISPOSITION IN GOOD STANDING" + }, + "landUseTypeCode": { + "@type": "LandUseTypeCodeResource", + "links": [], + "code": "7", + "description": "Yes, this is the land use type code", + "landUseSubTypeCodes": [ + { + "@type": "LandUseSubTypeCodeResource", + "links": [], + "code": "1", + "description": "First land use sub type" + } + ] + }, + "purposeCode": { + "@type": "PurposeCodeResource", + "links": [], + "code": "3", + "description": "I have a very important purpose in life!", + "subPurposeCodes": [ + { + "@type": "SubPurposeCodeResource", + "links": [], + "code": "6", + "description": "This is the first subpurpose description" + } + ] + }, + "documents": [], + "interestedParties": [individualPartyObj, organizationPartyObj], + "shapes": [], + "interestParcels": [ + { + "@type": "InterestParcelResource", + "links": [], + "interestParcelId": 12345, + "legalDescription": "READ THESE BORING LEGAL TERMS.", + "areaCalcCode": "AUTO", + "areaCalcDescription": "Calculated automatically", + "areaInHectares": 3.333, + "expiryDate": 1527878179000, + "featureCode": "FL98000100", + "areaInSquareMetres": 33855.6279054274, + "areaLengthInMetres": 740.122691165678, + "wktGeometry": "POLYGON ((843405.474983077 1481115.65441351, 843566.561526555 1481059.93430167, 843481.388035521 1480882.29620365, 843313.798870558 1480944.97363803, 843405.474983077 1481115.65441351))" + } + ], + "statusHistory": [ + { + "@type": "ApplicationStatusResource", + "links": [], + "code": "AC", + "description": "ACCEPTED", + "effectiveDate": 1527878179000, + "expiryDate": null + } + ], + "parkReasonHistory": [] + }; + + describe('When the api call returns successfully', () => { + beforeEach(() => { + nrsApi.get(landUseAppSearchPath) + .reply(200, ttlsApiResponse); + }); + + test('returns an application with the right tenure types and purposes', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(response => { + let firstApplication = response; + expect(firstApplication.TENURE_PURPOSE).toEqual('I have a very important purpose in life!'); + expect(firstApplication.TENURE_SUBPURPOSE).toEqual('This is the first subpurpose description'); + expect(firstApplication.TENURE_TYPE).toEqual('Yes, this is the land use type code'); + expect(firstApplication.TENURE_SUBTYPE).toEqual('First land use sub type'); + + done(); + }); + }); + + test('returns an application with the expected tenure status, stage, and location attrs', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(response => { + let firstApplication = response; + + expect(firstApplication.TENURE_STATUS).toEqual('DISPOSITION IN GOOD STANDING'); + expect(firstApplication.TENURE_STAGE).toEqual('TENURE'); + expect(firstApplication.TENURE_LOCATION).toEqual('Over the River and through the woods'); + + done(); + }); + }); + + test('returns an application with the correct additional attributes', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(response => { + let firstApplication = response; + expect(firstApplication.RESPONSIBLE_BUSINESS_UNIT).toEqual('Super evil corporation'); + expect(firstApplication.CROWN_LANDS_FILE).toEqual('888888'); + expect(firstApplication.DISPOSITION_TRANSACTION_SID).toEqual(dispId); + + done(); + }); + }); + + test('sets the statusHistoryEffectiveDate', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(response => { + expect(response.statusHistoryEffectiveDate).toEqual(1527878179000); + + done(); + }); + }); + + describe('parcels', () => { + + // TODO: Figure out how to to properly test centroid and areaHectares calculation + test('sets the areaHectares and centroid properties', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.areaHectares).toEqual(3.333); + expect(application.centroid).not.toBeNull(); + + done(); + }); + }); + + test('it adds parcels to the application', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.parcels).not.toBeNull(); + expect(application.parcels.length).toEqual(1); + const firstParcel = application.parcels[0]; + expect(firstParcel.type).toEqual('Feature'); + + done(); + }); + }); + + test('it sets the feature tenure properties correctly on the parcel', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.parcels.length).toEqual(1); + const firstParcel = application.parcels[0]; + const properties = firstParcel.properties; + expect(properties.TENURE_LEGAL_DESCRIPTION).toEqual('READ THESE BORING LEGAL TERMS.'); + expect(properties.TENURE_AREA_IN_HECTARES).toEqual(3.333); + expect(properties.INTRID_SID).toEqual(12345); + expect(properties.TENURE_EXPIRY).toEqual(1527878179000); + + done(); + }); + }); + + test('it sets the feature properties correctly on the parcel', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.parcels.length).toEqual(1); + const firstParcel = application.parcels[0]; + const properties = firstParcel.properties; + + expect(properties.FEATURE_CODE).toEqual('FL98000100'); + expect(properties.FEATURE_AREA_SQM).toEqual(33855.6279054274); + expect(properties.FEATURE_LENGTH_M).toEqual(740.122691165678); + + done(); + }); + }); + + test('sets the crs properties name', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.parcels.length).toEqual(1); + const firstParcel = application.parcels[0]; + const crs = firstParcel.crs; + expect(crs).not.toBeNull(); + expect(crs.properties.name).toEqual("urn:ogc:def:crs:EPSG::4326"); + + done(); + }); + }); + + // Not sure how to go about testing this, so I'm just testing that something gets set. + test('sets the geometry', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.parcels.length).toEqual(1); + const firstParcel = application.parcels[0]; + const geometry = firstParcel.geometry; + expect(geometry).not.toBeNull(); + expect(geometry.type).toEqual('Polygon'); + expect(geometry.coordinates).toBeDefined(); + + done(); + }); + }); + }); + + describe('interestedParties', () => { + describe('with an individual party type object', () => { + test('it adds the individual party object to the interestedParties array', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.interestedParties.length).toEqual(2); + const individualParty = _.find(application.interestedParties, {interestedPartyType: 'I'}); + expect(individualParty.firstName).toEqual('John'); + expect(individualParty.lastName).toEqual('Doe'); + expect(individualParty.interestedPartyType).toEqual('I'); + + done(); + }); + }); + }); + + describe('with an organization party type object', () => { + test('it adds the organization party object to the interestedParties array', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .then(application => { + expect(application.interestedParties.length).toEqual(2); + const orgParty = _.find(application.interestedParties, {interestedPartyType: 'O'}); + expect(orgParty.legalName).toEqual('Operation Car Wash'); + expect(orgParty.divisionBranch).toEqual('Brasil Tax Evasion'); + expect(orgParty.interestedPartyType).toEqual('O'); + + done(); + }); + }); + }); + }); + }); + + describe('when the api call returns with a non-200 status code', () => { + beforeEach(() => { + nrsApi.get(landUseAppSearchPath) + .reply(500, {error: 'something went wrong'}); + }); + + test('it rejects with an error object', done => { + Utils.getApplicationByDispositionID(accessToken, dispId) + .catch(error => { + expect(error).not.toBeNull(); + expect(error.statusCode).toEqual(500); + + done(); + }); + }); + }); + }); +}); diff --git a/api/test/search.test.js b/api/test/search.test.js index 0975478..5f1a4ad 100644 --- a/api/test/search.test.js +++ b/api/test/search.test.js @@ -7,6 +7,7 @@ const arcGisResponse = require('./fixtures/arcgis_response.json'); const crownlandsResponse = require('./fixtures/crownlands_response.json'); const tantalisResponse = require('./fixtures/tantalis_response.json'); const fieldNames = []; +const Utils = require('../helpers/utils'); const _ = require('lodash'); @@ -21,6 +22,19 @@ require('../helpers/models/feature'); const Application = mongoose.model('Application'); const Feature = mongoose.model('Feature'); + +app.get('/api/search/ttlsapi/crownLandFileNumber/:id', function(req, res) { + let extraFields = test_helper.buildParams({'fileNumber': req.params.id}); + let params = test_helper.createSwaggerParams(fieldNames, extraFields); + return searchController.protectedTTLSGetApplicationsByFileNumber(params, res); +}); + +app.get('/api/search/ttlsapi/dispositionTransactionId/:id', function(req, res) { + let extraFields = test_helper.buildParams({'dtId': req.params.id}); + let params = test_helper.createSwaggerParams(fieldNames, extraFields); + return searchController.protectedTTLSGetApplicationByDisp(params, res); +}); + app.get('/api/public/search/bcgw/getClientsInfoByDispositionId/:id', function(req, res) { return searchController.publicGetClientsInfoByDispositionId(publicParamsWithDtId(req), res); }); @@ -39,6 +53,144 @@ app.get('/api/public/search/bcgw/dispositionTransactionId/:id', function(req, re return searchController.publicGetBCGWDispositionTransactionId(publicParamsWithDtId(req), res); }); +describe('GET /api/search/ttlsapi/crownLandFileNumber/', () => { + let clFileNumber = 555555; + const firstResult = {DISPOSITION_TRANSACTION_SID: 111111}; + const secondResult = {DISPOSITION_TRANSACTION_SID: 222222}; + const dispSearchResult = {}; + + describe('when the ttls api login call returns successfully', () => { + let loginPromise = new Promise(function(resolve, reject) { + resolve('ACCESS_TOKEN'); + }); + + let appFileNumSearchPromise = new Promise(function(resolve, reject) { + resolve([firstResult, secondResult]); + }); + + let appDispSearchPromise = new Promise(function(resolve, reject) { + resolve(dispSearchResult); + }); + + beforeEach(() => { + spyOn(Utils, 'loginWebADE').and.returnValue(loginPromise); + + spyOn(Utils, 'getApplicationByFilenumber') + .and.returnValue(appFileNumSearchPromise); + + spyOn(Utils, 'getApplicationByDispositionID') + .and.returnValue(appDispSearchPromise); + }); + + test('logs in and then searches TTLS by CLFileNumber with that access token', done => { + request(app).get('/api/search/ttlsapi/crownLandFileNumber/' + clFileNumber) + .expect(200) + .then(response => { + expect(Utils.loginWebADE).toHaveBeenCalled(); + expect(Utils.getApplicationByFilenumber).toHaveBeenCalledWith('ACCESS_TOKEN', '555555'); + done(); + }); + }); + + test('searches TTLS getApplicationByDispositionID once for each disp returned by the file number search', done => { + request(app).get('/api/search/ttlsapi/crownLandFileNumber/' + clFileNumber) + .expect(200) + .then(response => { + expect(Utils.getApplicationByFilenumber).toHaveBeenCalledWith('ACCESS_TOKEN', '555555'); + + expect(Utils.getApplicationByDispositionID).toHaveBeenCalledWith('ACCESS_TOKEN', 111111); + expect(Utils.getApplicationByDispositionID).toHaveBeenCalledWith('ACCESS_TOKEN', 222222); + + done(); + }); + }); + + test('returns the search results from each getAppliationByDispositionID call', done => { + request(app).get('/api/search/ttlsapi/crownLandFileNumber/' + clFileNumber) + .expect(200) + .then(response => { + expect(response.body.length).toEqual(2); + expect(response.body).toEqual([dispSearchResult, dispSearchResult]) + + done(); + }); + }); + + }); + + describe('when the ttls api login call fails', () => { + let loginPromise = new Promise(function(resolve, reject) { + reject({statusCode: 503, message: 'Ooh boy something went wrong'}); + }); + + beforeEach(() => { + spyOn(Utils, 'loginWebADE').and.returnValue(loginPromise); + }); + + test('returns that error response', done => { + request(app).get('/api/search/ttlsapi/crownLandFileNumber/' + clFileNumber) + .expect(503) + .then(response => { + expect(response.body.message).toEqual('Ooh boy something went wrong'); + done(); + }); + }); + }); +}); + +describe('GET /api/search/ttlsapi/dispositionTransactionId/', () => { + let dispositionId = 666666; + const searchResult = { + DISPOSITION_TRANSACTION_SID: 666666 + }; + + describe('when the ttls api login call returns successfully', () => { + let loginPromise = new Promise(function(resolve, reject) { + resolve('ACCESS_TOKEN'); + }); + + let appDispSearchPromise = new Promise(function(resolve, reject) { + resolve(searchResult); + }); + + beforeEach(() => { + spyOn(Utils, 'loginWebADE') + .and.returnValue(loginPromise); + + spyOn(Utils, 'getApplicationByDispositionID') + .and.returnValue(appDispSearchPromise); + }); + + test('logs in and then retrieves the application with that access token', done => { + request(app).get('/api/search/ttlsapi/dispositionTransactionId/' + dispositionId) + .expect(200) + .then(response => { + expect(Utils.loginWebADE).toHaveBeenCalled(); + expect(Utils.getApplicationByDispositionID).toHaveBeenCalledWith('ACCESS_TOKEN', '666666'); + done(); + }); + }); + }); + + describe('when the ttls api login call fails', () => { + let loginPromise = new Promise(function(resolve, reject) { + reject({statusCode: 503, message: 'Ooh boy something went wrong'}); + }); + + beforeEach(() => { + spyOn(Utils, 'loginWebADE').and.returnValue(loginPromise); + }); + + test('returns that error response', done => { + request(app).get('/api/search/ttlsapi/dispositionTransactionId/' + dispositionId) + .expect(503) + .then(response => { + expect(response.body.message).toEqual('Ooh boy something went wrong'); + done(); + }); + }); + }); +}); describe('GET /api/public/search/bcgw/getClientsInfoByDispositionId', () => { const arcGisDomain = 'http://maps.gov.bc.ca/';