diff --git a/src/app/controllers/postcodes_controller.ts b/src/app/controllers/postcodes_controller.ts index 67646fc7..d4a686f7 100644 --- a/src/app/controllers/postcodes_controller.ts +++ b/src/app/controllers/postcodes_controller.ts @@ -99,20 +99,21 @@ const bulkGeocode: Handler = async (request, response, next) => { if (geolocations.length > MAX_GEOLOCATIONS) return next(new ExceedMaxGeolocationsError()); - const data: LookupGeolocationResult[] = []; + const data: LookupGeolocationResult[] = new Array(geolocations.length); const lookupGeolocation = async ( - location: NearestPostcodesOptions + location: NearestPostcodesOptions, + i: number ): Promise => { const postcodes = await Postcode.nearestPostcodes(location); let result = null; if (postcodes && postcodes.length > 0) { result = postcodes.map((postcode) => Postcode.toJson(postcode)); } - data.push({ + data[i] = { query: sanitizeQuery(location), result, - }); + }; }; const whitelist = [ @@ -134,13 +135,16 @@ const bulkGeocode: Handler = async (request, response, next) => { }; const queue = chunk( - geolocations.map((geolocation) => { - return lookupGeolocation({ - ...(globalLimit && { limit: globalLimit }), - ...(globalRadius && { radius: globalRadius }), - ...(globalWidesearch && { widesearch: true }), - ...geolocation, - }); + geolocations.map((geolocation, i) => { + return lookupGeolocation( + { + ...(globalLimit && { limit: globalLimit }), + ...(globalRadius && { radius: globalRadius }), + ...(globalWidesearch && { widesearch: true }), + ...geolocation, + }, + i + ); }), GEO_ASYNC_LIMIT ); @@ -170,27 +174,27 @@ const bulkLookupPostcodes: Handler = async (request, response, next) => { if (postcodes.length > MAX_POSTCODES) return next(new ExceedMaxPostcodesError()); - const result: BulkLookupPostcodesResult[] = []; + const p = postcodes.filter((pc) => typeof pc === "string"); - const lookupPostcode = async (postcode: string): Promise => { + const result: BulkLookupPostcodesResult[] = new Array(p.length); + + const lookupPostcode = async ( + postcode: string, + i: number + ): Promise => { const postcodeInfo = await Postcode.find(postcode); if (!postcodeInfo) { - result.push({ query: postcode, result: null }); + result[i] = { query: postcode, result: null }; return; } - result.push({ + result[i] = { query: postcode, result: Postcode.toJson(postcodeInfo), - }); + }; }; const queue: Promise[][] = chunk( - postcodes - .map((p) => { - if (typeof p === "string") return lookupPostcode(p); - return; - }) - .filter((p) => p !== null), + p.map(lookupPostcode).filter((pc) => pc !== null), BULK_ASYNC_LIMIT ); diff --git a/test/postcodes.bulk.integration.ts b/test/postcodes.bulk.integration.ts index 090a8018..09fa48a0 100644 --- a/test/postcodes.bulk.integration.ts +++ b/test/postcodes.bulk.integration.ts @@ -114,6 +114,7 @@ describe("Postcodes routes", () => { done(); }); }); + it("should return 404 if invalid geolocations object", (done) => { request(app) .post("/postcodes") @@ -149,6 +150,7 @@ describe("Postcodes routes", () => { done(); }); }); + it("is sensitive to limit set in query string", (done) => { const testLocation = { longitude: -2.084524, @@ -224,6 +226,34 @@ describe("Postcodes routes", () => { }); }); }); + + it("returns searches in order", async () => { + const geolocations = [ + { + longitude: -2.084524, + latitude: 57.129475, + }, + { + longitude: -2.014524, + latitude: 57.129475, + }, + { + longitude: -2.024524, + latitude: 57.129475, + }, + ]; + const response = await request(app) + .post("/postcodes") + .send({ geolocations }) + .expect(200); + for (let i = 0; i < geolocations.length; i += 1) { + assert.equal( + geolocations[i].longitude, + response.body.result[i].query.longitude + ); + } + }); + it("allows wide area searches", (done) => { const testLocation = { longitude: -2.12659411941741, @@ -330,6 +360,24 @@ describe("Postcodes routes", () => { ); }); + it("returns results in order", async () => { + const postcodes = [ + "YO31 6EG", + "HG3 3EX", + "CH65 6RW", + "CH6Z 6RW", + "N1 1SJ", + "BT36 5NS", + ]; + const response = await request(app) + .post("/postcodes") + .send({ postcodes }) + .expect(200); + for (let i = 0; i < postcodes.length; i += 1) { + assert.equal(response.body.result[i].query, postcodes[i]); + } + }); + it("should return addresses for postcodes", (done) => { request(app) .post("/postcodes")