diff --git a/app/models/waste_carriers_engine/address.rb b/app/models/waste_carriers_engine/address.rb index afb21c35d..a1d7f623b 100644 --- a/app/models/waste_carriers_engine/address.rb +++ b/app/models/waste_carriers_engine/address.rb @@ -74,18 +74,33 @@ def self.create_from_os_places_data(data) end def assign_house_number_and_address_lines(data) - lines = data["lines"] + lines = data["lines"].clone + + # buildingNumber and dependentThoroughfare are part of the "lines" logic + # but OS places does not include them in the "lines" array. + # If either or both are present, insert them before the thoroughFareName value. + if data["thoroughfareName"].present? && (insert_position = lines.index(data["thoroughfareName"])) + add_line_at?(lines, insert_position, data["dependentThoroughfare"]) + add_line_at?(lines, insert_position, data["buildingName"]) + end + + lines.reject!(&:blank?) + address_attributes = %i[house_number address_line_1 address_line_2 address_line_3 - address_line_4] - lines.reject!(&:blank?) + address_line_4 + address_line_5] # Assign lines one at a time until we run out of lines to assign write_attribute(address_attributes.shift, lines.shift) until lines.empty? end + def add_line_at?(lines, insert_position, insert_value) + lines.insert(insert_position, insert_value) if insert_value.present? + end + def manually_entered? address_mode == "manual-foreign" || address_mode == "manual-uk" end diff --git a/spec/fixtures/files/os_places_response.json b/spec/fixtures/files/os_places_response.json new file mode 100644 index 000000000..eedec2607 --- /dev/null +++ b/spec/fixtures/files/os_places_response.json @@ -0,0 +1,24 @@ +{ + "moniker": "340116", + "uprn": "340116", + "lines": ["NATURAL ENGLAND", "DEANERY ROAD"], + "town": "BRISTOL", + "postcode": "BS1 5AH", + "easting": "358205", + "northing": "172708", + "country": "", + "dependentLocality": "", + "dependentThroughfare": "", + "administrativeArea": "BRISTOL", + "localAuthorityUpdateDate": "", + "royalMailUpdateDate": "", + "partial": "NATURAL ENGLAND, HORIZON HOUSE, DEANERY ROAD, BRISTOL, BS1 5AH", + "subBuildingName": "", + "buildingName": "HORIZON HOUSE", + "thoroughfareName": "DEANERY ROAD", + "organisationName": "NATURAL ENGLAND", + "buildingNumber": "", + "postOfficeBoxNumber": "", + "departmentName": "", + "doubleDependentLocality": "" + } \ No newline at end of file diff --git a/spec/models/waste_carriers_engine/address_spec.rb b/spec/models/waste_carriers_engine/address_spec.rb index 8fa830d1e..59876456c 100644 --- a/spec/models/waste_carriers_engine/address_spec.rb +++ b/spec/models/waste_carriers_engine/address_spec.rb @@ -4,7 +4,7 @@ module WasteCarriersEngine RSpec.describe Address, type: :model do - describe "assign_house_number_and_address_lines" do + describe "#assign_house_number_and_address_lines" do let(:address) { build(:address) } context "when it is given address data" do @@ -56,5 +56,169 @@ module WasteCarriersEngine end end end + + describe ".create_from_os_places_data" do + let(:os_places_data) { JSON.parse(file_fixture("os_places_response.json").read) } + let(:os_lines) { os_places_data["lines"] } + subject { described_class.create_from_os_places_data(os_places_data) } + + RSpec.shared_examples "address fields" do + it "includes the expected fields" do + %i[uprn address_mode administrative_area administrative_area easting northing + house_number address_line_1 town_city postcode].each do |field| + expect(subject[field]).to be_present + end + end + + it "populates house number and address fields correctly" do + # use 'expect(x==y).to be_truthy' instead of 'expect(x).to eq(y)' to allow for nil values. + expect(subject[:house_number] == expected_house_address_lines[0]).to be_truthy + expect(subject[:address_line_1] == expected_house_address_lines[1]).to be_truthy + expect(subject[:address_line_2] == expected_house_address_lines[2]).to be_truthy + expect(subject[:address_line_3] == expected_house_address_lines[3]).to be_truthy + expect(subject[:address_line_4] == expected_house_address_lines[4]).to be_truthy + expect(subject[:address_line_5] == expected_house_address_lines[5]).to be_truthy + end + end + + context "with no dependent thoroughfare or building name" do + before do + os_places_data["dependentThoroughfare"] = "" + os_places_data["buildingName"] = "" + end + + context "with few address lines returned by OS places" do + let(:expected_house_address_lines) { [os_lines[0..1], [nil] * 4].flatten } + + it_behaves_like "address fields" + end + + context "with all address lines returned by OS places" do + before do + os_places_data["lines"] << Faker::Address.street_name while os_places_data["lines"].length < 6 + end + let(:expected_house_address_lines) { os_lines[0..5] } + + it_behaves_like "address fields" + end + end + + context "with a dependent thoroughfare and no building name" do + let(:dependent_thoroughfare) { Faker::Address.street_name } + before do + os_places_data["dependentThoroughfare"] = dependent_thoroughfare + os_places_data["buildingName"] = "" + end + + context "with few address lines returned by OS places" do + let(:expected_house_address_lines) do + [ + os_lines[0], + dependent_thoroughfare, + os_places_data["thoroughfareName"], + [nil] * 3 + ].flatten + end + + it_behaves_like "address fields" + end + + context "with all address lines returned by OS places" do + before do + os_places_data["lines"] << Faker::Address.street_name while os_places_data["lines"].length < 6 + end + + let(:expected_house_address_lines) do + [ + os_lines[0], + dependent_thoroughfare, + os_places_data["thoroughfareName"], + [os_lines[2..4]] + ].flatten + end + + it_behaves_like "address fields" + end + end + + context "with a building name and no dependent thoroughfare" do + let(:building_name) { Faker::Address.secondary_address } + before do + os_places_data["dependentThoroughfare"] = "" + os_places_data["buildingName"] = building_name + end + + context "with few address lines returned by OS places" do + let(:expected_house_address_lines) do + [ + os_lines[0], + building_name, + os_places_data["thoroughfareName"], + [nil] * 3 + ].flatten + end + + it_behaves_like "address fields" + end + + context "with all address lines returned by OS places" do + before do + os_places_data["lines"] << Faker::Address.street_name while os_places_data["lines"].length < 6 + end + + let(:expected_house_address_lines) do + [ + os_lines[0], + building_name, + os_places_data["thoroughfareName"], + [os_lines[2..4]] + ].flatten + end + + it_behaves_like "address fields" + end + end + + context "with a dependent thoroughfare and a building name" do + let(:dependent_thoroughfare) { Faker::Address.street_name } + let(:building_name) { Faker::Address.secondary_address } + before do + os_places_data["dependentThoroughfare"] = dependent_thoroughfare + os_places_data["buildingName"] = building_name + end + + context "with few address lines returned by OS places" do + let(:expected_house_address_lines) do + [ + os_lines[0], + building_name, + dependent_thoroughfare, + os_places_data["thoroughfareName"], + [nil] * 2 + ].flatten + end + + it_behaves_like "address fields" + end + + context "with all address lines returned by OS places" do + before do + os_places_data["lines"] << Faker::Address.street_name while os_places_data["lines"].length < 6 + end + + let(:expected_house_address_lines) do + [ + os_lines[0], + building_name, + dependent_thoroughfare, + os_places_data["thoroughfareName"], + [os_lines[2..3]] + ].flatten + end + + it_behaves_like "address fields" + end + end + end end end diff --git a/spec/support/address_finder_service_stub_helper.rb b/spec/support/address_finder_service_stub_helper.rb index 2a993451a..4e070eaa8 100644 --- a/spec/support/address_finder_service_stub_helper.rb +++ b/spec/support/address_finder_service_stub_helper.rb @@ -1,38 +1,14 @@ # frozen_string_literal: true module AddressFinderServiceStubHelper - # rubocop:disable Metrics/MethodLength def stub_address_finder_service(options = {}) - address_json = [{ - "moniker" => "340116", - "uprn" => "340116", - "lines" => ["NATURAL ENGLAND", "DEANERY ROAD"], - "town" => "BRISTOL", - "postcode" => "BS1 5AH", - "easting" => "358205", - "northing" => "172708", - "country" => "", - "dependentLocality" => "", - "dependentThroughfare" => "", - "administrativeArea" => "BRISTOL", - "localAuthorityUpdateDate" => "", - "royalMailUpdateDate" => "", - "partial" => "NATURAL ENGLAND, HORIZON HOUSE, DEANERY ROAD, BRISTOL, BS1 5AH", - "subBuildingName" => "", - "buildingName" => "HORIZON HOUSE", - "thoroughfareName" => "DEANERY ROAD", - "organisationName" => "NATURAL ENGLAND", - "buildingNumber" => "", - "postOfficeBoxNumber" => "", - "departmentName" => "", - "doubleDependentLocality" => "" - }.merge(options.stringify_keys)] + os_places_result = JSON.parse(file_fixture("os_places_response.json").read) + address_json = [os_places_result.merge(options.stringify_keys)] response = double(:response, results: address_json, successful?: true) allow(DefraRuby::Address::OsPlacesAddressLookupService).to receive(:run).and_return(response) end - # rubocop:enable Metrics/MethodLength end RSpec.configure do |config|