From ce78a204a78cbd695cc46de53fb6ca7177630c11 Mon Sep 17 00:00:00 2001 From: Jack S Date: Wed, 15 Mar 2023 11:05:38 +0000 Subject: [PATCH] Add UPRN Client --- app/services/uprn_client.rb | 50 +++++++++++++++++++++++ spec/services/uprn_client_spec.rb | 68 +++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 app/services/uprn_client.rb create mode 100644 spec/services/uprn_client_spec.rb diff --git a/app/services/uprn_client.rb b/app/services/uprn_client.rb new file mode 100644 index 000000000..2e57a6072 --- /dev/null +++ b/app/services/uprn_client.rb @@ -0,0 +1,50 @@ +require "net/http" + +class UprnClient + attr_reader :uprn + attr_accessor :error + + ADDRESS = "api.os.uk".freeze + PATH = "/search/places/v1/uprn".freeze + + def initialize(uprn) + @uprn = uprn + end + + def call + unless response.is_a?(Net::HTTPSuccess) && result.present? + @error = "UPRN is not recognised. Check the number, or enter the address" + end + rescue JSON::ParserError + @error = "UPRN is not recognised. Check the number, or enter the address" + end + + def result + @result ||= JSON.parse(response.body).dig("results", 0, "DPA") + end + +private + + def http_client + client = Net::HTTP.new(ADDRESS, 443) + client.use_ssl = true + client.verify_mode = OpenSSL::SSL::VERIFY_PEER + client.max_retries = 3 + client.read_timeout = 10 # seconds + client + end + + def endpoint_uri + uri = URI(PATH) + params = { + uprn:, + key: ENV["OS_DATA_KEY"], + } + uri.query = URI.encode_www_form(params) + uri.to_s + end + + def response + @response ||= http_client.request_get(endpoint_uri) + end +end diff --git a/spec/services/uprn_client_spec.rb b/spec/services/uprn_client_spec.rb new file mode 100644 index 000000000..b595b7e76 --- /dev/null +++ b/spec/services/uprn_client_spec.rb @@ -0,0 +1,68 @@ +require "rails_helper" + +describe UprnClient do + let(:client) { described_class.new("123") } + + let(:valid_response) do + { results: [{ DPA: { postcode: "12345" } }] }.to_json + end + + def stub_api_request(body:, status: 200) + stub_request(:get, "https://api.os.uk/search/places/v1/uprn?key=OS_DATA_KEY&uprn=123") + .to_return(status:, body:, headers: {}) + end + + describe "call" do + context "when json parse error" do + before do + stub_api_request(body: "{", status: 200) + + client.call + end + + it "returns error" do + expect(client.error).to eq("UPRN is not recognised. Check the number, or enter the address") + end + end + + context "when http error" do + before do + stub_api_request(body: valid_response, status: 500) + + client.call + end + + it "returns error" do + expect(client.error).to eq("UPRN is not recognised. Check the number, or enter the address") + end + end + + context "when results empty" do + before do + stub_api_request(body: {}.to_json) + + client.call + end + + it "returns error" do + expect(client.error).to eq("UPRN is not recognised. Check the number, or enter the address") + end + end + + context "with results" do + before do + stub_api_request(body: valid_response) + + client.call + end + + it "returns result" do + expect(client.result).to eq({ "postcode" => "12345" }) + end + + it "returns no error" do + expect(client.error).to be_nil + end + end + end +end