Browse Source

Cldc 1227 supported housing index (#648)

* Added test file for supported housing schemes

* Added factory bot for supported housing schemes

* swapped managing agent to org for scheme

* created migration for schemes

* created model for scheme

* added migration to add foreign key to the schemes table

* missing spec and log spec for supported housing

* fixed failing specs

* added schemes migration

* next step feature

* added route

* added controller

* added index

* added all schemes

* correct test for scheme

* added view

* route alias for schemes

* spec for index schemes

* failing scheme controller spec

* added simple view, scheme seed and authentication

* spec for index schemes list

* rubocop - thanks

* better seed

* added Heading to org

* added feature flag to hide supported services on prod

* added feature flag testing nav items

* testing coordinator user can see the link to supported housing

* moved toggle to a different place

* moved toggle to PrimaryNavigationComponent

* testing not being signed in on support pages

* testing showing search bar

* added search bar

* testing subset of schemes for coordinator user

* rubocop

* failing test for title in page

* code to expose title

* pagination with tests without searching

* partial for schemes

* scoping out all but support and coord users

* searching schemes code and test

* searching via code and org tests

* searching by org name tests

* searching by org name code

* search_by tests

* search_by code

* search_by woops must search by service

* searching schemes feature

* tests for data coordinator user

* redirect for data coordinator user

* testing org schemes for coordiantor user

* schemes in org controller for coordiantor user

* refactored specs moved into orgs what belongs there

* view for org schemes

* rubocop

* accebility field

* accebility field on org page

* correct return when on org schemes

* passing search test on the orgs page

* highlight nav tab

* navs helper done

* rubocop

* fixed failing tests for support user

* correct view

* how did I manage to delete this file?

* checking you cant access schems unathorized

* moved test

* renamed service name

* correct title for sup user schemes org

* testing not being able to view any other orgs supported housing for coordinator user

* Trigger WF

* last fix

* aded has many to org for schemes

* rubocop

Co-authored-by: Ted <ted.booton@madetech.com>
pull/654/head
J G 3 years ago committed by GitHub
parent
commit
402780c53f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      app/components/primary_navigation_component.rb
  2. 2
      app/components/search_component.rb
  3. 8
      app/controllers/organisations_controller.rb
  4. 26
      app/controllers/schemes_controller.rb
  5. 19
      app/helpers/navigation_items_helper.rb
  6. 1
      app/models/organisation.rb
  7. 7
      app/models/scheme.rb
  8. 22
      app/views/organisations/schemes.html.erb
  9. 39
      app/views/schemes/_scheme_list.html.erb
  10. 16
      app/views/schemes/index.html.erb
  11. 3
      config/routes.rb
  12. 11
      db/migrate/20220608144156_create_schemes.rb
  13. 16
      db/schema.rb
  14. 39
      db/seeds.rb
  15. 14
      spec/components/primary_navigation_component_spec.rb
  16. 8
      spec/factories/scheme.rb
  17. 78
      spec/features/schemes_spec.rb
  18. 82
      spec/helpers/navigation_items_helper_spec.rb
  19. 5
      spec/models/organisation_spec.rb
  20. 49
      spec/models/scheme_spec.rb
  21. 131
      spec/requests/organisations_controller_spec.rb
  22. 163
      spec/requests/schemes_controller_spec.rb

1
app/components/primary_navigation_component.rb

@ -3,6 +3,7 @@ class PrimaryNavigationComponent < ViewComponent::Base
def initialize(items:)
@items = items
Rails.env.production? ? @items = @items.reject { |nav_item| nav_item.text.include?("Supported housing") } : @items
super
end

2
app/components/search_component.rb

@ -13,6 +13,8 @@ class SearchComponent < ViewComponent::Base
request.path
elsif request.path.include?("organisations") && request.path.include?("logs")
request.path
elsif request.path.include?("organisations") && request.path.include?("supported-housing")
request.path
elsif request.path.include?("users")
user_path(current_user)
elsif request.path.include?("organisations")

8
app/controllers/organisations_controller.rb

@ -16,6 +16,14 @@ class OrganisationsController < ApplicationController
@total_count = all_organisations.size
end
def schemes
all_schemes = Scheme.where(organisation: @organisation)
@pagy, @schemes = pagy(filtered_collection(all_schemes, search_term))
@searched = search_term.presence
@total_count = all_schemes.size
end
def show
redirect_to details_organisation_path(@organisation)
end

26
app/controllers/schemes_controller.rb

@ -0,0 +1,26 @@
class SchemesController < ApplicationController
include Pagy::Backend
include Modules::SearchFilter
before_action :authenticate_user!
before_action :authenticate_scope!
def index
redirect_to supported_housing_organisation_path(current_user.organisation) unless current_user.support?
all_schemes = Scheme.all
@pagy, @schemes = pagy(filtered_collection(all_schemes, search_term))
@searched = search_term.presence
@total_count = all_schemes.size
end
private
def search_term
params["search"]
end
def authenticate_scope!
head :unauthorized and return unless current_user.data_coordinator? || current_user.support?
end
end

19
app/helpers/navigation_items_helper.rb

@ -7,6 +7,14 @@ module NavigationItemsHelper
NavigationItem.new("Organisations", organisations_path, organisations_current?(path)),
NavigationItem.new("Users", "/users", users_current?(path)),
NavigationItem.new("Logs", case_logs_path, logs_current?(path)),
NavigationItem.new("Supported housing", "/supported-housing", supported_housing_current?(path)),
]
elsif current_user.data_coordinator?
[
NavigationItem.new("Logs", case_logs_path, logs_current?(path)),
NavigationItem.new("Supported housing", "/supported-housing", subnav_supported_housing_path?(path)),
NavigationItem.new("Users", users_organisation_path(current_user.organisation), subnav_users_path?(path)),
NavigationItem.new("About your organisation", "/organisations/#{current_user.organisation.id}", subnav_details_path?(path)),
]
else
[
@ -20,6 +28,7 @@ module NavigationItemsHelper
def secondary_items(path, current_organisation_id)
[
NavigationItem.new("Logs", "/organisations/#{current_organisation_id}/logs", subnav_logs_path?(path)),
NavigationItem.new("Supported housing", "/organisations/#{current_organisation_id}/supported-housing", subnav_supported_housing_path?(path)),
NavigationItem.new("Users", "/organisations/#{current_organisation_id}/users", subnav_users_path?(path)),
NavigationItem.new("About this organisation", "/organisations/#{current_organisation_id}", subnav_details_path?(path)),
]
@ -35,8 +44,16 @@ private
path == "/users"
end
def supported_housing_current?(path)
path == "/supported-housing"
end
def organisations_current?(path)
path == "/organisations" || subnav_users_path?(path) || subnav_logs_path?(path) || subnav_details_path?(path)
path == "/organisations" || subnav_users_path?(path) || subnav_logs_path?(path) || subnav_details_path?(path) || subnav_supported_housing_path?(path)
end
def subnav_supported_housing_path?(path)
path.include?("/organisations") && path.include?("/supported-housing")
end
def subnav_users_path?(path)

1
app/models/organisation.rb

@ -4,6 +4,7 @@ class Organisation < ApplicationRecord
has_many :managed_case_logs, class_name: "CaseLog", foreign_key: "managing_organisation_id"
has_many :data_protection_confirmations
has_many :organisation_rent_periods
has_many :schemes
scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") }
scope :search_by, ->(param) { search_by_name(param) }

7
app/models/scheme.rb

@ -0,0 +1,7 @@
class Scheme < ApplicationRecord
belongs_to :organisation
scope :search_by_code, ->(code) { where("code ILIKE ?", "%#{code}%") }
scope :search_by_service_name, ->(name) { where("service_name ILIKE ?", "%#{name}%") }
scope :search_by, ->(param) { search_by_code(param).or(search_by_service_name(param)) }
end

22
app/views/organisations/schemes.html.erb

@ -0,0 +1,22 @@
<% item_label = format_label(@pagy.count, "scheme") %>
<% title = format_title(@searched, "Supported housing services", current_user, item_label, @pagy.count, @organisation.name) %>
<% content_for :title, title %>
<%= render partial: "organisations/headings", locals: current_user.support? ? { main: @organisation.name, sub: nil } : { main: "Supported housing services", sub: current_user.organisation.name } %>
<% if current_user.support? %>
<%= render SubNavigationComponent.new(
items: secondary_items(request.path, @organisation.id),
) %>
<% end %>
<h2 class="govuk-visually-hidden">Supported housing services</h2>
<%= render SearchComponent.new(current_user:, search_label: "Search by service name or code", value: @searched) %>
<hr class="govuk-section-break govuk-section-break--visible govuk-section-break--m">
<%= render partial: "schemes/scheme_list", locals: { schemes: @schemes, title:, pagy: @pagy, searched: @searched, item_label:, total_count: @total_count } %>
<%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "schemes" } %>

39
app/views/schemes/_scheme_list.html.erb

@ -0,0 +1,39 @@
<section class="app-table-group" tabindex="0" aria-labelledby="<%= title.dasherize %>">
<%= govuk_table do |table| %>
<%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %>
<span class="govuk-!-margin-right-4">
<% if searched.present? %>
<strong><%= pagy.count %></strong> <%= item_label %> found matching ‘<%= searched %>’ of <strong><%= total_count %></strong> total schemes. <%= govuk_link_to("Clear search", request.path) %>
<% else %>
<strong><%= pagy.count %></strong> total schemes.
<% end %>
</span>
<% end %>
<%= table.head do |head| %>
<%= head.row do |row| %>
<% row.cell(header: true, text: "Code", html_attributes: {
scope: "col",
}) %>
<% row.cell(header: true, text: "Service", html_attributes: {
scope: "col",
}) %>
<% row.cell(header: true, text: "Managing agent", html_attributes: {
scope: "col",
}) %>
<% row.cell(header: true, text: "Created", html_attributes: {
scope: "col",
}) %>
<% end %>
<% end %>
<% @schemes.each do |scheme| %>
<%= table.body do |body| %>
<%= body.row do |row| %>
<% row.cell(text: scheme.code) %>
<% row.cell(text: scheme.service_name) %>
<% row.cell(text: scheme.organisation.name) %>
<% row.cell(text: scheme.created_at.to_formatted_s(:govuk_date)) %>
<% end %>
<% end %>
<% end %>
<% end %>
</section>

16
app/views/schemes/index.html.erb

@ -0,0 +1,16 @@
<% item_label = format_label(@pagy.count, "scheme") %>
<% title = format_title(@searched, "Supported housing services", current_user, item_label, @pagy.count, nil) %>
<% content_for :title, title %>
<%= render partial: "organisations/headings", locals: current_user.support? ? { main: "Supported housing services", sub: nil } : { main: "Supported housing services", sub: current_user.organisation.name } %>
<h2 class="govuk-visually-hidden">Supported housing services</h2>
<%= render SearchComponent.new(current_user:, search_label: "Search by service name or code", value: @searched) %>
<hr class="govuk-section-break govuk-section-break--visible govuk-section-break--m">
<%= render partial: "schemes/scheme_list", locals: { schemes: @schemes, title:, pagy: @pagy, searched: @searched, item_label:, total_count: @total_count } %>
<%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "schemes" } %>

3
config/routes.rb

@ -35,6 +35,8 @@ Rails.application.routes.draw do
get "edit/password", to: "users#edit_password"
end
resources :schemes, path: "/supported-housing", only: [:index]
resources :users do
member do
get "deactivate", to: "users#deactivate"
@ -48,6 +50,7 @@ Rails.application.routes.draw do
get "users", to: "organisations#users"
get "users/invite", to: "users/account#new"
get "logs", to: "organisations#logs"
get "supported-housing", to: "organisations#schemes"
end
end

11
db/migrate/20220608144156_create_schemes.rb

@ -0,0 +1,11 @@
class CreateSchemes < ActiveRecord::Migration[7.0]
def change
create_table :schemes do |t|
t.string :code
t.string :service_name
t.references :organisation, null: false, foreign_key: true
t.timestamps
end
end
end

16
db/schema.rb

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2022_06_06_082639) do
ActiveRecord::Schema[7.0].define(version: 2022_06_08_144156) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -192,9 +192,9 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_06_082639) do
t.integer "joint"
t.bigint "created_by_id"
t.integer "illness_type_0"
t.integer "retirement_value_check"
t.integer "tshortfall_known"
t.integer "shelteredaccom"
t.integer "retirement_value_check"
t.integer "pregnancy_value_check"
t.index ["created_by_id"], name: "index_case_logs_on_created_by_id"
t.index ["managing_organisation_id"], name: "index_case_logs_on_managing_organisation_id"
@ -232,7 +232,7 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_06_082639) do
create_table "logs_exports", force: :cascade do |t|
t.datetime "created_at", default: -> { "CURRENT_TIMESTAMP" }
t.datetime "started_at", precision: nil, null: false
t.datetime "started_at", null: false
t.integer "base_number", default: 1, null: false
t.integer "increment_number", default: 1, null: false
t.boolean "empty_export", default: false, null: false
@ -277,6 +277,15 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_06_082639) do
t.index ["old_visible_id"], name: "index_organisations_on_old_visible_id", unique: true
end
create_table "schemes", force: :cascade do |t|
t.string "code"
t.string "service_name"
t.bigint "organisation_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["organisation_id"], name: "index_schemes_on_organisation_id"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
@ -330,4 +339,5 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_06_082639) do
t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
end
add_foreign_key "schemes", "organisations"
end

39
db/seeds.rb

@ -54,6 +54,45 @@ unless Rails.env.test?
pp "Seeded 3 dummy users"
end
if Rails.env.development?
dummy_org = Organisation.find_or_create_by!(
name: "FooBar LTD",
address_line1: "Higher Kingston",
address_line2: "Yeovil",
postcode: "BA21 4AT",
holds_own_stock: false,
other_stock_owners: "None",
managing_agents: "None",
provider_type: "LA",
)
pp "Seeded dummy FooBar LTD organisation"
end
if Rails.env.development? && Scheme.count.zero?
Scheme.create!(
code: "S878",
service_name: "Beulahside Care",
organisation: org,
created_at: Time.zone.now,
)
Scheme.create!(
code: "S312",
service_name: "Abdullahview Point",
organisation: org,
created_at: Time.zone.now,
)
Scheme.create!(
code: "7XYZ",
service_name: "Caspermouth Center",
organisation: dummy_org,
created_at: Time.zone.now,
)
end
pp "Seeded 3 dummy schemes"
if LaRentRange.count.zero?
Dir.glob("config/rent_range_data/*.csv").each do |path|
start_year = File.basename(path, ".csv")

14
spec/components/primary_navigation_component_spec.rb

@ -6,6 +6,7 @@ RSpec.describe PrimaryNavigationComponent, type: :component do
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", true),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs ", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
@ -24,6 +25,7 @@ RSpec.describe PrimaryNavigationComponent, type: :component do
expect(navigation_panel).to be_highlighted_item(items[0], "/something-else")
expect(navigation_panel).not_to be_highlighted_item(items[1], "/something-else")
expect(navigation_panel).not_to be_highlighted_item(items[2], "/something-else")
expect(navigation_panel).not_to be_highlighted_item(items[3], "/something-else")
end
end
@ -34,6 +36,18 @@ RSpec.describe PrimaryNavigationComponent, type: :component do
expect(result.text).to include("Organisations")
expect(result.text).to include("Users")
expect(result.text).to include("Logs")
expect(result.text).to include("Supported housing")
end
end
context "when production environment" do
before do
allow(Rails.env).to receive(:production?).and_return(true)
end
it "doesn't render supported housing" do
result = render_inline(described_class.new(items:))
expect(result.text).not_to include("Supported housing")
end
end
end

8
spec/factories/scheme.rb

@ -0,0 +1,8 @@
FactoryBot.define do
factory :scheme do
code { Faker::Name.initials(number: 4) }
service_name { Faker::Name.name_with_middle }
organisation
created_at { Time.zone.now }
end
end

78
spec/features/schemes_spec.rb

@ -0,0 +1,78 @@
require "rails_helper"
RSpec.describe "Supported housing scheme Features" do
context "when viewing list of schemes" do
context "when I am signed as a support user in there are schemes in the database" do
let(:user) { FactoryBot.create(:user, :support, last_sign_in_at: Time.zone.now) }
let!(:schemes) { FactoryBot.create_list(:scheme, 5) }
let!(:scheme_to_search) { FactoryBot.create(:scheme) }
let(:notify_client) { instance_double(Notifications::Client) }
let(:confirmation_token) { "MCDH5y6Km-U7CFPgAMVS" }
let(:devise_notify_mailer) { DeviseNotifyMailer.new }
let(:otp) { "999111" }
before do
allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer)
allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client)
allow(Devise).to receive(:friendly_token).and_return(confirmation_token)
allow(notify_client).to receive(:send_email).and_return(true)
allow(SecureRandom).to receive(:random_number).and_return(otp)
visit("/logs")
fill_in("user[email]", with: user.email)
fill_in("user[password]", with: user.password)
click_button("Sign in")
fill_in("code", with: otp)
click_button("Submit")
end
it "displays the link to the supported housing" do
expect(page).to have_link("Supported housing", href: "/supported-housing")
end
context "when I click Supported housing" do
before do
click_link "Supported housing", href: "/supported-housing"
end
it "shows list of schemes" do
schemes.each do |scheme|
expect(page).to have_content(scheme.code)
end
end
context "when I search for a specific scheme" do
it "there is a search bar with a message and search button for schemes" do
expect(page).to have_field("search")
expect(page).to have_content("Search by service name or code")
expect(page).to have_button("Search")
end
context "when I fill in search information and press the search button" do
before do
fill_in("search", with: scheme_to_search.code)
click_button("Search")
end
it "displays scheme matching the scheme code" do
expect(page).to have_content(scheme_to_search.code)
end
context "when I want to clear results" do
it "there is link to clear the search results" do
expect(page).to have_link("Clear search")
end
it "displays all schemes after I clear the search results" do
click_link("Clear search")
expect(page).to have_content(scheme_to_search.code)
schemes.each do |scheme|
expect(page).to have_content(scheme.code)
end
end
end
end
end
end
end
end
end

82
spec/helpers/navigation_items_helper_spec.rb

@ -8,10 +8,26 @@ RSpec.describe NavigationItemsHelper do
describe "#primary items" do
context "when the user is a data coordinator" do
context "when the user is on the logs page" do
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", true),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
NavigationItemsHelper::NavigationItem.new("Users", users_path, false),
NavigationItemsHelper::NavigationItem.new("About your organisation", organisation_path, false),
]
end
it "returns navigation items with the users item set as current" do
expect(primary_items("/logs", current_user)).to eq(expected_navigation_items)
end
end
context "when the user is on the users page" do
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
NavigationItemsHelper::NavigationItem.new("Users", users_path, true),
NavigationItemsHelper::NavigationItem.new("About your organisation", organisation_path, false),
]
@ -26,6 +42,7 @@ RSpec.describe NavigationItemsHelper do
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
NavigationItemsHelper::NavigationItem.new("Users", users_path, false),
NavigationItemsHelper::NavigationItem.new("About your organisation", organisation_path, true),
]
@ -40,6 +57,7 @@ RSpec.describe NavigationItemsHelper do
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
NavigationItemsHelper::NavigationItem.new("Users", "/organisations/#{current_user.organisation.id}/users", false),
NavigationItemsHelper::NavigationItem.new("About your organisation", organisation_path, false),
]
@ -54,12 +72,28 @@ RSpec.describe NavigationItemsHelper do
context "when the user is a support user" do
let(:current_user) { FactoryBot.create(:user, :support) }
context "when the user is on the logs page" do
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", false),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", true),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
it "returns navigation items with the users item set as current" do
expect(primary_items("/logs", current_user)).to eq(expected_navigation_items)
end
end
context "when the user is on the users page" do
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", false),
NavigationItemsHelper::NavigationItem.new("Users", "/users", true),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
@ -74,6 +108,7 @@ RSpec.describe NavigationItemsHelper do
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", false),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
@ -82,6 +117,21 @@ RSpec.describe NavigationItemsHelper do
end
end
context "when the user is on the supported housing page" do
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", false),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", true),
]
end
it "returns navigation items with the users item set as current" do
expect(primary_items("/supported-housing", current_user)).to eq(expected_navigation_items)
end
end
context "when the user is on the specific organisation's page" do
context "when the user is on organisation logs page" do
let(:required_sub_path) { "logs" }
@ -90,12 +140,14 @@ RSpec.describe NavigationItemsHelper do
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", true),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
let(:expected_secondary_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/organisations/#{current_user.organisation.id}/logs", true),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/organisations/#{current_user.organisation.id}/supported-housing", false),
NavigationItemsHelper::NavigationItem.new("Users", "/organisations/#{current_user.organisation.id}/users", false),
NavigationItemsHelper::NavigationItem.new("About this organisation", "/organisations/#{current_user.organisation.id}", false),
]
@ -114,12 +166,14 @@ RSpec.describe NavigationItemsHelper do
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", true),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
let(:expected_secondary_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/organisations/#{current_user.organisation.id}/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/organisations/#{current_user.organisation.id}/supported-housing", false),
NavigationItemsHelper::NavigationItem.new("Users", "/organisations/#{current_user.organisation.id}/users", true),
NavigationItemsHelper::NavigationItem.new("About this organisation", "/organisations/#{current_user.organisation.id}", false),
]
@ -131,6 +185,32 @@ RSpec.describe NavigationItemsHelper do
end
end
context "when the user is on organisation schemes page" do
let(:required_sub_path) { "supported-housing" }
let(:expected_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", true),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
let(:expected_secondary_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/organisations/#{current_user.organisation.id}/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/organisations/#{current_user.organisation.id}/supported-housing", true),
NavigationItemsHelper::NavigationItem.new("Users", "/organisations/#{current_user.organisation.id}/users", false),
NavigationItemsHelper::NavigationItem.new("About this organisation", "/organisations/#{current_user.organisation.id}", false),
]
end
it "returns navigation items with the schemes item set as current" do
expect(primary_items("/organisations/#{current_user.organisation.id}/#{required_sub_path}", current_user)).to eq(expected_navigation_items)
expect(secondary_items("/organisations/#{current_user.organisation.id}/#{required_sub_path}", current_user.organisation.id)).to eq(expected_secondary_navigation_items)
end
end
context "when the user is on organisation details page" do
let(:required_sub_path) { "details" }
let(:expected_navigation_items) do
@ -138,12 +218,14 @@ RSpec.describe NavigationItemsHelper do
NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", true),
NavigationItemsHelper::NavigationItem.new("Users", "/users", false),
NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false),
]
end
let(:expected_secondary_navigation_items) do
[
NavigationItemsHelper::NavigationItem.new("Logs", "/organisations/#{current_user.organisation.id}/logs", false),
NavigationItemsHelper::NavigationItem.new("Supported housing", "/organisations/#{current_user.organisation.id}/supported-housing", false),
NavigationItemsHelper::NavigationItem.new("Users", "/organisations/#{current_user.organisation.id}/users", false),
NavigationItemsHelper::NavigationItem.new("About this organisation", "/organisations/#{current_user.organisation.id}", true),
]

5
spec/models/organisation_spec.rb

@ -4,6 +4,7 @@ RSpec.describe Organisation, type: :model do
describe "#new" do
let(:user) { FactoryBot.create(:user) }
let!(:organisation) { user.organisation }
let!(:scheme) { FactoryBot.create(:scheme, organisation:) }
it "has expected fields" do
expect(organisation.attribute_names).to include("name", "phone", "provider_type")
@ -13,6 +14,10 @@ RSpec.describe Organisation, type: :model do
expect(organisation.users.first).to eq(user)
end
it "has schemes" do
expect(organisation.schemes.first).to eq(scheme)
end
it "validates provider_type presence" do
expect { FactoryBot.create(:organisation, provider_type: nil) }
.to raise_error(ActiveRecord::RecordInvalid, "Validation failed: Provider type can’t be blank")

49
spec/models/scheme_spec.rb

@ -0,0 +1,49 @@
require "rails_helper"
RSpec.describe Scheme, type: :model do
describe "#new" do
let(:scheme) { FactoryBot.create(:scheme) }
it "belongs to an organisation" do
expect(scheme.organisation).to be_a(Organisation)
end
describe "scopes" do
let!(:scheme_1) { FactoryBot.create(:scheme) }
let!(:scheme_2) { FactoryBot.create(:scheme) }
context "when searching by code" do
it "returns case insensitive matching records" do
expect(described_class.search_by_code(scheme_1.code.upcase).count).to eq(1)
expect(described_class.search_by_code(scheme_1.code.downcase).count).to eq(1)
expect(described_class.search_by_code(scheme_1.code.downcase).first.code).to eq(scheme_1.code)
expect(described_class.search_by_code(scheme_2.code.upcase).count).to eq(1)
expect(described_class.search_by_code(scheme_2.code.downcase).count).to eq(1)
expect(described_class.search_by_code(scheme_2.code.downcase).first.code).to eq(scheme_2.code)
end
end
context "when searching by service name" do
it "returns case insensitive matching records" do
expect(described_class.search_by_service_name(scheme_1.service_name.upcase).count).to eq(1)
expect(described_class.search_by_service_name(scheme_1.service_name.downcase).count).to eq(1)
expect(described_class.search_by_service_name(scheme_1.service_name.downcase).first.service_name).to eq(scheme_1.service_name)
expect(described_class.search_by_service_name(scheme_2.service_name.upcase).count).to eq(1)
expect(described_class.search_by_service_name(scheme_2.service_name.downcase).count).to eq(1)
expect(described_class.search_by_service_name(scheme_2.service_name.downcase).first.service_name).to eq(scheme_2.service_name)
end
end
context "when searching by all searchable field" do
it "returns case insensitive matching records" do
expect(described_class.search_by(scheme_1.code.upcase).count).to eq(1)
expect(described_class.search_by(scheme_1.code.downcase).count).to eq(1)
expect(described_class.search_by(scheme_1.code.downcase).first.code).to eq(scheme_1.code)
expect(described_class.search_by_service_name(scheme_2.service_name.upcase).count).to eq(1)
expect(described_class.search_by_service_name(scheme_2.service_name.downcase).count).to eq(1)
expect(described_class.search_by_service_name(scheme_2.service_name.downcase).first.service_name).to eq(scheme_2.service_name)
end
end
end
end
end

131
spec/requests/organisations_controller_spec.rb

@ -30,10 +30,141 @@ RSpec.describe OrganisationsController, type: :request do
get "/organisations", headers: headers, params: {}
expect(response).to redirect_to("/account/sign-in")
end
it "does not let you see supported housing list" do
get "/organisations/#{organisation.id}/supported-housing", headers: headers, params: {}
expect(response).to redirect_to("/account/sign-in")
end
end
end
context "when user is signed in" do
describe "#schemes" do
context "when support user" do
let(:user) { FactoryBot.create(:user, :support) }
let!(:schemes) { FactoryBot.create_list(:scheme, 5) }
let!(:same_org_scheme) { FactoryBot.create(:scheme, organisation: user.organisation) }
before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
sign_in user
get "/organisations/#{organisation.id}/supported-housing", headers:, params: {}
end
it "has page heading" do
expect(page).to have_content("Supported housing services")
end
it "shows a search bar" do
expect(page).to have_field("search", type: "search")
end
it "has hidden accebility field with description" do
expected_field = "<h2 class=\"govuk-visually-hidden\">Supported housing services</h2>"
expect(CGI.unescape_html(response.body)).to include(expected_field)
end
it "shows only schemes belonging to the same organisation" do
expect(page).to have_content(same_org_scheme.code)
schemes.each do |scheme|
expect(page).not_to have_content(scheme.code)
end
end
context "when searching" do
let!(:searched_scheme) { FactoryBot.create(:scheme, code: "CODE321", organisation: user.organisation) }
let(:search_param) { "CODE321" }
before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
get "/organisations/#{organisation.id}/supported-housing?search=#{search_param}"
end
it "returns matching results" do
expect(page).to have_content(searched_scheme.code)
schemes.each do |scheme|
expect(page).not_to have_content(scheme.code)
end
end
it "updates the table caption" do
expect(page).to have_content("1 scheme found matching ‘#{search_param}")
end
it "has search in the title" do
expect(page).to have_title("#{user.organisation.name} (1 scheme matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK")
end
end
end
context "when data coordinator user" do
let(:user) { FactoryBot.create(:user, :data_coordinator) }
let!(:schemes) { FactoryBot.create_list(:scheme, 5) }
let!(:same_org_scheme) { FactoryBot.create(:scheme, organisation: user.organisation) }
before do
sign_in user
get "/organisations/#{organisation.id}/supported-housing", headers:, params: {}
end
it "has page heading" do
expect(page).to have_content("Supported housing services")
end
it "shows a search bar" do
expect(page).to have_field("search", type: "search")
end
it "has hidden accebility field with description" do
expected_field = "<h2 class=\"govuk-visually-hidden\">Supported housing services</h2>"
expect(CGI.unescape_html(response.body)).to include(expected_field)
end
it "shows only schemes belonging to the same organisation" do
expect(page).to have_content(same_org_scheme.code)
schemes.each do |scheme|
expect(page).not_to have_content(scheme.code)
end
end
context "with schemes that are not in scope for the user, i.e. that they do not belong to" do
let!(:unauthorised_organisation) { FactoryBot.create(:organisation) }
before do
get "/organisations/#{unauthorised_organisation.id}/supported-housing", headers:, params: {}
end
it "returns not found 404 from org details route" do
expect(response).to have_http_status(:not_found)
end
end
context "when searching" do
let!(:searched_scheme) { FactoryBot.create(:scheme, code: "CODE321", organisation: user.organisation) }
let(:search_param) { "CODE321" }
before do
get "/organisations/#{organisation.id}/supported-housing?search=#{search_param}"
end
it "returns matching results" do
expect(page).to have_content(searched_scheme.code)
schemes.each do |scheme|
expect(page).not_to have_content(scheme.code)
end
end
it "updates the table caption" do
expect(page).to have_content("1 scheme found matching ‘#{search_param}")
end
it "has search in the title" do
expect(page).to have_title("Supported housing services (1 scheme matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK")
end
end
end
end
describe "#show" do
context "with an organisation that the user belongs to" do
before do

163
spec/requests/schemes_controller_spec.rb

@ -0,0 +1,163 @@
require "rails_helper"
RSpec.describe SchemesController, type: :request do
let(:organisation) { user.organisation }
let(:headers) { { "Accept" => "text/html" } }
let(:page) { Capybara::Node::Simple.new(response.body) }
let(:user) { FactoryBot.create(:user, :support) }
let!(:schemes) { FactoryBot.create_list(:scheme, 5) }
describe "#index" do
context "when not signed in" do
it "redirects to the sign in page" do
get "/supported-housing"
expect(response).to redirect_to("/account/sign-in")
end
end
context "when signed in as a data provider user" do
let(:user) { FactoryBot.create(:user) }
before do
sign_in user
get "/supported-housing"
end
it "returns 401 unauthorized" do
request
expect(response).to have_http_status(:unauthorized)
end
end
context "when signed in as a data coordinator user" do
let(:user) { FactoryBot.create(:user, :data_coordinator) }
before do
sign_in user
get "/supported-housing"
end
it "redirects to the organisation schemes path" do
follow_redirect!
expect(path).to match("/organisations/#{user.organisation.id}/supported-housing")
end
end
context "when signed in as a support user" do
before do
allow(user).to receive(:need_two_factor_authentication?).and_return(false)
sign_in user
get "/supported-housing"
end
it "has page heading" do
expect(page).to have_content("Supported housing services")
end
it "shows all schemes" do
schemes.each do |scheme|
expect(page).to have_content(scheme.code)
end
end
it "shows a search bar" do
expect(page).to have_field("search", type: "search")
end
it "has correct title" do
expect(page).to have_title("Supported housing services - Submit social housing lettings and sales data (CORE) - GOV.UK")
end
it "shows the total organisations count" do
expect(CGI.unescape_html(response.body)).to match("<strong>#{schemes.count}</strong> total schemes.")
end
it "has hidden accebility field with description" do
expected_field = "<h2 class=\"govuk-visually-hidden\">Supported housing services</h2>"
expect(CGI.unescape_html(response.body)).to include(expected_field)
end
context "when paginating over 20 results" do
let(:total_schemes_count) { Scheme.count }
before do
FactoryBot.create_list(:scheme, 20)
end
context "when on the first page" do
before do
get "/supported-housing"
end
it "shows the total schemes count" do
expect(CGI.unescape_html(response.body)).to match("<strong>#{total_schemes_count}</strong> total schemes.")
end
it "shows which schemes are being shown on the current page" do
expect(CGI.unescape_html(response.body)).to match("Showing <b>1</b> to <b>20</b> of <b>#{total_schemes_count}</b> schemes")
end
it "has correct page 1 of 2 title" do
expect(page).to have_title("Supported housing services (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK")
end
it "has pagination links" do
expect(page).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 "/supported-housing?page=2"
end
it "shows the total schemes count" do
expect(CGI.unescape_html(response.body)).to match("<strong>#{total_schemes_count}</strong> total schemes.")
end
it "has pagination links" do
expect(page).to have_content("Previous")
expect(page).to have_link("Previous")
expect(page).to have_content("Next")
expect(page).not_to have_link("Next")
end
it "shows which schemes are being shown on the current page" do
expect(CGI.unescape_html(response.body)).to match("Showing <b>21</b> to <b>25</b> of <b>#{total_schemes_count}</b> schemes")
end
it "has correct page 1 of 2 title" do
expect(page).to have_title("Supported housing services (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK")
end
end
end
context "when searching" do
let!(:searched_scheme) { FactoryBot.create(:scheme, code: "CODE321") }
let(:search_param) { "CODE321" }
before do
get "/supported-housing?search=#{search_param}"
end
it "returns matching results" do
expect(page).to have_content(searched_scheme.code)
schemes.each do |scheme|
expect(page).not_to have_content(scheme.code)
end
end
it "updates the table caption" do
expect(page).to have_content("1 scheme found matching ‘#{search_param}")
end
it "has search in the title" do
expect(page).to have_title("Supported housing services (1 scheme matching ‘#{search_param}’) - Submit social housing lettings and sales data (CORE) - GOV.UK")
end
end
end
end
end
Loading…
Cancel
Save