From 02c41333f61f8d06022011365cdb94815ad7b453 Mon Sep 17 00:00:00 2001 From: natdeanlewissoftwire <94526761+natdeanlewissoftwire@users.noreply.github.com> Date: Thu, 5 Jan 2023 16:28:03 +0000 Subject: [PATCH] Cldc 1669 add location redesign (#1034) * feat: wip postcode page * feat: wip add new flow * feat: add check answers page, continue updating flow * feat: add back behaviour * feat: more flow work * feat: further flow work and flash notice, name tidying * feat: add check_answers referrer linking * feat: add controller and details linking and lint * refactor: erblinting * feat: add local_authority page (currenlty separate from edit_local_authority to avoid conflict with add location to newly created scheme path, to be fixed later). also copy and routing updates * feat: add validations to controller (could later be added to model) * fix: correct date order * feat: validate on model (except startdate) * feat: copy update * refactor: railsification * feat: add date model validation * feat: add updated availability text in check_answers * feat: more updated dynamic text and linking * refactor: erblinting * refactor: cleanup of redundant code * refactor: remove redundant create * feat: use rails route * test: wip tests * test: wip tests * feat: add new back behaviour for new scheme path and tests wip * feat: add more back behaviour for new scheme path and fix local auth validation * feat: further linking behaviour with routes and referrers, don't add new location automatically to new schemes * feat: if location with no details added, route to normal path rather than check answers * test: update model and helper location tests * test: more test updates * test: more test updates and remove redundant files * test: remove redundant tests, add postcode test * test: add new #new tests * test: add test for all new controller methods * test: add more startdate tests * refactor: erblinting * test: fix failing tests * test: update scheme test * feat: respond to PR comments * feat: make postcode clear only if changed * feat: add _update methods * refactor: simplify validation and location_edit_path method * refactor: add helper method for action text * refactor: remove redundant logic * refactor: simplify routing * refactor: reintroduce location_params * refactor: use presence validation for postcode * refactor: use presence validation for la * feat: validate confirmed * tests: make tests pass with new startdate validation * WIP * refactor: simplify display attributes helpers and update tests * refactor: linting * feat: design change to save behaviour * test: fix failing tests * feat: location code copy tweak * refactor: remove redundant function * refactor: remove add_another_location and new location page * feat: simplify startdate validations to move to model, use scheme available_from date for in range validation * test: fix failing tests * refactor: linting * feat: remove name validation as a result of PO review * test: update tests * refactor: remove redundant context Co-authored-by: James Rose --- app/controllers/locations_controller.rb | 231 +-- app/controllers/schemes_controller.rb | 2 +- app/helpers/check_answers_helper.rb | 12 - app/helpers/locations_helper.rb | 38 +- app/helpers/tab_nav_helper.rb | 13 +- app/models/location.rb | 40 +- app/views/locations/availability.erb | 33 + app/views/locations/check_answers.html.erb | 34 + app/views/locations/edit.html.erb | 56 - .../locations/edit_local_authority.html.erb | 31 - app/views/locations/edit_name.html.erb | 26 - app/views/locations/index.html.erb | 18 +- app/views/locations/local_authority.html.erb | 40 + .../locations/mobility_standards.html.erb | 35 + app/views/locations/name.html.erb | 42 + app/views/locations/new.html.erb | 61 - app/views/locations/postcode.html.erb | 37 + app/views/locations/show.html.erb | 4 +- app/views/locations/type_of_unit.html.erb | 34 + app/views/locations/units.html.erb | 34 + app/views/schemes/check_answers.html.erb | 47 - config/locales/en.yml | 23 +- config/routes.rb | 19 +- spec/factories/location.rb | 2 +- spec/features/schemes_helpers.rb | 39 +- spec/features/schemes_spec.rb | 159 +- spec/helpers/locations_helper_spec.rb | 24 +- spec/models/location_spec.rb | 56 +- .../validations/date_validations_spec.rb | 6 +- .../validations/setup_validations_spec.rb | 8 +- spec/requests/locations_controller_spec.rb | 1462 +++++++++-------- spec/requests/schemes_controller_spec.rb | 10 +- 32 files changed, 1495 insertions(+), 1181 deletions(-) create mode 100644 app/views/locations/availability.erb create mode 100644 app/views/locations/check_answers.html.erb delete mode 100644 app/views/locations/edit.html.erb delete mode 100644 app/views/locations/edit_local_authority.html.erb delete mode 100644 app/views/locations/edit_name.html.erb create mode 100644 app/views/locations/local_authority.html.erb create mode 100644 app/views/locations/mobility_standards.html.erb create mode 100644 app/views/locations/name.html.erb delete mode 100644 app/views/locations/new.html.erb create mode 100644 app/views/locations/postcode.html.erb create mode 100644 app/views/locations/type_of_unit.html.erb create mode 100644 app/views/locations/units.html.erb diff --git a/app/controllers/locations_controller.rb b/app/controllers/locations_controller.rb index 4677488f1..f01193f4c 100644 --- a/app/controllers/locations_controller.rb +++ b/app/controllers/locations_controller.rb @@ -2,9 +2,10 @@ class LocationsController < ApplicationController include Pagy::Backend before_action :authenticate_user! before_action :authenticate_scope! - before_action :find_location, except: %i[new create index] + before_action :find_location, except: %i[create index] before_action :find_scheme before_action :authenticate_action! + before_action :scheme_and_location_present, except: %i[create index] include Modules::SearchFilter @@ -14,8 +15,127 @@ class LocationsController < ApplicationController @searched = search_term.presence end - def new - @location = Location.new + def create + @location = @scheme.locations.create! + redirect_to scheme_location_postcode_path(@scheme, @location, route: params[:route]) + end + + def postcode; end + + def update_postcode + @location.postcode = location_params[:postcode] + if @location.save(context: :postcode) + if @location.location_code.blank? || @location.location_admin_district.blank? + redirect_to scheme_location_local_authority_path(@scheme, @location, route: params[:route], referrer: params[:referrer]) + elsif return_to_check_your_answers? + redirect_to scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + redirect_to scheme_location_name_path(@scheme, @location, route: params[:route]) + end + else + render :postcode, status: :unprocessable_entity + end + end + + def local_authority; end + + def update_local_authority + @location.location_admin_district = location_params[:location_admin_district] + @location.location_code = Location.local_authorities.key(location_params[:location_admin_district]) + if @location.save(context: :location_admin_district) + if return_to_check_your_answers? || params[:referrer] == "check_local_authority" + redirect_to scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + redirect_to scheme_location_name_path(@scheme, @location, route: params[:route]) + end + else + render :local_authority, status: :unprocessable_entity + end + end + + def name; end + + def update_name + @location.name = location_params[:name] + if @location.save(context: :name) + if return_to_check_your_answers? + redirect_to scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + elsif params[:referrer] == "details" + redirect_to scheme_location_path(@scheme, @location) + else + redirect_to scheme_location_units_path(@scheme, @location, route: params[:route]) + end + else + render :name, status: :unprocessable_entity + end + end + + def units; end + + def update_units + @location.units = location_params[:units] + if @location.save(context: :units) + if return_to_check_your_answers? + redirect_to scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + redirect_to scheme_location_type_of_unit_path(@scheme, @location, route: params[:route]) + end + else + render :units, status: :unprocessable_entity + end + end + + def type_of_unit; end + + def update_type_of_unit + @location.type_of_unit = location_params[:type_of_unit] + if @location.save(context: :type_of_unit) + if return_to_check_your_answers? + redirect_to scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + redirect_to scheme_location_mobility_standards_path(@scheme, @location, route: params[:route]) + end + else + render :type_of_unit, status: :unprocessable_entity + end + end + + def mobility_standards; end + + def update_mobility_standards + @location.mobility_type = location_params[:mobility_type] + if @location.save(context: :mobility_type) + if return_to_check_your_answers? + redirect_to scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + redirect_to scheme_location_availability_path(@scheme, @location, route: params[:route]) + end + else + render :mobility_standards, status: :unprocessable_entity + end + end + + def availability; end + + def update_availability + day = location_params["startdate(3i)"] + month = location_params["startdate(2i)"] + year = location_params["startdate(1i)"] + @location.startdate = if [day, month, year].none?(&:blank?) && Date.valid_date?(year.to_i, month.to_i, day.to_i) + Time.zone.local(year.to_i, month.to_i, day.to_i) + end + if @location.save(context: :startdate) + redirect_to scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + render :availability, status: :unprocessable_entity + end + end + + def check_answers; end + + def confirm + flash[:notice] = "#{@location.postcode} #{@location.startdate.blank? || @location.startdate < Time.zone.now ? 'has been' : 'will be'} added to this scheme" + redirect_to scheme_locations_path(@scheme) end def show; end @@ -82,99 +202,14 @@ class LocationsController < ApplicationController end end - def create - if date_params_missing?(location_params) || valid_date_params?(location_params) - @location = Location.new(location_params) - if @location.save - if @location.location_admin_district.nil? - redirect_to(scheme_location_edit_local_authority_path(scheme_id: @scheme.id, location_id: @location.id, add_another_location: location_params[:add_another_location])) - elsif location_params[:add_another_location] == "Yes" - redirect_to new_scheme_location_path(@scheme) - else - check_answers_path = @scheme.confirmed? ? scheme_check_answers_path(@scheme, anchor: "locations") : scheme_check_answers_path(@scheme) - redirect_to check_answers_path - end - else - render :new, status: :unprocessable_entity - end - else - @location = Location.new(location_params.except("startdate(3i)", "startdate(2i)", "startdate(1i)")) - @location.valid? - @location.errors.add(:startdate) - render :new, status: :unprocessable_entity - end - end - - def edit - render_not_found and return unless @location && @scheme - end - - def edit_name - render_not_found and return unless @location && @scheme - end - - def edit_local_authority - render_not_found and return unless @location && @scheme - end - - def update - render_not_found and return unless @location && @scheme - - page = params[:location][:page] - if page == "edit-local-authority" && !valid_location_admin_district?(location_params) - error_message = I18n.t("validations.location_admin_district") - @location.errors.add :location_admin_district, error_message - render :edit_local_authority, status: :unprocessable_entity - else - if page == "edit-local-authority" - params[:location][:location_code] = Location.local_authorities.key(params[:location][:location_admin_district]) - end - if @location.update(location_params) - case page - when "edit" - if @location.location_admin_district.nil? - redirect_to(scheme_location_edit_local_authority_path(scheme_id: @scheme.id, location_id: @location.id, add_another_location: location_params[:add_another_location])) - elsif location_params[:add_another_location] == "Yes" - redirect_to(new_scheme_location_path(@location.scheme)) - else - redirect_to(scheme_check_answers_path(@scheme, anchor: "locations")) - end - when "edit-name" - if @scheme.locations.count == @scheme.locations.active.count - redirect_to(scheme_location_path(@scheme, @location)) - else - redirect_to(scheme_check_answers_path(@scheme, anchor: "locations")) - end - when "edit-local-authority" - if params[:add_another_location] == "Yes" - redirect_to(new_scheme_location_path(@location.scheme)) - else - redirect_to(scheme_check_answers_path(@scheme, anchor: "locations")) - end - end - else - render :edit, status: :unprocessable_entity - end - end - end - private - def valid_date_params?(location_params) - is_integer?(location_params["startdate(1i)"]) && is_integer?(location_params["startdate(2i)"]) && is_integer?(location_params["startdate(3i)"]) && - Date.valid_date?(location_params["startdate(1i)"].to_i, location_params["startdate(2i)"].to_i, location_params["startdate(3i)"].to_i) - end - - def date_params_missing?(location_params) - location_params["startdate(1i)"].blank? || location_params["startdate(2i)"].blank? || location_params["startdate(3i)"].blank? - end - - def is_integer?(string) - string.sub(/^0+/, "").to_i.to_s == string.sub(/^0+/, "") + def scheme_and_location_present + render_not_found and return unless @location && @scheme end def find_scheme - @scheme = if %w[new create index edit_name].include?(action_name) + @scheme = if %w[create index].include?(action_name) Scheme.find(params[:scheme_id]) else @location&.scheme @@ -190,14 +225,15 @@ private end def authenticate_action! - if %w[new edit update create index edit_name edit_local_authority new_deactivation deactivate_confirm deactivate].include?(action_name) && !((current_user.organisation == @scheme&.owning_organisation) || current_user.support?) + if %w[create update index new_deactivation deactivate_confirm deactivate postcode local_authority name units type_of_unit mobility_standards availability check_answers].include?(action_name) && !((current_user.organisation == @scheme&.owning_organisation) || current_user.support?) render_not_found and return end end def location_params - required_params = params.require(:location).permit(:postcode, :name, :units, :type_of_unit, :add_another_location, :startdate, :mobility_type, :location_admin_district, :location_code).merge(scheme_id: @scheme.id) + required_params = params.require(:location).permit(:postcode, :location_admin_district, :location_code, :name, :units, :type_of_unit, :mobility_type, "startdate(1i)", "startdate(2i)", "startdate(3i)").merge(scheme_id: @scheme.id) required_params[:postcode] = PostcodeService.clean(required_params[:postcode]) if required_params[:postcode] + required_params[:location_admin_district] = nil if required_params[:location_admin_district] == "Select an option" required_params end @@ -205,10 +241,6 @@ private params["search"] end - def valid_location_admin_district?(location_params) - location_params["location_admin_district"] != "Select an option" - end - def deactivate_success_notice case @location.status when :deactivated @@ -249,4 +281,9 @@ private Time.zone.local(year.to_i, month.to_i, day.to_i) if Date.valid_date?(year.to_i, month.to_i, day.to_i) end + + def return_to_check_your_answers? + params[:referrer] == "check_answers" + end + helper_method :return_to_check_your_answers? end diff --git a/app/controllers/schemes_controller.rb b/app/controllers/schemes_controller.rb index bfa7073d6..73fe02f79 100644 --- a/app/controllers/schemes_controller.rb +++ b/app/controllers/schemes_controller.rb @@ -237,7 +237,7 @@ private when "secondary-client-group" scheme_support_path(@scheme) when "support" - new_scheme_location_path(@scheme) + scheme_check_answers_path(@scheme) when "details" if @scheme.arrangement_type_before_type_cast == "D" scheme_primary_client_group_path(@scheme) diff --git a/app/helpers/check_answers_helper.rb b/app/helpers/check_answers_helper.rb index 1d4a1a9aa..709bbacd6 100644 --- a/app/helpers/check_answers_helper.rb +++ b/app/helpers/check_answers_helper.rb @@ -16,18 +16,6 @@ module CheckAnswersHelper !scheme.confirmed? || editable_attributes.include?(attribute_name) end - def get_location_change_link_href_postcode(scheme, location) - if location.confirmed? - scheme_location_path(scheme_id: scheme.id, id: location.id) - else - edit_scheme_location_path(scheme_id: scheme.id, id: location.id) - end - end - - def get_location_change_link_href_location_admin_district(scheme, location) - scheme_location_edit_local_authority_path(scheme_id: scheme.id, location_id: location.id) - end - def any_questions_have_summary_card_number?(subsection, lettings_log) subsection.applicable_questions(lettings_log).map(&:check_answers_card_number).compact.length.positive? end diff --git a/app/helpers/locations_helper.rb b/app/helpers/locations_helper.rb index 5203c0c06..9b8661221 100644 --- a/app/helpers/locations_helper.rb +++ b/app/helpers/locations_helper.rb @@ -25,23 +25,35 @@ module LocationsHelper def display_location_attributes(location) base_attributes = [ - { name: "Postcode", value: location.postcode }, - { name: "Location name", value: location.name, edit: true }, - { name: "Local authority", value: location.location_admin_district }, - { name: "Total number of units at this location", value: location.units }, - { name: "Common type of unit", value: location.type_of_unit }, - { name: "Mobility type", value: location.mobility_type }, - { name: "Location code", value: location.location_code }, - { name: "Availability", value: location_availability(location) }, + { name: "Postcode", value: location.postcode, attribute: "postcode" }, + { name: "Location name", value: location.name, attribute: "name" }, + { name: "Local authority", value: location.location_admin_district, attribute: "local_authority" }, + { name: "Number of units", value: location.units, attribute: "units" }, + { name: "Most common unit", value: location.type_of_unit, attribute: "type_of_unit" }, + { name: "Mobility standards", value: location.mobility_type, attribute: "mobility_standards" }, + { name: "Location code", value: location.location_code, attribute: "location_code" }, + { name: "Availability", value: location_availability(location), attribute: "availability" }, ] if FeatureToggle.location_toggle_enabled? - base_attributes.append({ name: "Status", value: location.status }) + base_attributes.append({ name: "Status", value: location.status, attribute: "status" }) end base_attributes end + def display_location_attributes_for_check_answers(location) + [ + { name: "Postcode", value: location.postcode, attribute: "postcode" }, + { name: "Location name", value: location.name, attribute: "name" }, + { name: "Local authority", value: location.location_admin_district, attribute: "local_authority" }, + { name: "Number of units", value: location.units, attribute: "units" }, + { name: "Most common unit", value: location.type_of_unit, attribute: "type_of_unit" }, + { name: "Mobility standards", value: location.mobility_type, attribute: "mobility_standards" }, + { name: "Availability", value: location&.startdate&.to_formatted_s(:govuk_date), attribute: "availability" }, + ] + end + def location_availability(location) availability = "" location_active_periods(location).each do |period| @@ -53,6 +65,14 @@ module LocationsHelper availability.strip end + def location_edit_path(location, attribute) + send("scheme_location_#{attribute}_path", location.scheme, location, referrer: "check_answers", route: params[:route]) + end + + def action_text_helper(attr, location) + attr[:value].blank? || (attr[:attribute] == "availability" && location.startdate.blank?) ? "Answer" : "Change" + end + def toggle_location_link(location) return govuk_button_link_to "Deactivate this location", scheme_location_new_deactivation_path(location.scheme, location), warning: true if location.active? return govuk_button_link_to "Reactivate this location", scheme_location_new_reactivation_path(location.scheme, location) if location.deactivated? diff --git a/app/helpers/tab_nav_helper.rb b/app/helpers/tab_nav_helper.rb index 1d2cf4063..3c61c9de0 100644 --- a/app/helpers/tab_nav_helper.rb +++ b/app/helpers/tab_nav_helper.rb @@ -7,21 +7,10 @@ module TabNavHelper end def location_cell_postcode(location, link) - link_text = location.postcode + link_text = location.postcode || "Add postcode" [govuk_link_to(link_text, link, method: :patch), "Location #{location.name}"].join("\n") end - def location_cell_location_admin_district(location, link) - la = location.location_admin_district - if location.confirmed? - la - elsif la - govuk_link_to(la, link, method: :patch) - else - govuk_link_to("Select local authority", link, method: :patch) - end - end - def scheme_cell(scheme) link_text = scheme.service_name link = scheme.confirmed? ? scheme : scheme_check_answers_path(scheme) diff --git a/app/models/location.rb b/app/models/location.rb index 850adfb05..36a134f81 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -1,6 +1,13 @@ class Location < ApplicationRecord - validate :validate_postcode - validates :units, :type_of_unit, :mobility_type, presence: true + validates :postcode, on: :postcode, presence: { message: I18n.t("validations.location.postcode_blank") } + validate :validate_postcode, on: :postcode, if: proc { |model| model.postcode.presence } + validates :location_admin_district, on: :location_admin_district, presence: { message: I18n.t("validations.location_admin_district") } + validates :units, on: :units, presence: { message: I18n.t("validations.location.units") } + validates :type_of_unit, on: :type_of_unit, presence: { message: I18n.t("validations.location.type_of_unit") } + validates :mobility_type, on: :mobility_type, presence: { message: I18n.t("validations.location.mobility_standards") } + validates :startdate, on: :startdate, presence: { message: I18n.t("validations.location.startdate_invalid") } + validate :validate_startdate, on: :startdate, if: proc { |model| model.startdate.presence } + validate :validate_confirmed belongs_to :scheme has_many :lettings_logs, class_name: "LettingsLog" has_many :location_deactivation_periods, class_name: "LocationDeactivationPeriod" @@ -11,8 +18,6 @@ class Location < ApplicationRecord auto_strip_attributes :name - attr_accessor :add_another_location - scope :search_by_postcode, ->(postcode) { where("REPLACE(postcode, ' ', '') ILIKE ?", "%#{postcode.delete(' ')}%") } scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") } scope :search_by, ->(param) { search_by_name(param).or(search_by_postcode(param)) } @@ -409,17 +414,34 @@ class Location < ApplicationRecord status == :reactivating_soon end -private - - PIO = PostcodeService.new - def validate_postcode - if postcode.nil? || !postcode&.match(POSTCODE_REGEXP) + if !postcode&.match(POSTCODE_REGEXP) error_message = I18n.t("validations.postcode") errors.add :postcode, error_message + else + self.postcode = PostcodeService.clean(postcode) + if postcode_changed? + self.location_admin_district = nil + self.location_code = nil + end end end + def validate_startdate + unless startdate.between?(scheme.available_from, Time.zone.local(2200, 1, 1)) + error_message = I18n.t("validations.location.startdate_out_of_range", date: scheme.available_from.to_formatted_s(:govuk_date)) + errors.add :startdate, error_message + end + end + + def validate_confirmed + self.confirmed = [postcode, location_admin_district, location_code, units, type_of_unit, mobility_type].all?(&:present?) + end + +private + + PIO = PostcodeService.new + def lookup_postcode! result = PIO.lookup(postcode) if result diff --git a/app/views/locations/availability.erb b/app/views/locations/availability.erb new file mode 100644 index 000000000..279c5110c --- /dev/null +++ b/app/views/locations/availability.erb @@ -0,0 +1,33 @@ +<% content_for :title, "Add a location to this scheme" %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_mobility_standards_path(@scheme, @location, route: params[:route]), + ) %> +<% end %> + +<%= form_for(@location, method: :patch, url: scheme_location_availability_path(@scheme, @location, route: params[:route], referrer: params[:referrer])) do |f| %> +
+
+ <%= f.govuk_error_summary %> + + <%= render partial: "organisations/headings", locals: { main: I18n.t("questions.location.startdate"), sub: "Add a location to #{@scheme.service_name}" } %> + + <%= f.govuk_date_field :startdate, + hint: { text: I18n.t("hints.location.startdate") }, + legend: nil, + width: 20 %> + +
+ <% if params[:referrer] == "check_answers" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_check_answers_path(@scheme, @location, route: params[:route]), secondary: true %> + <% else %> + <%= f.govuk_submit "Save and continue" %> + <%= govuk_link_to "Skip for now", scheme_location_check_answers_path(@scheme, @location), secondary: true %> + <% end %> +
+
+
+<% end %> diff --git a/app/views/locations/check_answers.html.erb b/app/views/locations/check_answers.html.erb new file mode 100644 index 000000000..11272b5a9 --- /dev/null +++ b/app/views/locations/check_answers.html.erb @@ -0,0 +1,34 @@ +<% title = @location.name %> +<% content_for :title, title %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: case params[:route] + when "locations" + scheme_locations_path(@scheme) + else + :back + end, + ) %> +<% end %> + +<%= render partial: "organisations/headings", locals: { main: "Check your answers", sub: "Add a location to #{@scheme.service_name}" } %> + +
+
+ <%= govuk_summary_list do |summary_list| %> + <% display_location_attributes_for_check_answers(@location).each do |attr| %> + <%= summary_list.row do |row| %> + <% row.key { attr[:name] } %> + <% row.value { details_html(attr) } %> + <% row.action(text: action_text_helper(attr, @location), href: location_edit_path(@location, attr[:attribute])) %> + <% end %> + <% end %> + <% end %> +
+
+
+ <%= govuk_button_to "Save and return to locations", scheme_location_confirm_path(@scheme, @location, route: params[:route]), method: :patch %> + <%= govuk_button_link_to "Cancel", scheme_locations_path(@scheme), secondary: true %> +
diff --git a/app/views/locations/edit.html.erb b/app/views/locations/edit.html.erb deleted file mode 100644 index dca0d04fb..000000000 --- a/app/views/locations/edit.html.erb +++ /dev/null @@ -1,56 +0,0 @@ -<% content_for :title, "Add a location to this scheme" %> - -<% content_for :before_content do %> - <%= govuk_back_link( - text: "Back", - href: scheme_check_answers_path(@scheme, anchor: "locations"), - ) %> -<% end %> - -<%= form_for(@location, method: :patch, url: scheme_location_path(scheme_id: @scheme.id, id: @location.id)) do |f| %> -
-
- <%= f.govuk_error_summary %> - - <%= render partial: "organisations/headings", locals: { main: "Add a location to this scheme", sub: @scheme.service_name } %> - - <%= f.govuk_text_field :postcode, - label: { size: "m" }, - hint: { text: I18n.t("hints.location.postcode") }, - width: 5 %> - - <%= f.govuk_text_field :name, - label: { text: I18n.t("questions.location.name"), size: "m" }, - hint: { text: I18n.t("hints.location.name") } %> - - <%= f.govuk_number_field :units, - label: { text: I18n.t("questions.location.units"), size: "m" }, - width: 2, - hint: { text: I18n.t("hints.location.units") }, - autofocus: true %> - - <%= f.govuk_collection_radio_buttons :type_of_unit, - type_of_units_selection, - :id, - :name, - legend: { text: I18n.t("questions.location.type_of_unit"), size: "m" } %> - - <%= f.govuk_collection_radio_buttons :mobility_type, - mobility_type_selection, - :id, - :name, - :description, - legend: { text: I18n.t("questions.location.mobility_type"), size: "m" } %> - - <%= f.govuk_date_field :startdate, - legend: { text: I18n.t("questions.location.startdate"), size: "m" }, - width: 20 %> - - <%= govuk_section_break(visible: true, size: "m") %> - - <%= f.hidden_field :page, value: "edit" %> - - <%= f.govuk_submit "Save and continue" %> -
-
-<% end %> diff --git a/app/views/locations/edit_local_authority.html.erb b/app/views/locations/edit_local_authority.html.erb deleted file mode 100644 index 1e5ab9fbb..000000000 --- a/app/views/locations/edit_local_authority.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -<% content_for :before_content do %> - <%= govuk_back_link( - text: "Back", - href: "/schemes/#{@scheme.id}/locations", - ) %> -<% end %> - -<%= form_for(@location, method: :patch, url: scheme_location_path(scheme_id: @scheme.id, id: @location.id, add_another_location: params[:add_another_location])) do |f| %> -
-
- <%= f.govuk_error_summary %> - - <%= render partial: "organisations/headings", locals: { main: "What is the local authority of #{@location.postcode}?", sub: @scheme.service_name } %> - - <%= f.govuk_collection_select :location_admin_district, - local_authorities_selection, - :name, - :name, - label: { hidden: true }, - "data-controller": %w[conditional-filter accessible-autocomplete] %> - - <%= f.hidden_field :page, value: "edit-local-authority" %> - -
- <%= f.govuk_submit "Save and continue" %> - - <%= govuk_link_to "Skip for now", "/schemes/#{@scheme.id}/check-answers#locations" %> -
-
-
-<% end %> diff --git a/app/views/locations/edit_name.html.erb b/app/views/locations/edit_name.html.erb deleted file mode 100644 index 7e75edf9d..000000000 --- a/app/views/locations/edit_name.html.erb +++ /dev/null @@ -1,26 +0,0 @@ -<% content_for :title, "Location name for #{@location.postcode}" %> - -<% content_for :before_content do %> - <%= govuk_back_link( - text: "Back", - href: scheme_location_path(@scheme, @location), - ) %> -<% end %> - -<%= form_for(@location, method: :patch, url: scheme_location_path(scheme_id: @scheme.id, id: @location.id)) do |f| %> -
-
- <%= f.govuk_error_summary %> - - <%= render partial: "organisations/headings", locals: { main: "Location name for #{@location.postcode}", sub: @scheme.service_name } %> - - <%= f.govuk_text_field :name, - label: { hidden: true }, - hint: { text: "This is how you refer to this location within your organisation" } %> - - <%= f.hidden_field :page, value: "edit-name" %> - - <%= f.govuk_submit "Save and continue" %> -
-
-<% end %> diff --git a/app/views/locations/index.html.erb b/app/views/locations/index.html.erb index 812296be8..5040120d0 100644 --- a/app/views/locations/index.html.erb +++ b/app/views/locations/index.html.erb @@ -50,14 +50,18 @@ <% @locations.each do |location| %> <%= table.body do |body| %> <%= body.row do |row| %> - <% row.cell(text: simple_format(location_cell_postcode(location, scheme_location_path(@scheme, location)), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> + <% row.cell(text: simple_format(location_cell_postcode(location, if location.confirmed + scheme_location_path(@scheme, location) + else + location.postcode.present? ? scheme_location_check_answers_path(@scheme, location, route: "locations") : scheme_location_postcode_path(@scheme, location) + end), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> <% row.cell(text: location.id) %> <% row.cell(text: status_tag(location.status)) %> <% end %> <% end %> <% end %> <% end %> - <%= govuk_button_link_to "Add a location", new_scheme_location_path(@scheme), secondary: true %> + <%= govuk_button_to "Add a location", scheme_locations_path(@scheme), method: "post", secondary: true %> @@ -95,19 +99,23 @@ <%= table.body do |body| %> <%= body.row do |row| %> <% row.cell(text: location.id) %> - <% row.cell(text: simple_format(location_cell_postcode(location, scheme_location_path(@scheme, location)), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> + <% row.cell(text: simple_format(location_cell_postcode(location, if location.confirmed + scheme_location_path(@scheme, location) + else + location.postcode.present? ? scheme_location_check_answers_path(@scheme, location, route: "locations") : scheme_location_postcode_path(@scheme, location) + end), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> <% row.cell(text: location.units) %> <% row.cell do %> <%= simple_format(location.type_of_unit) %> <% end %> <% row.cell(text: location.mobility_type) %> - <% row.cell(text: simple_format(location_cell_location_admin_district(location, scheme_location_edit_local_authority_path(@scheme, location)), wrapper_tag: "div")) %> + <% row.cell(text: location.location_admin_district) %> <% row.cell(text: location.startdate&.to_formatted_s(:govuk_date)) %> <% end %> <% end %> <% end %> <% end %> - <%= govuk_button_link_to "Add a location", new_scheme_location_path(@scheme), secondary: true %> + <%= govuk_button_to "Add a location", scheme_locations_path(@scheme), method: "post", secondary: true %> <% end %> diff --git a/app/views/locations/local_authority.html.erb b/app/views/locations/local_authority.html.erb new file mode 100644 index 000000000..69b36b5be --- /dev/null +++ b/app/views/locations/local_authority.html.erb @@ -0,0 +1,40 @@ +<% content_for :title, "Add a location to this scheme" %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: case params[:referrer] + when "check_local_authority" + scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + scheme_location_postcode_path(@scheme, @location, route: params[:route], referrer: params[:referrer]) + end, + ) %> +<% end %> + +<%= form_for(@location, method: :patch, url: scheme_location_local_authority_path(@scheme, @location, route: params[:route], referrer: params[:referrer])) do |f| %> +
+
+ <%= f.govuk_error_summary %> + + <%= render partial: "organisations/headings", locals: { main: "What is the local authority of #{@location.postcode}?", sub: @scheme.service_name } %> + + <%= f.govuk_collection_select :location_admin_district, + local_authorities_selection, + :name, + :name, + label: { text: "Start typing to search for your local authority" }, + "data-controller": %w[conditional-filter accessible-autocomplete] %> + +
+ <% if params[:referrer] == "check_answers" || params[:referrer] == "check_local_authority" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_check_answers_path(@scheme, @location, route: params[:route]), secondary: true %> + <% else %> + <%= f.govuk_submit "Save and continue" %> + <%= govuk_link_to "Skip for now", scheme_location_name_path(@scheme, @location), secondary: true %> + <% end %> +
+
+
+<% end %> diff --git a/app/views/locations/mobility_standards.html.erb b/app/views/locations/mobility_standards.html.erb new file mode 100644 index 000000000..42bdb4bcf --- /dev/null +++ b/app/views/locations/mobility_standards.html.erb @@ -0,0 +1,35 @@ +<% content_for :title, "Add a location to this scheme" %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_type_of_unit_path(@scheme, @location, route: params[:route]), + ) %> +<% end %> + +<%= form_for(@location, method: :patch, url: scheme_location_mobility_standards_path(@scheme, @location, route: params[:route], referrer: params[:referrer])) do |f| %> +
+
+ <%= f.govuk_error_summary %> + + <%= render partial: "organisations/headings", locals: { main: I18n.t("questions.location.mobility_type"), sub: "Add a location to #{@scheme.service_name}" } %> + + <%= f.govuk_collection_radio_buttons :mobility_type, + mobility_type_selection, + :id, + :name, + :description, + legend: nil %> + +
+ <% if params[:referrer] == "check_answers" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_check_answers_path(@scheme, @location, route: params[:route]), secondary: true %> + <% else %> + <%= f.govuk_submit "Save and continue" %> + <%= govuk_link_to "Skip for now", scheme_location_availability_path(@scheme, @location), secondary: true %> + <% end %> +
+
+
+<% end %> diff --git a/app/views/locations/name.html.erb b/app/views/locations/name.html.erb new file mode 100644 index 000000000..322a1da22 --- /dev/null +++ b/app/views/locations/name.html.erb @@ -0,0 +1,42 @@ +<% content_for :title, "Add a location to this scheme" %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: case params[:referrer] + when "check_answers" + scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + when "details" + scheme_location_path(@scheme, @location) + else + scheme_location_postcode_path(@scheme, @location, route: params[:route]) + end, + ) %> +<% end %> + +<%= form_for(@location, method: :patch, url: scheme_location_name_path(@scheme, @location, route: params[:route], referrer: params[:referrer])) do |f| %> +
+
+ <%= f.govuk_error_summary %> + + <%= render partial: "organisations/headings", locals: { main: I18n.t("questions.location.name"), sub: "Add a location to #{@scheme.service_name}" } %> + + <%= f.govuk_text_field :name, + label: nil, + hint: { text: I18n.t("hints.location.name") } %> + +
+ <% if params[:referrer] == "check_answers" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_check_answers_path(@scheme, @location, route: params[:route]), secondary: true %> + <% elsif params[:referrer] == "details" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_path(@scheme, @location), secondary: true %> + <% else %> + <%= f.govuk_submit "Save and continue" %> + <%= govuk_link_to "Skip for now", scheme_location_units_path(@scheme, @location), secondary: true %> + <% end %> +
+
+
+<% end %> diff --git a/app/views/locations/new.html.erb b/app/views/locations/new.html.erb deleted file mode 100644 index 69f56744b..000000000 --- a/app/views/locations/new.html.erb +++ /dev/null @@ -1,61 +0,0 @@ -<% content_for :title, "Add a location to this scheme" %> - -<% content_for :before_content do %> - <%= govuk_back_link( - text: "Back", - href: "/schemes/#{@scheme.id}/support", - ) %> -<% end %> - -<%= form_for(@location, method: :post, url: scheme_locations_path) do |f| %> -
-
- <%= f.govuk_error_summary %> - - <%= render partial: "organisations/headings", locals: { main: "Add a location to this scheme", sub: @scheme.service_name } %> - - <%= f.govuk_text_field :postcode, - label: { size: "m" }, - hint: { text: I18n.t("hints.location.postcode") }, - width: 5 %> - - <%= f.govuk_text_field :name, - label: { text: I18n.t("questions.location.name"), size: "m" }, - hint: { text: I18n.t("hints.location.name") } %> - - <%= f.govuk_number_field :units, - label: { text: I18n.t("questions.location.units"), size: "m" }, - width: 2, - hint: { text: I18n.t("hints.location.units") }, - autofocus: true %> - - <%= f.govuk_collection_radio_buttons :type_of_unit, - type_of_units_selection, - :id, - :name, - legend: { text: I18n.t("questions.location.type_of_unit"), size: "m" } %> - - <%= f.govuk_collection_radio_buttons :mobility_type, - mobility_type_selection, - :id, - :name, - :description, - legend: { text: I18n.t("questions.location.mobility_type"), size: "m" } %> - - <%= f.govuk_date_field :startdate, - legend: { text: I18n.t("questions.location.startdate"), size: "m" }, - width: 20 %> - - <%= govuk_section_break(visible: true, size: "m") %> - - <%= f.govuk_collection_radio_buttons :add_another_location, - another_location_selection, - :id, - :name, - inline: true, - legend: { text: I18n.t("questions.location.add_another_location"), size: "m" } %> - - <%= f.govuk_submit "Save and continue" %> -
-
-<% end %> diff --git a/app/views/locations/postcode.html.erb b/app/views/locations/postcode.html.erb new file mode 100644 index 000000000..5ede463ad --- /dev/null +++ b/app/views/locations/postcode.html.erb @@ -0,0 +1,37 @@ +<% content_for :title, "Add a location to this scheme" %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: if params[:referrer] == "check_answers" + scheme_location_check_answers_path(@scheme, @location, route: params[:route]) + else + scheme_locations_path(@scheme) + end, + ) %> +<% end %> + +<%= form_for(@location, method: :patch, url: scheme_location_postcode_path(@scheme, @location, route: params[:route], referrer: params[:referrer])) do |f| %> +
+
+ <%= f.govuk_error_summary %> + + <%= render partial: "organisations/headings", locals: { main: I18n.t("questions.location.postcode"), sub: "Add a location to #{@scheme.service_name}" } %> + + <%= f.govuk_text_field :postcode, + label: nil, + hint: { text: I18n.t("hints.location.postcode") }, + width: 5 %> + +
+ <% if params[:referrer] == "check_answers" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_check_answers_path(@scheme, @location, route: params[:route]), secondary: true %> + <% else %> + <%= f.govuk_submit "Save and continue" %> + <%= govuk_link_to "Skip for now", scheme_location_name_path(@scheme, @location), secondary: true %> + <% end %> +
+
+
+<% end %> diff --git a/app/views/locations/show.html.erb b/app/views/locations/show.html.erb index 59ece6529..79876e5b8 100644 --- a/app/views/locations/show.html.erb +++ b/app/views/locations/show.html.erb @@ -16,8 +16,8 @@ <% display_location_attributes(@location).each do |attr| %> <%= summary_list.row do |row| %> <% row.key { attr[:name] } %> - <% row.value { attr[:name].eql?("Status") ? status_tag(attr[:value]) : details_html(attr) } %> - <% row.action(text: "Change", href: scheme_location_edit_name_path(scheme_id: @scheme.id, location_id: @location.id)) if attr[:edit] %> + <% row.value { attr[:attribute].eql?("status") ? status_tag(attr[:value]) : details_html(attr) } %> + <% row.action(text: "Change", href: scheme_location_name_path(@scheme, @location, referrer: "details")) if attr[:attribute] == "name" %> <% end %> <% end %> <% end %> diff --git a/app/views/locations/type_of_unit.html.erb b/app/views/locations/type_of_unit.html.erb new file mode 100644 index 000000000..5ff4ed3f1 --- /dev/null +++ b/app/views/locations/type_of_unit.html.erb @@ -0,0 +1,34 @@ +<% content_for :title, "Add a location to this scheme" %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_units_path(@scheme, @location, route: params[:route]), + ) %> +<% end %> + +<%= form_for(@location, method: :patch, url: scheme_location_type_of_unit_path(@scheme, @location, route: params[:route], referrer: params[:referrer])) do |f| %> +
+
+ <%= f.govuk_error_summary %> + + <%= render partial: "organisations/headings", locals: { main: I18n.t("questions.location.type_of_unit"), sub: "Add a location to #{@scheme.service_name}" } %> + + <%= f.govuk_collection_radio_buttons :type_of_unit, + type_of_units_selection, + :id, + :name, + legend: nil %> + +
+ <% if params[:referrer] == "check_answers" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_check_answers_path(@scheme, @location, route: params[:route]), secondary: true %> + <% else %> + <%= f.govuk_submit "Save and continue" %> + <%= govuk_link_to "Skip for now", scheme_location_mobility_standards_path(@scheme, @location), secondary: true %> + <% end %> +
+
+
+<% end %> diff --git a/app/views/locations/units.html.erb b/app/views/locations/units.html.erb new file mode 100644 index 000000000..30a9b3eff --- /dev/null +++ b/app/views/locations/units.html.erb @@ -0,0 +1,34 @@ +<% content_for :title, "Add a location to this scheme" %> + +<% content_for :before_content do %> + <%= govuk_back_link( + text: "Back", + href: params[:referrer] == "check_answers" ? scheme_location_check_answers_path(@scheme, @location, route: params[:route]) : scheme_location_name_path(@scheme, @location, route: params[:route]), + ) %> +<% end %> + +<%= form_for(@location, method: :patch, url: scheme_location_units_path(@scheme, @location, route: params[:route], referrer: params[:referrer])) do |f| %> +
+
+ <%= f.govuk_error_summary %> + + <%= render partial: "organisations/headings", locals: { main: I18n.t("questions.location.units"), sub: "Add a location to #{@scheme.service_name}" } %> + + <%= f.govuk_number_field :units, + label: nil, + width: 2, + hint: { text: I18n.t("hints.location.units") }, + autofocus: true %> + +
+ <% if params[:referrer] == "check_answers" %> + <%= f.govuk_submit "Save changes" %> + <%= govuk_link_to "Cancel", scheme_location_check_answers_path(@scheme, @location, route: params[:route]), secondary: true %> + <% else %> + <%= f.govuk_submit "Save and continue" %> + <%= govuk_link_to "Skip for now", scheme_location_type_of_unit_path(@scheme, @location), secondary: true %> + <% end %> +
+
+
+<% end %> diff --git a/app/views/schemes/check_answers.html.erb b/app/views/schemes/check_answers.html.erb index 9f87ec566..806b8838a 100644 --- a/app/views/schemes/check_answers.html.erb +++ b/app/views/schemes/check_answers.html.erb @@ -33,53 +33,6 @@ <% end %> <% end %> - <% component.tab(label: "Locations") do %> -

Locations

- <%= govuk_table do |table| %> - <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %> - <%= @scheme.locations.count %> <%= @scheme.locations.count.eql?(1) ? "location" : "locations" %> - <% end %> - <%= table.head do |head| %> - <%= head.row do |row| %> - <% row.cell(header: true, text: "Code", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Postcode", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Units", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Common unit type", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Mobility type", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Local authority", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Available from", html_attributes: { - scope: "col", - }) %> - <% end %> - <% end %> - <% @scheme.locations.each do |location| %> - <%= table.body do |body| %> - <%= body.row do |row| %> - <% row.cell(text: location.id) %> - <% row.cell(text: simple_format(location_cell_postcode(location, get_location_change_link_href_postcode(@scheme, location)), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> - <% row.cell(text: location.units) %> - <% row.cell(text: simple_format("#{location.type_of_unit}")) %> - <% row.cell(text: location.mobility_type) %> - <% row.cell(text: simple_format(location_cell_location_admin_district(location, get_location_change_link_href_location_admin_district(@scheme, location)), wrapper_tag: "div")) %> - <% row.cell(text: location_availability(location)) %> - <% end %> - <% end %> - <% end %> - <% end %> - <%= govuk_button_link_to "Add a location", new_scheme_location_path(scheme_id: @scheme.id), secondary: true %> - <% end %> <% end %> <%= f.hidden_field :page, value: "check-answers" %> <%= f.hidden_field :confirmed, value: "true" %> diff --git a/config/locales/en.yml b/config/locales/en.yml index b42791ae8..611c64d23 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -372,6 +372,12 @@ en: location: + postcode_blank: "Enter a postcode" + units: "The units at this location must be a number" + type_of_unit: "Select the most common type of unit at this location" + mobility_standards: "Select the mobility standard for the majority of the units at this location" + startdate_invalid: "Enter a valid day, month and year when the first property became available at this location" + startdate_out_of_range: "Availability date must be on or after the %{date}" toggle_date: not_selected: "Select one of the options" invalid: "Enter a valid day, month and year" @@ -425,11 +431,11 @@ en: questions: location: - name: "Location name (optional)" - units: "Total number of units at this location" + postcode: "What is the postcode?" + name: "What is the name of this location?" + units: "How many units are at this location?" type_of_unit: "What is the most common type of unit at this location?" - startdate: "When did the first property in this location become available under this scheme? (optional)" - add_another_location: "Do you want to add another location?" + startdate: "When did the first property in this location become available under this scheme?" mobility_type: "What are the mobility standards for the majority of units in this location?" toggle_active: apply_from: "When should this change apply?" @@ -439,16 +445,17 @@ en: descriptions: location: mobility_type: - W: "The majority of units are suitable for someone who uses a wheelchair and offer the full use of all rooms and facilities." - A: "For example, the majority of units have been fitted with stairlifts, ramps, level access showers or grab rails." - N: "The majority of units are not designed to wheelchair-user standards or fitted with any equipment and adaptations." + W: "Suitable for someone who uses a wheelchair and offers the full use of all rooms and facilities." + A: "Fitted with stairlifts, ramps, level access showers or grab rails." + N: "Not designed to wheelchair-user standards or fitted with any equipment or adaptations." hints: location: postcode: "For example, SW1P 4DF." name: "This is how you refer to this location within your organisation" - units: "A unit can be a bedroom in a shared house or flat, or a house with 4 bedrooms. Do not include bedrooms used for wardens, managers, volunteers or sleep-in staff." + units: "A unit is the space being let. For example, the property might be a block of flats and the unit would be the specific flat being let. A unit can also be a bedroom in a shared house or flat. Do not include spaces used for staff." toggle_active: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed." + startdate: "For example, 27 3 2021" scheme: toggle_active: "If the date is before %{date}, select ‘From the start of the current collection period’ because the previous period has now closed." diff --git a/config/routes.rb b/config/routes.rb index 49eafc015..eef759e92 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -58,12 +58,27 @@ Rails.application.routes.draw do patch "reactivate", to: "schemes#reactivate" resources :locations do - get "edit-name", to: "locations#edit_name" - get "edit-local-authority", to: "locations#edit_local_authority" + post "locations", to: "locations#create" get "new-deactivation", to: "locations#new_deactivation" get "deactivate-confirm", to: "locations#deactivate_confirm" get "reactivate", to: "locations#reactivate" get "new-reactivation", to: "locations#new_reactivation" + get "postcode", to: "locations#postcode" + patch "postcode", to: "locations#update_postcode" + get "local-authority", to: "locations#local_authority" + patch "local-authority", to: "locations#update_local_authority" + get "name", to: "locations#name" + patch "name", to: "locations#update_name" + get "units", to: "locations#units" + patch "units", to: "locations#update_units" + get "type-of-unit", to: "locations#type_of_unit" + patch "type-of-unit", to: "locations#update_type_of_unit" + get "mobility-standards", to: "locations#mobility_standards" + patch "mobility-standards", to: "locations#update_mobility_standards" + get "availability", to: "locations#availability" + patch "availability", to: "locations#update_availability" + get "check-answers", to: "locations#check_answers" + patch "confirm", to: "locations#confirm" patch "new-deactivation", to: "locations#new_deactivation" patch "deactivate", to: "locations#deactivate" patch "reactivate", to: "locations#reactivate" diff --git a/spec/factories/location.rb b/spec/factories/location.rb index 870140cd5..75b4380f5 100644 --- a/spec/factories/location.rb +++ b/spec/factories/location.rb @@ -7,7 +7,7 @@ FactoryBot.define do mobility_type { %w[A M N W X].sample } location_code { "E09000033" } location_admin_district { "Westminster" } - startdate { nil } + startdate { Time.zone.local(2022, 4, 1) } confirmed { true } scheme trait :export do diff --git a/spec/features/schemes_helpers.rb b/spec/features/schemes_helpers.rb index 0592a8ef2..68c5d9dee 100644 --- a/spec/features/schemes_helpers.rb +++ b/spec/features/schemes_helpers.rb @@ -55,26 +55,43 @@ module SchemesHelpers end def fill_in_and_save_location - fill_in "Postcode", with: "AA11AA" - fill_in "Location name (optional)", with: "Some name" - fill_in "Total number of units at this location", with: 5 - fill_in "Day", with: 2 - fill_in "Month", with: 2 - fill_in "Year", with: 2022 + click_link "Locations" + click_button "Add a location" + fill_in with: "AA11AA" + click_button "Save and continue" + fill_in with: "Adur" + fill_in with: "Some name" + click_button "Save and continue" + fill_in with: 5 + click_button "Save and continue" choose "Self-contained house" - choose "location-add-another-location-no-field" + click_button "Save and continue" choose "location-mobility-type-none-field" click_button "Save and continue" + fill_in "Day", with: 2 + fill_in "Month", with: 5 + fill_in "Year", with: 2022 + click_button "Save and continue" end def fill_in_and_save_second_location - fill_in "Postcode", with: "AA12AA" - fill_in "Location name (optional)", with: "Other name" - fill_in "Total number of units at this location", with: 2 + click_link "Locations" + click_button "Add a location" + fill_in with: "AA12AA" + click_button "Save and continue" + fill_in with: "Adur" + fill_in with: "Other name" + click_button "Save and continue" + fill_in with: 2 + click_button "Save and continue" choose "Self-contained house" - choose "location-add-another-location-no-field" + click_button "Save and continue" choose "location-mobility-type-none-field" click_button "Save and continue" + fill_in "Day", with: 2 + fill_in "Month", with: 5 + fill_in "Year", with: 2022 + click_button "Save and continue" end def create_and_save_a_scheme diff --git a/spec/features/schemes_spec.rb b/spec/features/schemes_spec.rb index 728c3dcb6..4d8d460b9 100644 --- a/spec/features/schemes_spec.rb +++ b/spec/features/schemes_spec.rb @@ -270,59 +270,66 @@ RSpec.describe "Schemes scheme Features" do context "when the user clicks add location" do before do click_link("Locations") - click_link("Add a location") + click_button("Add a location") end it "shows the new location form" do - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("Add a location to #{scheme.service_name}") end context "when the user completes the new location form" do let(:location_name) { "Area 42" } before do - fill_in "Postcode", with: "NW1L 5DP" - fill_in "Location name (optional)", with: location_name - fill_in "Total number of units at this location", with: 1 - choose "Bungalow" + fill_in with: "AA12AA" + click_button "Save and continue" + fill_in with: "Adur" + fill_in with: location_name + click_button "Save and continue" + fill_in with: 1 + click_button "Save and continue" + choose "Self-contained house" + click_button "Save and continue" choose "location-mobility-type-none-field" - choose "location-add-another-location-no-field" + click_button "Save and continue" + fill_in "Day", with: 2 + fill_in "Month", with: 2 + fill_in "Year", with: 2022 click_button "Save and continue" end - it "shows the check answers page location tab" do - expect(page.current_url.split("/").last).to eq("check-answers#locations") + it "shows the location check answers page" do + expect(page.current_url.split("/").last).to eq("check-answers") expect(page).to have_content(location_name) end it "has the correct action button text" do - expect(page).to have_button("Save") - expect(page).not_to have_button("Create scheme") + expect(page).to have_button("Save and return to locations") end it "allows you to edit the newly added location" do - click_link "Locations" - expect(page).to have_link(nil, href: /edit/) + expect(page).to have_link(href: /postcode/) end context "when you click save" do + before do + click_button "Save and return to locations" + end + it "displays a updated banner" do - click_button "Save" expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") - expect(page).to have_content("has been updated") + expect(page).to have_content("has been added") end it "does not let you edit the saved location" do - click_link "Locations" - expect(page).to have_link(nil, href: /edit(?!-name)/) - click_button "Save" - click_link "Locations" - expect(page).not_to have_link(nil, href: /edit(?!-name)/) + click_link "AA1 2AA" + expect(page).not_to have_link(nil, href: /postcode/) end end context "when you click to view the scheme details" do before do + click_button "Save and return to locations" click_link("Scheme") end @@ -340,6 +347,7 @@ RSpec.describe "Schemes scheme Features" do context "when creating a new scheme" do let(:organisation_name) { "FooBar" } let(:scheme) { Scheme.first } + let(:location) { Location.first } before do FactoryBot.create(:organisation, name: organisation_name) @@ -468,68 +476,56 @@ RSpec.describe "Schemes scheme Features" do context "when adding a location" do before do create_and_save_a_scheme + click_button "Create scheme" end it "lets me add location" do - expect(page).to have_content "Add a location to this scheme" - end - - it "lets me navigate back to support questions" do - click_link "Back" - expect(page).to have_current_path("/schemes/#{scheme.id}/support") - expect(page).to have_content "What support does this scheme provide?" - end - - it "returns to the add location page after amending the support question" do - click_link "Back" - click_button "Save and continue" - expect(page).to have_current_path("/schemes/#{scheme.id}/locations/new") + click_link "Locations" + expect(page).to have_content "Add a location" end it "lets me check my answers after adding a location" do fill_in_and_save_location - expect(page).to have_current_path("/schemes/#{scheme.id}/check-answers") - expect(page).to have_content "Check your changes before creating this scheme" + expect(page).to have_current_path("/schemes/#{scheme.id}/locations/#{location.id}/check-answers") + expect(page).to have_content "Check your answers" end it "lets me check my answers after adding a second location" do fill_in_and_save_location - click_link "Add a location" + click_button "Save and return to locations" fill_in_and_save_second_location - expect(page).to have_content "Check your changes before creating this scheme" + expect(page).to have_content "Check your answers" end end context "when viewing locations" do before do create_and_save_a_scheme - + click_button "Create scheme" fill_in_and_save_location + click_button "Save and return to locations" click_link "Locations" end it "displays information about a single location" do expect(page).to have_content "Locations" - expect(page).to have_content "#{scheme.locations.count} location" + expect(page).to have_content "#{scheme.locations.count} total location" end it "displays information about the first created location" do expect(page).to have_content "AA1 1AA" expect(page).to have_content "Some name" - expect(page).to have_content "5" - expect(page).to have_content "Self-contained house" - expect(page).to have_content "2 February 2022" + expect(page).to have_content "Active" end it "displays information about another location" do - click_link "Add a location" fill_in_and_save_second_location + click_button "Save and return to locations" expect(page).to have_content "Locations" - expect(page).to have_content "#{scheme.locations.count} location" + expect(page).to have_content "#{scheme.locations.count} total location" end it "displays information about newly created location" do - click_link "Add a location" fill_in_and_save_second_location expect(page).to have_content "AA1 2AA" expect(page).to have_content "Other name" @@ -540,25 +536,24 @@ RSpec.describe "Schemes scheme Features" do context "when changing location details" do before do create_and_save_a_scheme + click_button "Create scheme" fill_in_and_save_second_location - click_link "Locations" + click_button "Save and return to locations" end it "displays changed location" do click_link "AA1 2AA" - fill_in "Postcode", with: "AA1 3AA" - choose "location-mobility-type-wheelchair-user-standard-field" - click_button "Save and continue" - expect(page).to have_content "Locations" - expect(page).to have_content "#{scheme.locations.count} location" - expect(page).to have_content "AA1 3AA" + click_link "Change" + fill_in with: "new name" + click_button "Save changes" + expect(page).to have_content "AA1 2AA" + expect(page).to have_content "new name" end end context "when changing scheme answers" do before do create_and_save_a_scheme - fill_in_and_save_location end it "displays change links" do @@ -594,7 +589,6 @@ RSpec.describe "Schemes scheme Features" do context "when selecting 'create a scheme'" do before do create_and_save_a_scheme - fill_in_and_save_location click_button "Create scheme" end @@ -650,7 +644,6 @@ RSpec.describe "Schemes scheme Features" do fill_in_and_save_secondary_client_group_confirmation fill_in_and_save_secondary_client_group fill_in_and_save_support - fill_in_and_save_location end it "displays change links" do @@ -832,7 +825,7 @@ RSpec.describe "Schemes scheme Features" do assert_selector "a", text: "Change", count: 1 click_link("Change") - expect(page).to have_content "Location name for #{location.postcode}" + expect(page).to have_content "What is the name of this location?" end it "allows to deactivate a location" do @@ -858,7 +851,7 @@ RSpec.describe "Schemes scheme Features" do it "returns to locations check your answers page and shows the new name" do fill_in "location-name-field", with: "NewName" - click_button "Save and continue" + click_button "Save changes" expect(page).to have_content location.postcode expect(page).to have_content "NewName" expect(page).to have_current_path("/schemes/#{scheme.id}/locations/#{location.id}") @@ -920,42 +913,70 @@ RSpec.describe "Schemes scheme Features" do context "when the user clicks add location" do before do click_link("Locations") - click_link("Add a location") + click_button("Add a location") end it "shows the new location form" do - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("Add a location to #{scheme.service_name}") end context "when the user completes the new location form" do let(:location_name) { "Area 42" } before do - fill_in "Postcode", with: "NW1L 5DP" - fill_in "Location name (optional)", with: location_name - fill_in "Total number of units at this location", with: 1 - choose "Bungalow" + fill_in with: "AA12AA" + click_button "Save and continue" + fill_in with: "Adur" + fill_in with: location_name + click_button "Save and continue" + fill_in with: 1 + click_button "Save and continue" + choose "Self-contained house" + click_button "Save and continue" choose "location-mobility-type-none-field" - choose "location-add-another-location-no-field" + click_button "Save and continue" + fill_in "Day", with: 2 + fill_in "Month", with: 2 + fill_in "Year", with: 2022 click_button "Save and continue" end - it "shows the check answers page location tab" do - expect(page.current_url.split("/").last).to eq("check-answers#locations") + it "shows the location check answers page" do + expect(page.current_url.split("/").last).to eq("check-answers") expect(page).to have_content(location_name) end it "has the correct action button text" do - expect(page).to have_button("Save") - expect(page).not_to have_button("Create scheme") + expect(page).to have_button("Save and return to locations") + end + + it "allows you to edit the newly added location" do + expect(page).to have_link(href: /postcode/) + end + + context "when you click save" do + before do + click_button "Save and return to locations" + end + + it "displays a updated banner" do + expect(page).to have_css(".govuk-notification-banner.govuk-notification-banner--success") + expect(page).to have_content("has been added") + end + + it "does not let you edit the saved location" do + click_link "AA1 2AA" + expect(page).not_to have_link(nil, href: /postcode/) + end end context "when you click to view the scheme details" do before do + click_button "Save and return to locations" click_link("Scheme") end - it "does not let you change details other than the name, Confidential information and Housing stock owned by" do + it "does not let you change details other than the name, confidential information and housing stock owner" do assert_selector "a", text: "Change", count: 3 end end diff --git a/spec/helpers/locations_helper_spec.rb b/spec/helpers/locations_helper_spec.rb index 96db265e3..4d58a7e8f 100644 --- a/spec/helpers/locations_helper_spec.rb +++ b/spec/helpers/locations_helper_spec.rb @@ -2,9 +2,9 @@ require "rails_helper" RSpec.describe LocationsHelper do describe "mobility type selection" do - expected_selection = [OpenStruct.new(id: "Wheelchair-user standard", name: "Wheelchair-user standard", description: "The majority of units are suitable for someone who uses a wheelchair and offer the full use of all rooms and facilities."), - OpenStruct.new(id: "Fitted with equipment and adaptations", name: "Fitted with equipment and adaptations", description: "For example, the majority of units have been fitted with stairlifts, ramps, level access showers or grab rails."), - OpenStruct.new(id: "None", name: "None", description: "The majority of units are not designed to wheelchair-user standards or fitted with any equipment and adaptations.")] + expected_selection = [OpenStruct.new(id: "Wheelchair-user standard", name: "Wheelchair-user standard", description: "Suitable for someone who uses a wheelchair and offers the full use of all rooms and facilities."), + OpenStruct.new(id: "Fitted with equipment and adaptations", name: "Fitted with equipment and adaptations", description: "Fitted with stairlifts, ramps, level access showers or grab rails."), + OpenStruct.new(id: "None", name: "None", description: "Not designed to wheelchair-user standards or fitted with any equipment or adaptations.")] it "returns correct selection to display" do expect(mobility_type_selection).to eq(expected_selection) end @@ -138,15 +138,15 @@ RSpec.describe LocationsHelper do it "returns correct display attributes" do attributes = [ - { name: "Postcode", value: location.postcode }, - { name: "Location name", value: location.name, edit: true }, - { name: "Local authority", value: location.location_admin_district }, - { name: "Total number of units at this location", value: location.units }, - { name: "Common type of unit", value: location.type_of_unit }, - { name: "Mobility type", value: location.mobility_type }, - { name: "Location code", value: location.location_code }, - { name: "Availability", value: "Active from 1 April 2022" }, - { name: "Status", value: :active }, + { attribute: "postcode", name: "Postcode", value: location.postcode }, + { attribute: "name", name: "Location name", value: location.name }, + { attribute: "local_authority", name: "Local authority", value: location.location_admin_district }, + { attribute: "units", name: "Number of units", value: location.units }, + { attribute: "type_of_unit", name: "Most common unit", value: location.type_of_unit }, + { attribute: "mobility_standards", name: "Mobility standards", value: location.mobility_type }, + { attribute: "location_code", name: "Location code", value: location.location_code }, + { attribute: "availability", name: "Availability", value: "Active from 1 April 2022" }, + { attribute: "status", name: "Status", value: :active }, ] expect(display_location_attributes(location)).to eq(attributes) diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb index 11c826d28..51509d765 100644 --- a/spec/models/location_spec.rb +++ b/spec/models/location_spec.rb @@ -20,7 +20,7 @@ RSpec.describe Location, type: :model do end end - describe "#validate_postcode" do + describe "#postcode" do let(:location) { FactoryBot.build(:location) } it "does not add an error if postcode is valid" do @@ -31,14 +31,34 @@ RSpec.describe Location, type: :model do it "does add an error when the postcode is invalid" do location.postcode = "invalid" - expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Postcode #{I18n.t('validations.postcode')}") + location.valid?(:postcode) + expect(location.errors.count).to eq(1) end it "does add an error when the postcode is missing" do location.postcode = nil - expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Postcode #{I18n.t('validations.postcode')}") + location.valid?(:postcode) + expect(location.errors.count).to eq(1) + end + end + + describe "#local_authority" do + let(:location) { FactoryBot.build(:location) } + + it "does add an error when the local authority is invalid" do + location.location_admin_district = nil + location.valid?(:location_admin_district) + expect(location.errors.count).to eq(1) + end + end + + describe "#name" do + let(:location) { FactoryBot.build(:location) } + + it "does not add an error when the name is invalid" do + location.name = nil + location.valid? + expect(location.errors.count).to eq(0) end end @@ -47,8 +67,8 @@ RSpec.describe Location, type: :model do it "does add an error when the number of units is invalid" do location.units = nil - expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Units #{I18n.t('activerecord.errors.models.location.attributes.units.blank')}") + location.valid?(:units) + expect(location.errors.count).to eq(1) end end @@ -57,8 +77,8 @@ RSpec.describe Location, type: :model do it "does add an error when the type of unit is invalid" do location.type_of_unit = nil - expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Type of unit #{I18n.t('activerecord.errors.models.location.attributes.type_of_unit.blank')}") + location.valid?(:type_of_unit) + expect(location.errors.count).to eq(1) end end @@ -67,8 +87,18 @@ RSpec.describe Location, type: :model do it "does add an error when the mobility type is invalid" do location.mobility_type = nil - expect { location.save! } - .to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Mobility type #{I18n.t('activerecord.errors.models.location.attributes.mobility_type.blank')}") + location.valid?(:mobility_type) + expect(location.errors.count).to eq(1) + end + end + + describe "#availability" do + let(:location) { FactoryBot.build(:location) } + + it "does add an error when the availability is invalid" do + location.startdate = Time.zone.local(1, 1, 1) + location.valid?(:startdate) + expect(location.errors.count).to eq(1) end end @@ -90,7 +120,7 @@ RSpec.describe Location, type: :model do before do FactoryBot.create(:location, name: "ABC", postcode: "NW1 8RR", startdate: Time.zone.today) FactoryBot.create(:location, name: "XYZ", postcode: "SE1 6HJ", startdate: Time.zone.today + 1.day) - FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: Time.zone.today - 1.day, confirmed: false) + FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: Time.zone.today - 1.day, units: nil) FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: nil) end @@ -122,7 +152,7 @@ RSpec.describe Location, type: :model do end context "when filtering by active locations" do - it "returns only locations that started today or earlier and have been confirmed" do + it "returns only locations that started today or earlier and are complete (and so confirmed)" do expect(described_class.active.count).to eq(2) end end diff --git a/spec/models/validations/date_validations_spec.rb b/spec/models/validations/date_validations_spec.rb index 11e929741..20d1e094c 100644 --- a/spec/models/validations/date_validations_spec.rb +++ b/spec/models/validations/date_validations_spec.rb @@ -86,7 +86,7 @@ RSpec.describe Validations::DateValidations do context "with a deactivated location" do let(:scheme) { create(:scheme) } - let(:location) { create(:location, scheme:, startdate: nil) } + let(:location) { create(:location, scheme:) } before do create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), location:) @@ -111,7 +111,7 @@ RSpec.describe Validations::DateValidations do context "with a location that is reactivating soon" do let(:scheme) { create(:scheme) } - let(:location) { create(:location, scheme:, startdate: nil) } + let(:location) { create(:location, scheme:) } before do create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), location:) @@ -136,7 +136,7 @@ RSpec.describe Validations::DateValidations do context "with a location that has many reactivations soon" do let(:scheme) { create(:scheme) } - let(:location) { create(:location, scheme:, startdate: nil) } + let(:location) { create(:location, scheme:) } before do create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), location:) diff --git a/spec/models/validations/setup_validations_spec.rb b/spec/models/validations/setup_validations_spec.rb index 701e410ad..326a6936d 100644 --- a/spec/models/validations/setup_validations_spec.rb +++ b/spec/models/validations/setup_validations_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Validations::SetupValidations do describe "#validate_scheme" do context "with a deactivated location" do let(:scheme) { create(:scheme) } - let(:location) { create(:location, scheme:, startdate: nil) } + let(:location) { create(:location, scheme:) } before do create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), location:) @@ -59,7 +59,7 @@ RSpec.describe Validations::SetupValidations do context "with a location that is reactivating soon" do let(:scheme) { create(:scheme) } - let(:location) { create(:location, scheme:, startdate: nil) } + let(:location) { create(:location, scheme:) } before do create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), location:) @@ -156,7 +156,7 @@ RSpec.describe Validations::SetupValidations do describe "#validate_location" do context "with a deactivated location" do let(:scheme) { create(:scheme) } - let(:location) { create(:location, scheme:, startdate: nil) } + let(:location) { create(:location, scheme:) } before do create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), location:) @@ -181,7 +181,7 @@ RSpec.describe Validations::SetupValidations do context "with a location that is reactivating soon" do let(:scheme) { create(:scheme) } - let(:location) { create(:location, scheme:, startdate: nil) } + let(:location) { create(:location, scheme:) } before do create(:location_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), location:) diff --git a/spec/requests/locations_controller_spec.rb b/spec/requests/locations_controller_spec.rb index e870fe4ff..3b75339ff 100644 --- a/spec/requests/locations_controller_spec.rb +++ b/spec/requests/locations_controller_spec.rb @@ -10,10 +10,10 @@ RSpec.describe LocationsController, type: :request do allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form) end - describe "#new" do + describe "#create" do context "when not signed in" do it "redirects to the sign in page" do - get "/schemes/1/locations/new" + get "/schemes/1/locations/create" expect(response).to redirect_to("/account/sign-in") end end @@ -23,7 +23,7 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - get "/schemes/1/locations/new" + get "/schemes/1/locations/create" end it "returns 401 unauthorized" do @@ -38,52 +38,82 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - get "/schemes/#{scheme.id}/locations/new" + post scheme_locations_path(scheme) + end + + it "creates a new location for scheme and redirects to correct page" do + expect { post scheme_locations_path(scheme) }.to change(Location, :count).by(1) end - it "returns a template for a new location" do + it "redirects to the postcode page" do + follow_redirect! expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("What is the postcode?") end - context "when trying to new location to a scheme that belongs to another organisation" do + it "creates a new location for scheme with the right owning organisation" do + expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) + end + + context "when trying to add a new location to a scheme that belongs to another organisation" do let(:another_scheme) { FactoryBot.create(:scheme) } it "displays the new page with an error message" do - get "/schemes/#{another_scheme.id}/locations/new" + post scheme_locations_path(another_scheme) expect(response).to have_http_status(:not_found) end end end context "when signed in as a support user" do + let(:user) { FactoryBot.create(:user, :data_coordinator) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + before do allow(user).to receive(:need_two_factor_authentication?).and_return(false) sign_in user - get "/schemes/#{scheme.id}/locations/new" + post scheme_locations_path(scheme) end - it "returns a template for a new location" do + it "creates a new location for scheme and redirects to correct page" do + expect { post scheme_locations_path(scheme) }.to change(Location, :count).by(1) + end + + it "redirects to the postcode page" do + follow_redirect! expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("What is the postcode?") + end + + it "creates a new location for scheme with the right owning organisation" do + expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) + end + + context "when trying to add a new location to a scheme that belongs to another organisation" do + let(:another_scheme) { FactoryBot.create(:scheme) } + + it "displays the new page with an error message" do + post scheme_locations_path(another_scheme) + expect(response).to have_http_status(:not_found) + end end end end - describe "#create" do + describe "#index" do context "when not signed in" do it "redirects to the sign in page" do - post "/schemes/1/locations" + get "/schemes/#{scheme.id}/locations" expect(response).to redirect_to("/account/sign-in") end end - context "when signed in as a data provider" do + context "when signed in as a data provider user" do let(:user) { FactoryBot.create(:user) } before do sign_in user - post "/schemes/1/locations" + get "/schemes/#{scheme.id}/locations" end it "returns 401 unauthorized" do @@ -92,386 +122,397 @@ RSpec.describe LocationsController, type: :request do end end - context "when signed in as a data coordinator" do + context "when signed in as a data coordinator user" do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let(:startdate) { Time.utc(2022, 2, 2) } - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", startdate:, mobility_type: "A" } } } + let!(:locations) { FactoryBot.create_list(:location, 3, scheme:, startdate: Time.zone.local(2022, 4, 1)) } before do sign_in user - post "/schemes/#{scheme.id}/locations", params: - end - - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your answers before creating this scheme") + get "/schemes/#{scheme.id}/locations" end - it "creates a new location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.postcode).to eq("ZZ1 1ZZ") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - expect(Location.last.startdate).to eq(startdate) - expect(Location.last.mobility_type).to eq("Fitted with equipment and adaptations") - end + context "when coordinator attempts to see scheme belonging to a different organisation" do + let!(:another_scheme) { FactoryBot.create(:scheme) } - context "when postcode is submitted with lower case" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "zz1 1zz", mobility_type: "N" } } } + before do + FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2022, 4, 1)) + end - it "creates a new location for scheme with postcode " do - expect(Location.last.postcode).to eq("ZZ1 1ZZ") + it "returns 404 not found" do + get "/schemes/#{another_scheme.id}/locations" + expect(response).to have_http_status(:not_found) end end - context "when startdate is submitted with leading zeroes" do - let(:params) do - { location: { - name: "Test", - units: "5", - type_of_unit: "Bungalow", - add_another_location: "No", - postcode: "zz1 1zz", - mobility_type: "N", - "startdate(3i)" => "01", - "startdate(2i)" => "01", - "startdate(1i)" => "2022", - } } + it "shows locations with correct data wben the new locations layout feature toggle is enabled" do + locations.each do |location| + expect(page).to have_content(location.id) + expect(page).to have_content(location.postcode) + expect(page).to have_content(location.name) + expect(page).to have_content(location.status) end + end - it "creates a new location for scheme with postcode " do - expect(Location.last.startdate).to eq(Time.utc(2022, 1, 1)) + it "shows locations with correct data wben the new locations layout feature toggle is disabled" do + allow(FeatureToggle).to receive(:location_toggle_enabled?).and_return(false) + get "/schemes/#{scheme.id}/locations" + locations.each do |location| + expect(page).to have_content(location.id) + expect(page).to have_content(location.postcode) + expect(page).to have_content(location.type_of_unit) + expect(page).to have_content(location.mobility_type) + expect(page).to have_content(location.location_admin_district) + expect(page).to have_content(location.startdate&.to_formatted_s(:govuk_date)) end end - context "when trying to add location to a scheme that belongs to another organisation" do - let(:another_scheme) { FactoryBot.create(:scheme) } - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", mobility_type: "N" } } } + it "has page heading" do + expect(page).to have_content(scheme.service_name) + end - it "displays the new page with an error message" do - post "/schemes/#{another_scheme.id}/locations", params: params - expect(response).to have_http_status(:not_found) - end + it "has correct title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) end - context "when do you want to add another location is selected as yes" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "Yes", postcode: "ZZ1 1ZZ", mobility_type: "N" } } } + context "when paginating over 20 results" do + let!(:locations) { FactoryBot.create_list(:location, 25, scheme:) } - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + context "when on the first page" do + before do + get "/schemes/#{scheme.id}/locations" + end + + it "shows which schemes are being shown on the current page" do + expect(CGI.unescape_html(response.body)).to match("Showing 1 to 20 of #{locations.count} locations") + end + + it "has correct page 1 of 2 title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) + end + + it "has pagination links" do + expect(page).not_to have_content("Previous") + expect(page).not_to have_link("Previous") + expect(page).to have_content("Next") + expect(page).to have_link("Next") + end end - it "creates a new location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - expect(Location.last.mobility_type).to eq("None") + context "when on the second page" do + before do + get "/schemes/#{scheme.id}/locations?page=2" + end + + it "shows which schemes are being shown on the current page" do + expect(CGI.unescape_html(response.body)).to match("Showing 21 to 25 of #{locations.count} locations") + end + + it "has correct page 2 of 2 title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) + end + + it "has pagination links" do + expect(page).to have_content("Previous") + expect(page).to have_link("Previous") + expect(page).not_to have_content("Next") + expect(page).not_to have_link("Next") + end end end - context "when do you want to add another location is selected as no" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", mobility_type: "N" } } } + context "when searching" do + let(:searched_location) { locations.first } + let(:search_param) { searched_location.name } + + before do + get "/schemes/#{scheme.id}/locations?search=#{search_param}" + end - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") + it "returns matching results" do + expect(page).to have_content(searched_location.name) + locations[1..].each do |location| + expect(page).not_to have_content(location.name) + end end - it "creates a new location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + it "updates the table caption" do + expect(page).to have_content("1 location found matching ‘#{search_param}’") + end + + it "has search in the title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} (1 location matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) end end + end - context "when do you want to add another location is not selected" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", postcode: "ZZ1 1ZZ", mobility_type: "W" } } } + context "when signed in as a support user" do + let(:user) { FactoryBot.create(:user, :support) } + let!(:scheme) { FactoryBot.create(:scheme) } + let!(:locations) { FactoryBot.create_list(:location, 3, scheme:, startdate: Time.zone.local(2022, 4, 1)) } - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + get "/schemes/#{scheme.id}/locations" + end + + it "shows locations with correct data wben the new locations layout feature toggle is enabled" do + locations.each do |location| + expect(page).to have_content(location.id) + expect(page).to have_content(location.postcode) + expect(page).to have_content(location.name) + expect(page).to have_content(location.status) end + end - it "creates a new location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - expect(Location.last.mobility_type).to eq("Wheelchair-user standard") + it "shows locations with correct data wben the new locations layout feature toggle is disabled" do + allow(FeatureToggle).to receive(:location_toggle_enabled?).and_return(false) + get "/schemes/#{scheme.id}/locations" + locations.each do |location| + expect(page).to have_content(location.id) + expect(page).to have_content(location.postcode) + expect(page).to have_content(location.type_of_unit) + expect(page).to have_content(location.mobility_type) + expect(page).to have_content(location.location_admin_district) + expect(page).to have_content(location.startdate&.to_formatted_s(:govuk_date)) end end - context "when required param are missing" do - let(:params) { { location: { postcode: "", name: "Test", units: "", type_of_unit: "", add_another_location: "No" } } } + it "has page heading" do + expect(page).to have_content(scheme.service_name) + end - it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.postcode")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.units.blank")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.type_of_unit.blank")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.mobility_type.blank")) - end + it "has correct title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) end - context "when invalid time is supplied" do - let(:params) do - { location: { - name: "Test", - units: "5", - type_of_unit: "Bungalow", - mobility_type: "N", - add_another_location: "No", - postcode: "ZZ1 1ZZ", - "startdate(3i)" => "1", - "startdate(2i)" => "1", - "startdate(1i)" => "w", - } } + context "when paginating over 20 results" do + let!(:locations) { FactoryBot.create_list(:location, 25, scheme:) } + + context "when on the first page" do + before do + get "/schemes/#{scheme.id}/locations" + end + + it "shows which schemes are being shown on the current page" do + expect(CGI.unescape_html(response.body)).to match("Showing 1 to 20 of #{locations.count} locations") + end + + it "has correct page 1 of 2 title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) + end + + it "has pagination links" do + expect(page).not_to have_content("Previous") + expect(page).not_to have_link("Previous") + expect(page).to have_content("Next") + expect(page).to have_link("Next") + end end - it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.date.invalid_date")) + context "when on the second page" do + before do + get "/schemes/#{scheme.id}/locations?page=2" + end + + it "shows which schemes are being shown on the current page" do + expect(CGI.unescape_html(response.body)).to match("Showing 21 to 25 of #{locations.count} locations") + end + + it "has correct page 1 of 2 title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) + end + + it "has pagination links" do + expect(page).to have_content("Previous") + expect(page).to have_link("Previous") + expect(page).not_to have_content("Next") + expect(page).not_to have_link("Next") + end end end - context "when no startdate is supplied" do - let(:params) do - { location: { - name: "Test", - units: "5", - type_of_unit: "Bungalow", - mobility_type: "N", - add_another_location: "No", - postcode: "ZZ1 1ZZ", - "startdate(3i)" => "", - "startdate(2i)" => "", - "startdate(1i)" => "", - } } + context "when searching" do + let(:searched_location) { locations.first } + let(:search_param) { searched_location.name } + + before do + get "/schemes/#{scheme.id}/locations?search=#{search_param}" end - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your answers before creating this scheme") + it "returns matching results" do + expect(page).to have_content(searched_location.name) + locations[1..].each do |location| + expect(page).not_to have_content(location.name) + end end - end - context "when postcodes.io doesn't return a la_code" do - let(:params) do - { location: { - name: "Test", - units: "5", - type_of_unit: "Bungalow", - mobility_type: "N", - add_another_location: "No", - postcode: "AA1 4AA", - "startdate(3i)" => "", - "startdate(2i)" => "", - "startdate(1i)" => "", - } } + it "updates the table caption" do + expect(page).to have_content("1 location found matching ‘#{search_param}’") end - it "redirects to la_fallback" do - post "/schemes/#{scheme.id}/locations", params: params - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("What is the local authority of AA1 4AA?") + it "has search in the title" do + expected_title = CGI.escapeHTML("#{scheme.service_name} (1 location matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK") + expect(page).to have_title(expected_title) end end end + end - context "when signed in as a support user" do - let(:user) { FactoryBot.create(:user, :support) } - let!(:scheme) { FactoryBot.create(:scheme) } - let(:params) { { location: { name: " Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", mobility_type: "N" } } } + describe "#postcode" do + context "when not signed in" do + it "redirects to the sign in page" do + get "/schemes/1/locations/1/postcode" + expect(response).to redirect_to("/account/sign-in") + end + end + + context "when signed in as a data provider" do + let(:user) { FactoryBot.create(:user) } before do - allow(user).to receive(:need_two_factor_authentication?).and_return(false) sign_in user - post "/schemes/#{scheme.id}/locations", params: + get "/schemes/1/locations/1/postcode" end - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your answers before creating this scheme") + it "returns 401 unauthorized" do + request + expect(response).to have_http_status(:unauthorized) + end + end + + context "when signed in as a data coordinator" do + let(:user) { FactoryBot.create(:user, :data_coordinator) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let!(:location) { FactoryBot.create(:location, scheme:) } + + before do + sign_in user + get "/schemes/#{scheme.id}/locations/#{location.id}/postcode" end - it "creates a new location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.postcode).to eq("ZZ1 1ZZ") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + it "returns a template for a postcode" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("What is the postcode?") end context "when postcode is submitted with lower case" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "zz1 1zz", mobility_type: "N" } } } + let(:params) { { location: { postcode: "zz1 1zz" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/postcode", params: + end - it "creates a new location for scheme with postcode " do + it "adds postcode to location" do expect(Location.last.postcode).to eq("ZZ1 1ZZ") end + + it "redirects correctly when postcodes.io does return a local authority" do + follow_redirect! + expect(page).to have_content("What is the name of this location?") + end end - context "when required postcode param is missing" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No" } } } + context "when postcodes.io does not return a local authority" do + let(:params) { { location: { postcode: "xx1 1xx" } } } - it "displays the new page with an error message" do - post "/schemes/#{scheme.id}/locations", params: params - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.postcode")) + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/postcode", params: end - end - context "when do you want to add another location is selected as yes" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "Yes", postcode: "ZZ1 1ZZ", mobility_type: "N" } } } + it "adds postcode to location" do + expect(Location.last.postcode).to eq("XX11XX") + end - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) + it "redirects correctly" do follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("What is the local authority") end + end - it "creates a new location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + context "when trying to edit postcode of location that belongs to another organisation" do + let(:another_scheme) { FactoryBot.create(:scheme) } + let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } + + it "displays the new page with an error message" do + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/postcode" + expect(response).to have_http_status(:not_found) end end + end - context "when do you want to add another location is selected as no" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", mobility_type: "N" } } } + context "when signed in as a support user" do + let(:user) { FactoryBot.create(:user, :support) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let!(:location) { FactoryBot.create(:location, scheme:) } - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") - end + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + get "/schemes/#{scheme.id}/locations/#{location.id}/postcode" + end - it "creates a new location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - end + it "returns a template for a postcode" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("What is the postcode?") end - context "when do you want to add another location is not selected" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", postcode: "ZZ1 1ZZ", mobility_type: "N" } } } + context "when postcode is submitted with lower case" do + let(:params) { { location: { postcode: "zz1 1zz" } } } - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/postcode", params: end - it "creates a new location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + it "adds postcode to location" do + expect(Location.last.postcode).to eq("ZZ1 1ZZ") end - end - context "when required param are missing" do - let(:params) { { location: { postcode: "", name: "Test", units: "", type_of_unit: "", add_another_location: "No" } } } - - it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.postcode")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.units.blank")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.type_of_unit.blank")) + it "redirects correctly when postcodes.io does return a local authority" do + follow_redirect! + expect(page).to have_content("What is the name of this location?") end end - context "when invalid time is supplied" do - let(:params) do - { location: { - name: "Test", - units: "5", - type_of_unit: "Bungalow", - mobility_type: "N", - add_another_location: "No", - postcode: "ZZ1 1ZZ", - "startdate(3i)" => "1", - "startdate(2i)" => "1", - "startdate(1i)" => "w", - } } - end + context "when postcodes.io does not return a local authority" do + let(:params) { { location: { postcode: "xx1 1xx" } } } - it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.date.invalid_date")) + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/postcode", params: end - end - context "when no startdate is supplied" do - let(:params) do - { location: { - name: "Test", - units: "5", - type_of_unit: "Bungalow", - mobility_type: "N", - add_another_location: "No", - postcode: "ZZ1 1ZZ", - "startdate(3i)" => "", - "startdate(2i)" => "", - "startdate(1i)" => "", - } } + it "adds postcode to location" do + expect(Location.last.postcode).to eq("XX11XX") end - it "creates a new location for scheme with valid params and redirects to correct page" do - expect { post "/schemes/#{scheme.id}/locations", params: }.to change(Location, :count).by(1) + it "redirects correctly" do follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your answers before creating this scheme") + expect(page).to have_content("What is the local authority") end end - context "when postcodes.io doesn't return a la_code" do - let(:params) do - { location: { - name: "Test", - units: "5", - type_of_unit: "Bungalow", - mobility_type: "N", - add_another_location: "No", - postcode: "AA1 4AA", - "startdate(3i)" => "", - "startdate(2i)" => "", - "startdate(1i)" => "", - } } - end + context "when the requested location does not exist" do + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } - it "redirects to la_fallback" do - post "/schemes/#{scheme.id}/locations", params: params - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("What is the local authority of AA1 4AA?") + it "returns not found" do + expect(response).to have_http_status(:not_found) end end end end - describe "#edit" do + describe "#local_authority" do context "when not signed in" do it "redirects to the sign in page" do - get "/schemes/1/locations/1/edit" + get "/schemes/1/locations/1/local-authority" expect(response).to redirect_to("/account/sign-in") end end @@ -481,7 +522,7 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - get "/schemes/1/locations/1/edit" + get "/schemes/1/locations/1/local-authority" end it "returns 401 unauthorized" do @@ -497,28 +538,38 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - get "/schemes/#{scheme.id}/locations/#{location.id}/edit" + get "/schemes/#{scheme.id}/locations/#{location.id}/local-authority" end - it "returns a template for a new location" do + it "returns a template for a local authority" do expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("What is the local authority") end - context "when trying to edit a location that belongs to another organisation" do - let(:another_scheme) { FactoryBot.create(:scheme) } - let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } + context "when local authority is submitted" do + let(:params) { { location: { location_admin_district: "Adur" } } } - it "displays the new page with an error message" do - get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/edit" - expect(response).to have_http_status(:not_found) + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/local-authority", params: + end + + it "adds local authority to location " do + expect(Location.last.location_admin_district).to eq("Adur") + expect(Location.last.location_code).to eq("E07000223") + end + + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("What is the name of this location?") end end - context "when the requested location does not exist" do - let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1) } + context "when trying to edit local authority of location that belongs to another organisation" do + let(:another_scheme) { FactoryBot.create(:scheme) } + let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } - it "returns not found" do + it "displays the new page with an error message" do + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/local-authority" expect(response).to have_http_status(:not_found) end end @@ -532,20 +583,46 @@ RSpec.describe LocationsController, type: :request do before do allow(user).to receive(:need_two_factor_authentication?).and_return(false) sign_in user - get "/schemes/#{scheme.id}/locations/#{location.id}/edit" + get "/schemes/#{scheme.id}/locations/#{location.id}/local-authority" end - it "returns a template for a new location" do + it "returns a template for a local authority" do expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("What is the local authority") + end + + context "when local authority is submitted" do + let(:params) { { location: { location_admin_district: "Adur" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/local-authority", params: + end + + it "adds local authority to location " do + expect(Location.last.location_admin_district).to eq("Adur") + expect(Location.last.location_code).to eq("E07000223") + end + + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("What is the name of this location?") + end + end + + context "when the requested location does not exist" do + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } + + it "returns not found" do + expect(response).to have_http_status(:not_found) + end end end end - describe "#update" do + describe "#name" do context "when not signed in" do it "redirects to the sign in page" do - patch "/schemes/1/locations/1" + get "/schemes/1/locations/1/name" expect(response).to redirect_to("/account/sign-in") end end @@ -555,7 +632,7 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - patch "/schemes/1/locations/1" + get "/schemes/1/locations/1/name" end it "returns 401 unauthorized" do @@ -568,274 +645,210 @@ RSpec.describe LocationsController, type: :request do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } let!(:location) { FactoryBot.create(:location, scheme:) } - let(:startdate) { Time.utc(2021, 1, 2) } - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", startdate:, page: "edit" } } } before do sign_in user - patch "/schemes/#{scheme.id}/locations/#{location.id}", params: + get "/schemes/#{scheme.id}/locations/#{location.id}/name" end - it "updates existing location for scheme with valid params and redirects to correct page" do - follow_redirect! + it "returns a template for a name" do expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your answers before creating this scheme") - end - - it "updates existing location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.postcode).to eq("ZZ1 1ZZ") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - expect(Location.last.startdate).to eq(startdate) + expect(page).to have_content("What is the name of this location?") end - context "when updating from edit-name page" do - let(:params) { { location: { name: "Test", page: "edit-name" } } } + context "when name is submitted" do + let(:params) { { location: { name: "a name" } } } - it "updates existing location for scheme with valid params and redirects to correct page" do - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Test") + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/name", params: end - it "updates existing location for scheme with valid params" do - expect(Location.last.name).to eq("Test") + it "adds name to location" do + expect(Location.last.name).to eq("a name") end - end - - context "when postcode is submitted with lower case" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "zz1 1zz", page: "edit" } } } - it "updates existing location for scheme with postcode " do - expect(Location.last.postcode).to eq("ZZ1 1ZZ") + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("How many units are at this location?") end end - context "when trying to update location for a scheme that belongs to another organisation" do + context "when trying to edit name of location that belongs to another organisation" do let(:another_scheme) { FactoryBot.create(:scheme) } - let(:another_location) { FactoryBot.create(:location) } - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", page: "edit" } } } + let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } it "displays the new page with an error message" do - patch "/schemes/#{another_scheme.id}/locations/#{another_location.id}", params: params + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/name" expect(response).to have_http_status(:not_found) end end + end - context "when required postcode param is invalid" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "invalid", page: "edit" } } } + context "when signed in as a support user" do + let(:user) { FactoryBot.create(:user, :support) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let!(:location) { FactoryBot.create(:location, scheme:) } - it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.postcode")) - end + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + get "/schemes/#{scheme.id}/locations/#{location.id}/name" end - context "when do you want to add another location is selected as yes" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "Yes", postcode: "ZZ1 1ZZ", page: "edit" } } } + it "returns a template for a name" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("What is the name of this location?") + end - it "updates existing location for scheme with valid params and redirects to correct page" do - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") - end + context "when name is submitted" do + let(:params) { { location: { name: "a name" } } } - it "updates existing location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/name", params: end - end - - context "when do you want to add another location is selected as no" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", page: "edit" } } } - it "updates existing location for scheme with valid params and redirects to correct page" do - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") + it "adds name to location" do + expect(Location.last.name).to eq("a name") end - it "updates existing location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("How many units are at this location?") end end - context "when do you want to add another location is not selected" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", postcode: "ZZ1 1ZZ", page: "edit" } } } + context "when the requested location does not exist" do + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } - it "updates existing location for scheme with valid params and redirects to correct page" do - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") + it "returns not found" do + expect(response).to have_http_status(:not_found) end + end + end + end - it "updates existing location for scheme with valid params" do - expect(Location.last.scheme.owning_organisation_id).to eq(user.organisation_id) - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - end + describe "#units" do + context "when not signed in" do + it "redirects to the sign in page" do + get "/schemes/1/locations/1/units" + expect(response).to redirect_to("/account/sign-in") end + end - context "when required param are missing" do - let(:params) { { location: { postcode: "", name: "Test", units: "", type_of_unit: "", add_another_location: "No" } } } + context "when signed in as a data provider" do + let(:user) { FactoryBot.create(:user) } - it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.postcode")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.units.blank")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.type_of_unit.blank")) - end + before do + sign_in user + get "/schemes/1/locations/1/units" end - context "when the requested location does not exist" do - let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1) } - let(:params) { {} } - - it "returns not found" do - expect(response).to have_http_status(:not_found) - end + it "returns 401 unauthorized" do + request + expect(response).to have_http_status(:unauthorized) end end - context "when signed in as a support user" do + context "when signed in as a data coordinator" do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let!(:location) { FactoryBot.create(:location, scheme:) } - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", page: "edit" } } } + let!(:location) { FactoryBot.create(:location, scheme:) } before do - allow(user).to receive(:need_two_factor_authentication?).and_return(false) sign_in user - patch "/schemes/#{scheme.id}/locations/#{location.id}", params: + get "/schemes/#{scheme.id}/locations/#{location.id}/units" end - it "updates a location for scheme with valid params and redirects to correct page" do - follow_redirect! + it "returns a template for units" do expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your answers before creating this scheme") + expect(page).to have_content("How many units are at this location?") end - it "updates existing location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.postcode).to eq("ZZ1 1ZZ") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - end - - context "when updating from edit-name page" do - let(:params) { { location: { name: "Test", page: "edit-name" } } } + context "when units is submitted" do + let(:params) { { location: { units: 6 } } } - it "updates existing location for scheme with valid params and redirects to correct page" do - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Test") + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/units", params: end - it "updates existing location for scheme with valid params" do - expect(Location.last.name).to eq("Test") + it "adds units to location" do + expect(Location.last.units).to eq(6) end - end - - context "when postcode is submitted with lower case" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "zz1 1zz", page: "edit" } } } - it "updates a location for scheme with postcode " do - expect(Location.last.postcode).to eq("ZZ1 1ZZ") + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("What is the most common type of unit at this location?") end end - context "when required postcode param is missing" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "invalid", page: "edit" } } } + context "when trying to edit units of location that belongs to another organisation" do + let(:another_scheme) { FactoryBot.create(:scheme) } + let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.postcode")) + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/units" + expect(response).to have_http_status(:not_found) end end + end - context "when do you want to add another location is selected as yes" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "Yes", postcode: "ZZ1 1ZZ", page: "edit" } } } + context "when signed in as a support user" do + let(:user) { FactoryBot.create(:user, :support) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let!(:location) { FactoryBot.create(:location, scheme:) } - it "updates location for scheme with valid params and redirects to correct page" do - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") - end + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + get "/schemes/#{scheme.id}/locations/#{location.id}/units" + end - it "updates existing location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") - end + it "returns a template for units" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("How many units are at this location?") end - context "when do you want to add another location is selected as no" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", add_another_location: "No", postcode: "ZZ1 1ZZ", page: "edit" } } } + context "when units is submitted" do + let(:params) { { location: { units: 6 } } } - it "updates a location for scheme with valid params and redirects to correct page" do - follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/units", params: end - it "updates existing location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + it "adds units to location" do + expect(Location.last.units).to eq(6) end - end - context "when do you want to add another location is not selected" do - let(:params) { { location: { name: "Test", units: "5", type_of_unit: "Bungalow", postcode: "ZZ1 1ZZ", page: "edit" } } } - - it "updates a location for scheme with valid params and redirects to correct page" do + it "redirects correctly" do follow_redirect! - expect(response).to have_http_status(:ok) - expect(page).to have_content("Check your changes before creating this scheme") - end - - it "updates a location for scheme with valid params" do - expect(Location.last.name).to eq("Test") - expect(Location.last.units).to eq(5) - expect(Location.last.type_of_unit).to eq("Bungalow") + expect(page).to have_content("What is the most common type of unit at this location?") end end - context "when required param are missing" do - let(:params) { { location: { postcode: "", name: "Test", units: "", type_of_unit: "", add_another_location: "No" } } } + context "when the requested location does not exist" do + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } - it "displays the new page with an error message" do - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("validations.postcode")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.units.blank")) - expect(page).to have_content(I18n.t("activerecord.errors.models.location.attributes.type_of_unit.blank")) + it "returns not found" do + expect(response).to have_http_status(:not_found) end end end end - describe "#index" do + describe "#type_of_unit" do context "when not signed in" do it "redirects to the sign in page" do - get "/schemes/#{scheme.id}/locations" + get "/schemes/1/locations/1/type-of-unit" expect(response).to redirect_to("/account/sign-in") end end - context "when signed in as a data provider user" do + context "when signed in as a data provider" do let(:user) { FactoryBot.create(:user) } before do sign_in user - get "/schemes/#{scheme.id}/locations" + get "/schemes/1/locations/1/type-of-unit" end it "returns 401 unauthorized" do @@ -844,255 +857,204 @@ RSpec.describe LocationsController, type: :request do end end - context "when signed in as a data coordinator user" do + context "when signed in as a data coordinator" do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let!(:locations) { FactoryBot.create_list(:location, 3, scheme:, startdate: Time.zone.local(2022, 4, 1)) } + let!(:location) { FactoryBot.create(:location, scheme:) } before do sign_in user - get "/schemes/#{scheme.id}/locations" - end - - context "when coordinator attempts to see scheme belonging to a different organisation" do - let!(:another_scheme) { FactoryBot.create(:scheme) } - - before do - FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2022, 4, 1)) - end - - it "returns 404 not found" do - get "/schemes/#{another_scheme.id}/locations" - expect(response).to have_http_status(:not_found) - end - end - - it "shows locations with correct data wben the new locations layout feature toggle is enabled" do - locations.each do |location| - expect(page).to have_content(location.id) - expect(page).to have_content(location.postcode) - expect(page).to have_content(location.name) - expect(page).to have_content(location.status) - end - end - - it "shows locations with correct data wben the new locations layout feature toggle is disabled" do - allow(FeatureToggle).to receive(:location_toggle_enabled?).and_return(false) - get "/schemes/#{scheme.id}/locations" - locations.each do |location| - expect(page).to have_content(location.id) - expect(page).to have_content(location.postcode) - expect(page).to have_content(location.type_of_unit) - expect(page).to have_content(location.mobility_type) - expect(page).to have_content(location.location_admin_district) - expect(page).to have_content(location.startdate&.to_formatted_s(:govuk_date)) - end - end - - it "has page heading" do - expect(page).to have_content(scheme.service_name) - end - - it "has correct title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) + get "/schemes/#{scheme.id}/locations/#{location.id}/type-of-unit" end - context "when paginating over 20 results" do - let!(:locations) { FactoryBot.create_list(:location, 25, scheme:) } - - context "when on the first page" do - before do - get "/schemes/#{scheme.id}/locations" - end - - it "shows which schemes are being shown on the current page" do - expect(CGI.unescape_html(response.body)).to match("Showing 1 to 20 of #{locations.count} locations") - end - - it "has correct page 1 of 2 title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) - end - - it "has pagination links" do - expect(page).not_to have_content("Previous") - expect(page).not_to have_link("Previous") - expect(page).to have_content("Next") - expect(page).to have_link("Next") - end - end - - context "when on the second page" do - before do - get "/schemes/#{scheme.id}/locations?page=2" - end - - it "shows which schemes are being shown on the current page" do - expect(CGI.unescape_html(response.body)).to match("Showing 21 to 25 of #{locations.count} locations") - end - - it "has correct page 2 of 2 title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) - end - - it "has pagination links" do - expect(page).to have_content("Previous") - expect(page).to have_link("Previous") - expect(page).not_to have_content("Next") - expect(page).not_to have_link("Next") - end - end + it "returns a template for type of unit" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("What is the most common type of unit at this location?") end - context "when searching" do - let(:searched_location) { locations.first } - let(:search_param) { searched_location.name } + context "when type of unit is submitted" do + let(:params) { { location: { type_of_unit: "Bungalow" } } } before do - get "/schemes/#{scheme.id}/locations?search=#{search_param}" + patch "/schemes/#{scheme.id}/locations/#{location.id}/type-of-unit", params: end - it "returns matching results" do - expect(page).to have_content(searched_location.name) - locations[1..].each do |location| - expect(page).not_to have_content(location.name) - end + it "adds type of unit to location" do + expect(Location.last.type_of_unit).to eq("Bungalow") end - it "updates the table caption" do - expect(page).to have_content("1 location found matching ‘#{search_param}’") + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("What are the mobility standards for the majority of units in this location?") end + end - it "has search in the title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} (1 location matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) + context "when trying to edit type_of_unit of location that belongs to another organisation" do + let(:another_scheme) { FactoryBot.create(:scheme) } + let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } + + it "displays the new page with an error message" do + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/type-of-unit" + expect(response).to have_http_status(:not_found) end end end context "when signed in as a support user" do let(:user) { FactoryBot.create(:user, :support) } - let!(:scheme) { FactoryBot.create(:scheme) } - let!(:locations) { FactoryBot.create_list(:location, 3, scheme:, startdate: Time.zone.local(2022, 4, 1)) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let!(:location) { FactoryBot.create(:location, scheme:) } before do allow(user).to receive(:need_two_factor_authentication?).and_return(false) sign_in user - get "/schemes/#{scheme.id}/locations" + get "/schemes/#{scheme.id}/locations/#{location.id}/type-of-unit" end - it "shows locations with correct data wben the new locations layout feature toggle is enabled" do - locations.each do |location| - expect(page).to have_content(location.id) - expect(page).to have_content(location.postcode) - expect(page).to have_content(location.name) - expect(page).to have_content(location.status) + it "returns a template for type of unit" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("What is the most common type of unit at this location?") + end + + context "when type of unit is submitted" do + let(:params) { { location: { type_of_unit: "Bungalow" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/type-of-unit", params: + end + + it "adds type of unit to location" do + expect(Location.last.type_of_unit).to eq("Bungalow") + end + + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("What are the mobility standards for the majority of units in this location?") end end - it "shows locations with correct data wben the new locations layout feature toggle is disabled" do - allow(FeatureToggle).to receive(:location_toggle_enabled?).and_return(false) - get "/schemes/#{scheme.id}/locations" - locations.each do |location| - expect(page).to have_content(location.id) - expect(page).to have_content(location.postcode) - expect(page).to have_content(location.type_of_unit) - expect(page).to have_content(location.mobility_type) - expect(page).to have_content(location.location_admin_district) - expect(page).to have_content(location.startdate&.to_formatted_s(:govuk_date)) + context "when the requested location does not exist" do + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } + + it "returns not found" do + expect(response).to have_http_status(:not_found) end end + end + end - it "has page heading" do - expect(page).to have_content(scheme.service_name) + describe "#mobility_standards" do + context "when not signed in" do + it "redirects to the sign in page" do + get "/schemes/1/locations/1/mobility-standards" + expect(response).to redirect_to("/account/sign-in") end + end - it "has correct title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) + context "when signed in as a data provider" do + let(:user) { FactoryBot.create(:user) } + + before do + sign_in user + get "/schemes/1/locations/1/mobility-standards" end - context "when paginating over 20 results" do - let!(:locations) { FactoryBot.create_list(:location, 25, scheme:) } + it "returns 401 unauthorized" do + request + expect(response).to have_http_status(:unauthorized) + end + end - context "when on the first page" do - before do - get "/schemes/#{scheme.id}/locations" - end + context "when signed in as a data coordinator" do + let(:user) { FactoryBot.create(:user, :data_coordinator) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let!(:location) { FactoryBot.create(:location, scheme:) } - it "shows which schemes are being shown on the current page" do - expect(CGI.unescape_html(response.body)).to match("Showing 1 to 20 of #{locations.count} locations") - end + before do + sign_in user + get "/schemes/#{scheme.id}/locations/#{location.id}/mobility-standards" + end - it "has correct page 1 of 2 title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) - end + it "returns a template for mobility standards" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("What are the mobility standards for the majority of units in this location?") + end - it "has pagination links" do - expect(page).not_to have_content("Previous") - expect(page).not_to have_link("Previous") - expect(page).to have_content("Next") - expect(page).to have_link("Next") - end + context "when mobility standards is submitted" do + let(:params) { { location: { mobility_type: "Wheelchair-user standard" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/mobility-standards", params: end - context "when on the second page" do - before do - get "/schemes/#{scheme.id}/locations?page=2" - end + it "adds mobility standards to location" do + expect(Location.last.mobility_type).to eq("Wheelchair-user standard") + end - it "shows which schemes are being shown on the current page" do - expect(CGI.unescape_html(response.body)).to match("Showing 21 to 25 of #{locations.count} locations") - end + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("When did the first property in this location become available under this scheme?") + end + end - it "has correct page 1 of 2 title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) - end + context "when trying to edit mobility_standards of location that belongs to another organisation" do + let(:another_scheme) { FactoryBot.create(:scheme) } + let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } - it "has pagination links" do - expect(page).to have_content("Previous") - expect(page).to have_link("Previous") - expect(page).not_to have_content("Next") - expect(page).not_to have_link("Next") - end + it "displays the new page with an error message" do + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/mobility-standards" + expect(response).to have_http_status(:not_found) end end + end - context "when searching" do - let(:searched_location) { locations.first } - let(:search_param) { searched_location.name } + context "when signed in as a support user" do + let(:user) { FactoryBot.create(:user, :support) } + let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } + let!(:location) { FactoryBot.create(:location, scheme:) } + + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + get "/schemes/#{scheme.id}/locations/#{location.id}/mobility-standards" + end + + it "returns a template for mobility standards" do + expect(response).to have_http_status(:ok) + expect(page).to have_content("What are the mobility standards for the majority of units in this location?") + end + + context "when mobility standards is submitted" do + let(:params) { { location: { mobility_type: "Wheelchair-user standard" } } } before do - get "/schemes/#{scheme.id}/locations?search=#{search_param}" + patch "/schemes/#{scheme.id}/locations/#{location.id}/mobility-standards", params: end - it "returns matching results" do - expect(page).to have_content(searched_location.name) - locations[1..].each do |location| - expect(page).not_to have_content(location.name) - end + it "adds mobility standards to location" do + expect(Location.last.mobility_type).to eq("Wheelchair-user standard") end - it "updates the table caption" do - expect(page).to have_content("1 location found matching ‘#{search_param}’") + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("When did the first property in this location become available under this scheme?") end + end - it "has search in the title" do - expected_title = CGI.escapeHTML("#{scheme.service_name} (1 location matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK") - expect(page).to have_title(expected_title) + context "when the requested location does not exist" do + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } + + it "returns not found" do + expect(response).to have_http_status(:not_found) end end end end - describe "#edit-name" do + describe "#startdate" do context "when not signed in" do it "redirects to the sign in page" do - get "/schemes/1/locations/1/edit-name" + get "/schemes/1/locations/1/availability" expect(response).to redirect_to("/account/sign-in") end end @@ -1102,7 +1064,7 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - get "/schemes/1/locations/1/edit-name" + get "/schemes/1/locations/1/availability" end it "returns 401 unauthorized" do @@ -1118,20 +1080,67 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - get "/schemes/#{scheme.id}/locations/#{location.id}/edit-name" + get "/schemes/#{scheme.id}/locations/#{location.id}/availability" end - it "returns a template for a edit-name" do + it "returns a template for a startdate" do expect(response).to have_http_status(:ok) - expect(page).to have_content("Location name for #{location.postcode}") + expect(page).to have_content("When did the first property in this location become available under this scheme?") + end + + context "when startdate is submitted" do + let(:params) { { location: { "startdate(1i)": "2022", "startdate(2i)": "1", "startdate(3i)": "2" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/availability", params: + end + + it "adds startdate to location" do + expect(Location.last.startdate).to eq(Time.zone.local(2022, 1, 2)) + end + + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("Check your answers") + end + end + + context "when startdate is submitted with leading zeroes" do + let(:params) { { location: { "startdate(1i)": "2022", "startdate(2i)": "01", "startdate(3i)": "02" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/availability", params: + end + + it "adds startdate correctly " do + expect(Location.last.startdate).to eq(Time.zone.local(2022, 1, 2)) + end + + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("Check your answers") + end end - context "when trying to edit location name of location that belongs to another organisation" do + context "when startdate is missing" do + let(:params) { { location: { "startdate(1i)": "", "startdate(2i)": "", "startdate(3i)": "" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/availability", params: + end + + it "displays the new page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.location.startdate_invalid")) + end + end + + context "when trying to edit startdate of location that belongs to another organisation" do let(:another_scheme) { FactoryBot.create(:scheme) } let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } it "displays the new page with an error message" do - get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/edit-name" + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/availability" expect(response).to have_http_status(:not_found) end end @@ -1145,16 +1154,63 @@ RSpec.describe LocationsController, type: :request do before do allow(user).to receive(:need_two_factor_authentication?).and_return(false) sign_in user - get "/schemes/#{scheme.id}/locations/#{location.id}/edit-name" + get "/schemes/#{scheme.id}/locations/#{location.id}/availability" end - it "returns a template for a new location" do + it "returns a template for a startdate" do expect(response).to have_http_status(:ok) - expect(page).to have_content("Location name for #{location.postcode}") + expect(page).to have_content("When did the first property in this location become available under this scheme?") + end + + context "when startdate is submitted" do + let(:params) { { location: { "startdate(1i)": "2022", "startdate(2i)": "1", "startdate(3i)": "2" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/availability", params: + end + + it "adds startdate to location" do + expect(Location.last.startdate).to eq(Time.zone.local(2022, 1, 2)) + end + + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("Check your answers") + end + end + + context "when startdate is submitted with leading zeroes" do + let(:params) { { location: { "startdate(1i)": "2022", "startdate(2i)": "01", "startdate(3i)": "02" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/availability", params: + end + + it "adds startdate correctly " do + expect(Location.last.startdate).to eq(Time.zone.local(2022, 1, 2)) + end + + it "redirects correctly" do + follow_redirect! + expect(page).to have_content("Check your answers") + end + end + + context "when startdate is missing" do + let(:params) { { location: { "startdate(1i)": "", "startdate(2i)": "", "startdate(3i)": "" } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/availability", params: + end + + it "displays the new page with an error message" do + expect(response).to have_http_status(:unprocessable_entity) + expect(page).to have_content(I18n.t("validations.location.startdate_invalid")) + end end context "when the requested location does not exist" do - let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1) } + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } it "returns not found" do expect(response).to have_http_status(:not_found) @@ -1163,10 +1219,10 @@ RSpec.describe LocationsController, type: :request do end end - describe "#edit-local-authority" do + describe "#check_answers" do context "when not signed in" do it "redirects to the sign in page" do - get "/schemes/1/locations/1/edit-local-authority" + get "/schemes/1/locations/1/check-answers" expect(response).to redirect_to("/account/sign-in") end end @@ -1176,7 +1232,7 @@ RSpec.describe LocationsController, type: :request do before do sign_in user - get "/schemes/1/locations/1/edit-local-authority" + get "/schemes/1/locations/1/check-answers" end it "returns 401 unauthorized" do @@ -1188,24 +1244,42 @@ RSpec.describe LocationsController, type: :request do context "when signed in as a data coordinator" do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let!(:location) { FactoryBot.create(:location, scheme:) } + let!(:location) { FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2000, 1, 1)) } before do sign_in user - get "/schemes/#{scheme.id}/locations/#{location.id}/edit-local-authority" + get "/schemes/#{scheme.id}/locations/#{location.id}/check-answers" end - it "returns a template for an edit-local-authority" do + it "returns the check answers page" do expect(response).to have_http_status(:ok) - expect(page).to have_content("What is the local authority of #{location.postcode}?") + expect(page).to have_content("Check your answers") + end + + context "when location is confirmed" do + let(:params) { { location: { confirmed: true } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/confirm", params: + end + + it "confirms location" do + expect(Location.last.confirmed).to eq(true) + end + + it "redirects correctly and displays success banner" do + follow_redirect! + expect(page).to have_content("Success") + expect(page).to have_content("added to this scheme") + end end - context "when trying to edit location name of location that belongs to another organisation" do + context "when trying to edit check_answers of location that belongs to another organisation" do let(:another_scheme) { FactoryBot.create(:scheme) } let(:another_location) { FactoryBot.create(:location, scheme: another_scheme) } it "displays the new page with an error message" do - get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/edit-local-authority" + get "/schemes/#{another_scheme.id}/locations/#{another_location.id}/check-answers" expect(response).to have_http_status(:not_found) end end @@ -1214,21 +1288,39 @@ RSpec.describe LocationsController, type: :request do context "when signed in as a support user" do let(:user) { FactoryBot.create(:user, :support) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let!(:location) { FactoryBot.create(:location, scheme:) } + let!(:location) { FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2000, 1, 1)) } before do allow(user).to receive(:need_two_factor_authentication?).and_return(false) sign_in user - get "/schemes/#{scheme.id}/locations/#{location.id}/edit-local-authority" + get "/schemes/#{scheme.id}/locations/#{location.id}/check-answers" end - it "returns a template for a new location" do + it "returns the check answers page" do expect(response).to have_http_status(:ok) - expect(page).to have_content("What is the local authority of #{location.postcode}?") + expect(page).to have_content("Check your answers") + end + + context "when location is confirmed" do + let(:params) { { location: { confirmed: true } } } + + before do + patch "/schemes/#{scheme.id}/locations/#{location.id}/confirm", params: + end + + it "confirms location" do + expect(Location.last.confirmed).to eq(true) + end + + it "redirects correctly and displays success banner" do + follow_redirect! + expect(page).to have_content("Success") + expect(page).to have_content("added to this scheme") + end end context "when the requested location does not exist" do - let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1) } + let(:location) { OpenStruct.new(id: (Location.maximum(:id) || 0) + 1, scheme:) } it "returns not found" do expect(response).to have_http_status(:not_found) @@ -1262,7 +1354,7 @@ RSpec.describe LocationsController, type: :request do context "when signed in as a data coordinator" do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let!(:location) { FactoryBot.create(:location, scheme:, startdate: nil, created_at: Time.zone.local(2022, 4, 1)) } + let!(:location) { FactoryBot.create(:location, scheme:, created_at: Time.zone.local(2022, 4, 1)) } let(:deactivation_date) { Time.utc(2022, 10, 10) } let!(:lettings_log) { FactoryBot.create(:lettings_log, :sh, location:, scheme:, startdate:, owning_organisation: user.organisation) } let(:startdate) { Time.utc(2022, 10, 11) } @@ -1311,7 +1403,7 @@ RSpec.describe LocationsController, type: :request do context "with other date" do let(:params) { { location_deactivation_period: { deactivation_date_type: "other", "deactivation_date(3i)": "10", "deactivation_date(2i)": "10", "deactivation_date(1i)": "2022" } } } - context "and afected logs" do + context "and affected logs" do it "redirects to the confirmation page" do follow_redirect! expect(response).to have_http_status(:ok) @@ -1501,7 +1593,7 @@ RSpec.describe LocationsController, type: :request do context "when signed in as a data coordinator" do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let!(:location) { FactoryBot.create(:location, scheme:, startdate: nil) } + let!(:location) { FactoryBot.create(:location, scheme:) } let(:add_deactivations) { location.location_deactivation_periods << location_deactivation_period } before do @@ -1581,7 +1673,7 @@ RSpec.describe LocationsController, type: :request do context "when signed in as a data coordinator" do let(:user) { FactoryBot.create(:user, :data_coordinator) } let!(:scheme) { FactoryBot.create(:scheme, owning_organisation: user.organisation) } - let!(:location) { FactoryBot.create(:location, scheme:, startdate: nil) } + let!(:location) { FactoryBot.create(:location, scheme:) } let(:deactivation_date) { Time.zone.local(2022, 4, 1) } let(:startdate) { Time.utc(2022, 10, 11) } diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb index 3624313eb..5417e79f1 100644 --- a/spec/requests/schemes_controller_spec.rb +++ b/spec/requests/schemes_controller_spec.rb @@ -834,10 +834,10 @@ RSpec.describe SchemesController, type: :request do context "when updating support" do let(:params) { { scheme: { intended_stay: "Medium stay", support_type: "Low level", page: "support" } } } - it "renders add location to this scheme successful update" do + it "renders the check answers page" do follow_redirect! expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("Check your answers before creating this scheme") end it "updates a scheme with valid params" do @@ -1000,7 +1000,7 @@ RSpec.describe SchemesController, type: :request do expect(scheme_to_update.reload.confirmed?).to eq(true) end - it "marks all the scheme locations as confirmed" do + it "marks all the scheme locations as confirmed given they are complete" do expect(scheme_to_update.locations.count > 0).to eq(true) scheme_to_update.locations.each do |location| expect(location.confirmed?).to eq(true) @@ -1117,10 +1117,10 @@ RSpec.describe SchemesController, type: :request do context "when updating support" do let(:params) { { scheme: { intended_stay: "Medium stay", support_type: "Low level", page: "support" } } } - it "renders confirm secondary group after successful update" do + it "renders scheme check your answers page after successful update" do follow_redirect! expect(response).to have_http_status(:ok) - expect(page).to have_content("Add a location to this scheme") + expect(page).to have_content("Check your answers before creating this scheme") end it "updates a scheme with valid params" do