Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select contact address from postcode lookup results #120

Merged
merged 4 commits into from
Apr 12, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/controllers/contact_address_forms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,11 @@ def new
def create
super(ContactAddressForm, "contact_address_form")
end

def skip_to_manual_address
set_transient_registration(params[:reg_identifier])

@transient_registration.skip_to_manual_address! if form_matches_state?
redirect_to_correct_form
end
end
55 changes: 50 additions & 5 deletions app/forms/contact_address_form.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,62 @@
class ContactAddressForm < BaseForm
# TODO: Define accessible attributes, eg attr_accessor :field
attr_accessor :business_type
attr_accessor :temp_contact_postcode
attr_accessor :temp_addresses
attr_accessor :temp_address
attr_accessor :addresses

def initialize(transient_registration)
super
# TODO: Define params to get from transient_registration, eg self.field = @transient_registration.field
# We only use this for the correct microcopy
self.business_type = @transient_registration.business_type
self.temp_contact_postcode = @transient_registration.temp_contact_postcode

look_up_addresses
preselect_existing_address
end

def submit(params)
# Assign the params for validation and pass them to the BaseForm method for updating
# TODO: Define allowed params, eg self.field = params[:field]
# TODO: Include attributes to update in the attributes hash, eg { field: field }
attributes = {}
self.addresses = add_or_replace_address(params[:temp_address])
attributes = { addresses: addresses }

super(attributes, params[:reg_identifier])
end

validates :addresses, presence: true

private

# Look up addresses based on the temp_contact_postcode
def look_up_addresses
if temp_contact_postcode.present?
address_finder = AddressFinderService.new(temp_contact_postcode)
self.temp_addresses = address_finder.search_by_postcode
else
self.temp_addresses = []
end
end

# If an address has already been assigned to the transient registration, pre-select it
def preselect_existing_address
return unless @transient_registration.addresses.present?
current_address = @transient_registration.contact_address
return unless current_address.uprn.present?
selected_address = temp_addresses.detect { |address| address["uprn"] == current_address.uprn.to_s }
self.temp_address = selected_address["uprn"] if selected_address.present?
end

def add_or_replace_address(selected_address_uprn)
return if selected_address_uprn.blank?

data = temp_addresses.detect { |address| address["uprn"] == selected_address_uprn }
address = Address.create_from_os_places_data(data)
address.assign_attributes(address_type: "CONTACT")

# Update the transient object's nested addresses, replacing any existing registered address
updated_addresses = @transient_registration.addresses
updated_addresses.delete(@transient_registration.contact_address) if @transient_registration.contact_address
updated_addresses << address
updated_addresses
end
end
38 changes: 27 additions & 11 deletions app/views/contact_address_forms/new.html.erb
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
<%= render("shared/back", back_path: back_contact_address_forms_path(@contact_address_form.reg_identifier)) %>

<% if @contact_address_form.errors.any? %>

<h1 class="heading-large"><%= t(".error_heading") %></h1>

<% @contact_address_form.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>

<% else %>

<div class="text">
<%= form_for(@contact_address_form) do |f| %>
<%= render("shared/errors", object: @contact_address_form) %>

<h1 class="heading-large"><%= t(".heading") %></h1>

<div class="form-group">
<label class="form-label"><%= t(".postcode_label") %></label>
<span class="postcode"><%= @contact_address_form.temp_contact_postcode %></span>
<%= link_to(t(".postcode_change_link"), back_contact_address_forms_path(@contact_address_form.reg_identifier)) %>
</div>

<% if @contact_address_form.errors[:addresses].any? %>
<div class="form-group form-group-error">
<% else %>
<div class="form-group">
<% end %>
<fieldset id="addresses">
<%= f.label :temp_address, t(".address_label"), class: "form-label" %>
<%= f.select(:temp_address,
options_for_select(@contact_address_form.temp_addresses.map { |a| [a["partial"], a["uprn"]] }, @contact_address_form.temp_address),
{ include_blank: t(".address_blank_option", count: @contact_address_form.temp_addresses.length ) },
{ class: "form-control" }) %>
</fieldset>
</div>

<div class="form-group">
<%= link_to(t(".manual_address_link"), skip_to_manual_address_contact_address_forms_path(@contact_address_form.reg_identifier)) %>
</div>

<%= f.hidden_field :reg_identifier, value: @contact_address_form.reg_identifier %>
<div class="form-group">
<%= f.submit t(".next_button"), class: "button" %>
</div>
<% end %>

<% end %>
<%= render("shared/os_terms_footer") %>
</div>
10 changes: 10 additions & 0 deletions config/locales/forms/contact_address_forms/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ en:
contact_address_forms:
new:
heading: What's the address of the person we should contact?
postcode_label: Postcode
postcode_change_link: Change
address_label: Address
address_blank_option:
zero: No addresses found
one: 1 address found
other: "%{count} addresses found"
manual_address_link: "I can't find the address in the list"
error_heading: Something is wrong
next_button: Continue
activemodel:
errors:
models:
contact_address_form:
attributes:
addresses:
blank: "You must select an address"
reg_identifier:
invalid_format: "The registration ID is not in a valid format"
no_registration: "There is no registration matching this ID"
Expand Down
5 changes: 5 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@
to: "contact_address_forms#go_back",
as: "back",
on: :collection

get "skip_to_manual_address/:reg_identifier",
to: "contact_address_forms#skip_to_manual_address",
as: "skip_to_manual_address",
on: :collection
end

resources :contact_address_manual_forms,
Expand Down
28 changes: 28 additions & 0 deletions spec/factories/forms/contact_address_form.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
FactoryBot.define do
factory :contact_address_form do
trait :has_required_data do
temp_address "340116"
temp_addresses [{
"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" => ""
}]

addresses { [build(:address, :has_required_data, :contact)] }

initialize_with { new(create(:transient_registration, :has_required_data, workflow_state: "contact_address_form")) }
end
end
Expand Down
67 changes: 50 additions & 17 deletions spec/forms/contact_address_forms_spec.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
require "rails_helper"

RSpec.describe ContactAddressForm, type: :model do
# Stub the address search so we have JSON to use
before do
address_json = build(:contact_address_form, :has_required_data).temp_addresses
allow_any_instance_of(AddressFinderService).to receive(:search_by_postcode).and_return(address_json)
end

describe "#submit" do
context "when the form is valid" do
let(:contact_address_form) { build(:contact_address_form, :has_required_data) }
let(:valid_params) { { reg_identifier: contact_address_form.reg_identifier } }
let(:valid_params) { { reg_identifier: contact_address_form.reg_identifier, temp_address: contact_address_form.temp_address } }

it "should submit" do
expect(contact_address_form.submit(valid_params)).to eq(true)
VCR.use_cassette("contact_postcode_form_valid_postcode") do
expect(contact_address_form.submit(valid_params)).to eq(true)
end
end
end

Expand All @@ -16,28 +24,22 @@
let(:invalid_params) { { reg_identifier: "foo" } }

it "should not submit" do
expect(contact_address_form.submit(invalid_params)).to eq(false)
VCR.use_cassette("contact_postcode_form_valid_postcode") do
expect(contact_address_form.submit(invalid_params)).to eq(false)
end
end
end
end

describe "#reg_identifier" do
context "when a valid transient registration exists" do
let(:transient_registration) do
create(:transient_registration,
:has_required_data,
workflow_state: "contact_address_form")
end
# Don't use FactoryBot for this as we need to make sure it initializes with a specific object
let(:contact_address_form) { ContactAddressForm.new(transient_registration) }
context "when a form with a valid transient registration exists" do
let(:contact_address_form) { build(:contact_address_form, :has_required_data) }

describe "#reg_identifier" do
context "when a reg_identifier meets the requirements" do
before(:each) do
contact_address_form.reg_identifier = transient_registration.reg_identifier
end

it "is valid" do
expect(contact_address_form).to be_valid
VCR.use_cassette("contact_postcode_form_valid_postcode") do
expect(contact_address_form).to be_valid
end
end
end

Expand All @@ -46,13 +48,44 @@
contact_address_form.reg_identifier = ""
end

it "is not valid" do
VCR.use_cassette("contact_postcode_form_valid_postcode") do
expect(contact_address_form).to_not be_valid
end
end
end
end

describe "#addresses" do
context "when no address is selected" do
before(:each) do
contact_address_form.addresses = nil
end

it "is not valid" do
expect(contact_address_form).to_not be_valid
end
end
end
end

context "when a form with a valid transient registration exists and the transient registration already has an address" do
let(:transient_registration) do
build(:transient_registration,
:has_postcode,
:has_addresses,
workflow_state: "contact_address_form")
end
# Don't use FactoryBot for this as we need to make sure it initializes with a specific object
let(:contact_address_form) { ContactAddressForm.new(transient_registration) }

describe "#temp_address" do
it "pre-selects the address" do
expect(contact_address_form.temp_address).to eq(transient_registration.addresses.where(address_type: "CONTACT").first.uprn.to_s)
end
end
end

describe "#transient_registration" do
context "when the transient registration is invalid" do
let(:transient_registration) do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
it "changes to :check_your_answers_form after the 'next' event" do
expect(transient_registration).to transition_from(:contact_address_form).to(:check_your_answers_form).on_event(:next)
end

it "changes to :contact_address_manual_form after the 'skip_to_manual_address' event" do
expect(transient_registration).to transition_from(:contact_address_form).to(:contact_address_manual_form).on_event(:skip_to_manual_address)
end
end
end
end
Loading