Skip to content

Commit 76aff0c

Browse files
committed
feat(USA): Resolve addreses in US format
1 parent 84e2c83 commit 76aff0c

File tree

3 files changed

+152
-4
lines changed

3 files changed

+152
-4
lines changed

lib/resources/autocomplete.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { listMethod, retrieveMethod } from "./resource";
2-
import { AddressSuggestionResponse, GbrResolveResponse } from "../types";
2+
import {
3+
AddressSuggestionResponse,
4+
GbrResolveResponse,
5+
UsaResolveResponse,
6+
} from "../types";
37
import { OptionalStringMap } from "../util";
48
import { Client } from "../client";
59
import { HttpResponse } from "../agent";
@@ -73,6 +77,22 @@ export interface Gbr {
7377
(client: Client, id: string, request: Request): Promise<GbrResponse>;
7478
}
7579

80+
// Resolves address to the GBR format
81+
export const usa: Usa = (client, id, request) =>
82+
retrieveMethod<Request, UsaResolveResponse>({
83+
resource,
84+
client,
85+
action: "usa",
86+
})(id, request);
87+
88+
export interface UsaResponse extends HttpResponse {
89+
body: UsaResolveResponse;
90+
}
91+
92+
export interface Usa {
93+
(client: Client, id: string, request: Request): Promise<UsaResponse>;
94+
}
95+
7696
// Resolves address to the GBR format
7797
export const gbr: Gbr = (client, id, request) =>
7898
retrieveMethod<Request, GbrResolveResponse>({

lib/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ export type AddressResponse =
1010
export type AddressSuggestionResponse =
1111
paths["/autocomplete/addresses"]["get"]["responses"][200]["content"]["application/json"];
1212

13+
export type UsaResolveResponse =
14+
paths["/autocomplete/addresses/{address}/usa"]["get"]["responses"][200]["content"]["application/json"];
15+
1316
export type GbrResolveResponse =
1417
paths["/autocomplete/addresses/{address}/gbr"]["get"]["responses"][200]["content"]["application/json"];
1518

test/autocomplete.resource.ts

Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as sinon from "sinon";
22
import { IdpcRequestFailedError, IdpcBalanceDepletedError } from "../lib/error";
33
import { errors, autocomplete } from "@ideal-postcodes/api-fixtures";
4-
import { list, gbr } from "../lib/resources/autocomplete";
4+
import { list, gbr, usa } from "../lib/resources/autocomplete";
55
import { HttpVerb } from "../lib/agent";
66
import { Client, defaults } from "../lib/index";
77
import { assert } from "chai";
@@ -76,10 +76,10 @@ describe("AutocompleteResource: List", () => {
7676
});
7777
});
7878

79-
describe("AutocompleteResource: Resolve", () => {
79+
describe("AutocompleteResource: Resolve GBR", () => {
8080
const fixture = {
8181
description: "UDPRN address retrieval",
82-
url: "/v1/udprn/23747208",
82+
url: "/v1/autocomplete/addresses/paf_23747208/gbr",
8383
query: {
8484
api_key: "<VALID_API_KEY>",
8585
},
@@ -198,3 +198,128 @@ describe("AutocompleteResource: Resolve", () => {
198198
});
199199
});
200200
});
201+
202+
describe("AutocompleteResource: Resolve USA", () => {
203+
const fixture = {
204+
description: "USA address retrieval",
205+
url: "/v1/autocomplete/addresses/usps_Y115641805%7C10%7C%7C7254/usa",
206+
query: {
207+
api_key: "<VALID_API_KEY>",
208+
},
209+
headers: {},
210+
httpStatus: 200,
211+
body: {
212+
result: {
213+
primary_number: "10",
214+
secondary_number: "",
215+
plus_4_code: "7254",
216+
line_1: "10 A A Dr",
217+
line_2: "",
218+
last_line: "Taylorsville NC 28681-7254",
219+
zip_plus_4_code: "28681-7254",
220+
id: "usps_Y115641805|10||7254",
221+
dataset: "usps",
222+
country_iso: "USA",
223+
country: "United States",
224+
update_key_number: "Y115641805",
225+
zip_code: "28681",
226+
record_type_code: "S",
227+
carrier_route_id: "R008",
228+
street_pre_directional_abbreviation: "",
229+
street_name: "A A",
230+
street_suffix_abbreviation: "Dr",
231+
street_post_directional_abbreviation: "",
232+
building_or_firm_name: "",
233+
base_alternate_code: "B",
234+
lacs_status_indicator: "",
235+
government_building_indicator: "",
236+
state_abbreviation: "NC",
237+
municipality_city_state_key: "",
238+
state: "North Carolina",
239+
urbanization_city_state_key: "",
240+
preferred_last_line_city_state_key: "Y16602",
241+
address_secondary_abbreviation: "",
242+
county: "Alexander",
243+
city: "Taylorsville",
244+
city_abbreviation: "",
245+
preferred_city: "Taylorsville",
246+
city_state_name_facility_code: "P",
247+
zip_classification_code: "",
248+
city_state_mailing_name_indicator: "Y",
249+
carrier_route_rate_sortation: "D",
250+
finance_number: 367712,
251+
congressional_district_number: 5,
252+
county_number: 3,
253+
},
254+
code: 2000,
255+
message: "Success",
256+
},
257+
};
258+
259+
afterEach(() => sinon.restore());
260+
261+
const api_key = "foo";
262+
const id = "paf_123456";
263+
const query = { api_key };
264+
const client = new Client(newConfig());
265+
const expectedRequest = {
266+
method: "GET" as HttpVerb,
267+
header: defaults.header,
268+
query,
269+
timeout: client.config.timeout,
270+
url: `https://api.ideal-postcodes.co.uk/v1/autocomplete/addresses/${id}/usa`,
271+
};
272+
273+
describe("contract", () => {
274+
it("generates API request on agent", (done) => {
275+
const stub = sinon
276+
.stub(client.config.agent, "http")
277+
.resolves(toResponse(fixture, expectedRequest));
278+
279+
usa(client, id, { query }).then(() => {
280+
sinon.assert.calledOnce(stub);
281+
sinon.assert.calledWithExactly(stub, expectedRequest);
282+
done();
283+
});
284+
});
285+
});
286+
287+
it("returns resolved address", (done) => {
288+
sinon
289+
.stub(client.config.agent, "http")
290+
.resolves(toResponse(fixture, expectedRequest));
291+
292+
usa(client, id, { query }).then((response) => {
293+
//@ts-ignore
294+
assert.deepEqual(response.body, fixture.body);
295+
done();
296+
});
297+
});
298+
299+
it("returns non API errors (e.g. connection error)", (done) => {
300+
sinon.stub(client.config.agent, "http").rejects(new Error("timeout!"));
301+
302+
usa(client, id, { query })
303+
.then(() => {
304+
done(new Error("Promise should be rejected"));
305+
})
306+
.catch((error) => {
307+
assert.instanceOf(error, Error);
308+
done();
309+
});
310+
});
311+
312+
it("returns API errors", (done) => {
313+
sinon
314+
.stub(client.config.agent, "http")
315+
.resolves(toResponse(errors.balanceDepleted, expectedRequest));
316+
317+
usa(client, id, { query })
318+
.then(() => done(new Error("Promise should be rejected")))
319+
.catch((error) => {
320+
assert.instanceOf(error, IdpcBalanceDepletedError);
321+
assert.isTrue(error instanceof IdpcRequestFailedError);
322+
done();
323+
});
324+
});
325+
});

0 commit comments

Comments
 (0)