From 88455ea26a51e4e38c07e01041b1f64c99423c83 Mon Sep 17 00:00:00 2001 From: Ted-U <92022120+Ted-U@users.noreply.github.com> Date: Mon, 23 May 2022 15:37:53 +0100 Subject: [PATCH] Cldc 1102 admin organisations page (#557) * Get all organisations in controller * Display organisations data in the table * Route to logs for specific organisation * add tests * update spec * lint fixes * set up failing test for organisation logs page * fix failing test * write test for organisations support user page * Update a organisation page test and lint * added pagination test with next and previous links and total count for support user * test for pagination in organisations title * Added "Organisations" to to organisations page title * add pagination test for organisations page 2, remove second before block * Add the remaining pagination tests * Redirect when accessing organisation logs by non support user * Test for displaying logs for specific organisation * Add test for org name * Add a failing log filter test for specific org * Extract filter methods into a helper * Allow logs filtering for specific org * Fix test, support user was creating an extra org, remove orgs filter for specific org * Remove redundant test, lint * Reuse primary navigation component and add sub navigation for support users * allow support users edit or and add sub navigation to about this org * allow support users to access the edit org page * only allow to edit existing editable fields * display correct values in the organisations table * allow support user to update org * user table component for organisations table * use guard clause for organisation logs page * remove create a new lettings log from organisation logs * Move case logs filter from helpers to modules * lint erb * yarn lint * bring back if statement in logs controller * update modules import * let! * test for links first in the org cotroller spec * interpolate number of orgs * conditionally render sub navigation Co-authored-by: Kat Co-authored-by: Dushan Despotovic Co-authored-by: JG --- app/components/navigation_component.html.erb | 17 ++ app/components/navigation_component.rb | 13 ++ .../primary_navigation_component.html.erb | 17 -- .../primary_navigation_component.rb | 12 - app/controllers/case_logs_controller.rb | 28 +-- app/controllers/modules/case_logs_filter.rb | 23 ++ app/controllers/organisations_controller.rb | 18 +- app/frontend/styles/_primary-navigation.scss | 29 ++- app/helpers/navigation_items_helper.rb | 17 +- app/helpers/organisation_helper.rb | 16 ++ app/models/user.rb | 4 +- app/views/case_logs/_log_filters.erb | 4 +- app/views/layouts/application.html.erb | 3 +- app/views/layouts/organisations.html.erb | 2 +- .../organisations/_organisation_list.html.erb | 27 +++ app/views/organisations/index.html.erb | 3 +- app/views/organisations/logs.erb | 22 ++ app/views/organisations/show.html.erb | 9 + config/routes.rb | 1 + .../primary_navigation_component_spec.rb | 2 +- spec/features/organisation_spec.rb | 31 +++ .../requests/organisations_controller_spec.rb | 206 ++++++++++++++++-- 22 files changed, 417 insertions(+), 87 deletions(-) create mode 100644 app/components/navigation_component.html.erb create mode 100644 app/components/navigation_component.rb delete mode 100644 app/components/primary_navigation_component.html.erb delete mode 100644 app/components/primary_navigation_component.rb create mode 100644 app/controllers/modules/case_logs_filter.rb create mode 100644 app/helpers/organisation_helper.rb create mode 100644 app/views/organisations/_organisation_list.html.erb create mode 100644 app/views/organisations/logs.erb diff --git a/app/components/navigation_component.html.erb b/app/components/navigation_component.html.erb new file mode 100644 index 000000000..3d192ef2b --- /dev/null +++ b/app/components/navigation_component.html.erb @@ -0,0 +1,17 @@ + diff --git a/app/components/navigation_component.rb b/app/components/navigation_component.rb new file mode 100644 index 000000000..e386e429f --- /dev/null +++ b/app/components/navigation_component.rb @@ -0,0 +1,13 @@ +class NavigationComponent < ViewComponent::Base + attr_reader :items, :level + + def initialize(items:, level: "primary") + @items = items + @level = level + super + end + + def highlighted_tab?(item, _path) + item[:current] + end +end diff --git a/app/components/primary_navigation_component.html.erb b/app/components/primary_navigation_component.html.erb deleted file mode 100644 index 9cad3bc64..000000000 --- a/app/components/primary_navigation_component.html.erb +++ /dev/null @@ -1,17 +0,0 @@ - diff --git a/app/components/primary_navigation_component.rb b/app/components/primary_navigation_component.rb deleted file mode 100644 index f9668f812..000000000 --- a/app/components/primary_navigation_component.rb +++ /dev/null @@ -1,12 +0,0 @@ -class PrimaryNavigationComponent < ViewComponent::Base - attr_reader :items - - def initialize(items:) - @items = items - super - end - - def highlighted_tab?(item, _path) - item[:current] - end -end diff --git a/app/controllers/case_logs_controller.rb b/app/controllers/case_logs_controller.rb index a80705962..1217585f0 100644 --- a/app/controllers/case_logs_controller.rb +++ b/app/controllers/case_logs_controller.rb @@ -1,5 +1,6 @@ class CaseLogsController < ApplicationController include Pagy::Backend + include Modules::CaseLogsFilter skip_before_action :verify_authenticity_token, if: :json_api_request? before_action :authenticate, if: :json_api_request? @@ -9,12 +10,12 @@ class CaseLogsController < ApplicationController def index set_session_filters - @pagy, @case_logs = pagy(filtered_case_logs) + @pagy, @case_logs = pagy(filtered_case_logs(current_user.case_logs)) respond_to do |format| format.html format.csv do - send_data filtered_case_logs.to_csv, filename: "logs-#{Time.zone.now}.csv" + send_data filtered_case_logs(current_user.case_logs).to_csv, filename: "logs-#{Time.zone.now}.csv" end end end @@ -120,27 +121,4 @@ private def find_resource @case_log = CaseLog.find_by(id: params[:id]) end - - def filtered_case_logs - query = current_user.case_logs - if session[:case_logs_filters].present? - filters = JSON.parse(session[:case_logs_filters]) - filters.each do |category, values| - next if Array(values).reject(&:empty?).blank? - next if category == "organisation" && params["organisation_select"] == "all" - - query = query.public_send("filter_by_#{category}", values, current_user) - end - end - query = query.order(created_at: :desc) - current_user.support? ? query.all.includes(:owning_organisation, :managing_organisation) : query - end - - def set_session_filters - new_filters = session[:case_logs_filters].present? ? JSON.parse(session[:case_logs_filters]) : {} - current_user.case_logs_filters.each { |filter| new_filters[filter] = params[filter] if params[filter].present? } - new_filters = new_filters.except("organisation") if params["organisation_select"] == "all" - - session[:case_logs_filters] = new_filters.to_json - end end diff --git a/app/controllers/modules/case_logs_filter.rb b/app/controllers/modules/case_logs_filter.rb new file mode 100644 index 000000000..52a79bac9 --- /dev/null +++ b/app/controllers/modules/case_logs_filter.rb @@ -0,0 +1,23 @@ +module Modules::CaseLogsFilter + def filtered_case_logs(logs) + if session[:case_logs_filters].present? + filters = JSON.parse(session[:case_logs_filters]) + filters.each do |category, values| + next if Array(values).reject(&:empty?).blank? + next if category == "organisation" && params["organisation_select"] == "all" + + logs = logs.public_send("filter_by_#{category}", values, current_user) + end + end + logs = logs.order(created_at: :desc) + current_user.support? ? logs.all.includes(:owning_organisation, :managing_organisation) : logs + end + + def set_session_filters(specific_org: false) + new_filters = session[:case_logs_filters].present? ? JSON.parse(session[:case_logs_filters]) : {} + current_user.case_logs_filters(specific_org:).each { |filter| new_filters[filter] = params[filter] if params[filter].present? } + new_filters = new_filters.except("organisation") if params["organisation_select"] == "all" + + session[:case_logs_filters] = new_filters.to_json + end +end diff --git a/app/controllers/organisations_controller.rb b/app/controllers/organisations_controller.rb index 9401fae3a..8468a3f9f 100644 --- a/app/controllers/organisations_controller.rb +++ b/app/controllers/organisations_controller.rb @@ -1,5 +1,7 @@ class OrganisationsController < ApplicationController include Pagy::Backend + include Modules::CaseLogsFilter + before_action :authenticate_user!, except: [:index] before_action :find_resource, except: [:index] before_action :authenticate_scope! @@ -24,7 +26,7 @@ class OrganisationsController < ApplicationController end def edit - if current_user.data_coordinator? + if current_user.data_coordinator? || current_user.support? render "edit", layout: "application" else head :unauthorized @@ -32,7 +34,7 @@ class OrganisationsController < ApplicationController end def update - if current_user.data_coordinator? + if current_user.data_coordinator? || current_user.support? if @organisation.update(org_params) flash[:notice] = I18n.t("organisation.updated") redirect_to details_organisation_path(@organisation) @@ -42,6 +44,18 @@ class OrganisationsController < ApplicationController end end + def logs + if current_user.support? + set_session_filters(specific_org: true) + + organisation_logs = CaseLog.all.where(owning_organisation_id: @organisation.id) + @pagy, @case_logs = pagy(filtered_case_logs(organisation_logs)) + render "logs", layout: "application" + else + redirect_to(case_logs_path) + end + end + private def org_params diff --git a/app/frontend/styles/_primary-navigation.scss b/app/frontend/styles/_primary-navigation.scss index e6597ea2b..7409962ea 100644 --- a/app/frontend/styles/_primary-navigation.scss +++ b/app/frontend/styles/_primary-navigation.scss @@ -1,14 +1,20 @@ -.app-primary-navigation { +.app-primary-navigation, +.app-sub-navigation { @include govuk-font(19, $weight: bold); - background-color: govuk-colour("light-grey"); border-bottom: 1px solid $govuk-border-colour; } -.govuk-phase-banner + .app-primary-navigation { +.app-primary-navigation { + background-color: govuk-colour("light-grey"); +} + +.govuk-phase-banner + .app-primary-navigation, +.app-sub-navigation { margin-top: -1px; } -.app-primary-navigation__list { +.app-primary-navigation__list, +.app-sub-navigation__list { @include govuk-clearfix; left: govuk-spacing(-3); list-style: none; @@ -19,7 +25,8 @@ width: calc(100% + #{govuk-spacing(6)}); } -.app-primary-navigation__item { +.app-primary-navigation__item, +.app-sub-navigation__item { box-sizing: border-box; display: block; float: left; @@ -29,7 +36,8 @@ position: relative; } -.app-primary-navigation__item--current { +.app-primary-navigation__item--current, +.app-sub-navigation__item--current { border-bottom: $govuk-border-width-narrow solid $govuk-link-colour; &:hover { @@ -41,13 +49,15 @@ } } -.app-primary-navigation__item--align-right { +.app-primary-navigation__item--align-right, +.app-sub-navigation__item--align-right { @include govuk-media-query($from: tablet) { float: right; } } -.app-primary-navigation__link { +.app-primary-navigation__link, +.app-sub-navigation__link { @include govuk-link-common; @include govuk-link-style-no-visited-state; @include govuk-link-style-no-underline; @@ -64,6 +74,7 @@ } } -.app-primary-navigation__item--current .app-primary-navigation__link:hover { +.app-primary-navigation__item--current .app-primary-navigation__link:hover, +.app-sub-navigation__item--current .app-sub-navigation__link:hover { text-decoration: none; } diff --git a/app/helpers/navigation_items_helper.rb b/app/helpers/navigation_items_helper.rb index 970f89993..0115d6a24 100644 --- a/app/helpers/navigation_items_helper.rb +++ b/app/helpers/navigation_items_helper.rb @@ -17,10 +17,17 @@ module NavigationItemsHelper end end + def secondary_items(path, current_organisation_id) + [ + NavigationItem.new("Logs", "/organisations/#{current_organisation_id}/logs", organisation_logs_current?(path, current_organisation_id)), + NavigationItem.new("About this organisation", "/organisations/#{current_organisation_id}", about_organisation_current?(path, current_organisation_id)), + ] + end + private def logs_current?(path) - path.include?("/logs") + path == "/logs" end def users_current?(path) @@ -30,4 +37,12 @@ private def organisation_current?(path) path.include?("/organisations") && !path.include?("/users") end + + def about_organisation_current?(path, organisation_id) + path.include?("/organisations/#{organisation_id}/details") || path.include?("/organisations/#{organisation_id}/edit") + end + + def organisation_logs_current?(path, organisation_id) + path == "/organisations/#{organisation_id}/logs" + end end diff --git a/app/helpers/organisation_helper.rb b/app/helpers/organisation_helper.rb new file mode 100644 index 000000000..c600f61da --- /dev/null +++ b/app/helpers/organisation_helper.rb @@ -0,0 +1,16 @@ +module OrganisationHelper + def organisation_header(path, user, current_organisation) + if path == "/organisations" + "Organisations" + elsif user.organisation_id == current_organisation.id + "Your organisation" + else + current_organisation.name + end + end + + DISPLAY_PROVIDER_TYPE = { "LA": "Local authority", "PRP": "Private registered provider" }.freeze + def display_provider_type(provider_type) + DISPLAY_PROVIDER_TYPE[provider_type.to_sym] + end +end diff --git a/app/models/user.rb b/app/models/user.rb index efbe21b0e..f32096ad6 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -108,8 +108,8 @@ class User < ApplicationRecord ROLES.except(:support) end - def case_logs_filters - if support? + def case_logs_filters(specific_org: false) + if support? && !specific_org %w[status years user organisation] else %w[status years user] diff --git a/app/views/case_logs/_log_filters.erb b/app/views/case_logs/_log_filters.erb index 45354fb40..b0f3e07be 100644 --- a/app/views/case_logs/_log_filters.erb +++ b/app/views/case_logs/_log_filters.erb @@ -4,13 +4,13 @@

Filters

- <%= form_with url: "/logs", html: { method: :get } do |f| %> + <%= form_with html: { method: :get } do |f| %> <% years = {"2021": "2021/22", "2022": "2022/23"} %> <% all_or_yours = {"all": { label: "All" }, "yours": { label: "Yours" } } %> <%= render partial: "filters/checkbox_filter", locals: { f: f, options: years, label: "Collection year", category: "years" } %> <%= render partial: "filters/checkbox_filter", locals: { f: f, options: status_filters, label: "Status", category: "status" } %> <%= render partial: "filters/radio_filter", locals: { f: f, options: all_or_yours, label: "Logs", category: "user", } %> - <% if @current_user.support? %> + <% if @current_user.support? && request.path == "/logs" %> <%= render partial: "filters/radio_filter", locals: { f: f, options: { diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 7a3e85d89..d1a2c0dd6 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -65,8 +65,9 @@ ) %> <% if !current_user.nil? %> - <%= render PrimaryNavigationComponent.new( + <%= render NavigationComponent.new( items: primary_items(request.path, current_user), + level: "primary", ) %> <% end %> diff --git a/app/views/layouts/organisations.html.erb b/app/views/layouts/organisations.html.erb index e258aa2aa..0feff9918 100644 --- a/app/views/layouts/organisations.html.erb +++ b/app/views/layouts/organisations.html.erb @@ -1,6 +1,6 @@ <% content_for :content do %>

- Your organisation + <%= organisation_header(request.path, current_user, @organisation) %>

<% items = tab_items(current_user) %> diff --git a/app/views/organisations/_organisation_list.html.erb b/app/views/organisations/_organisation_list.html.erb new file mode 100644 index 000000000..8e6e443b1 --- /dev/null +++ b/app/views/organisations/_organisation_list.html.erb @@ -0,0 +1,27 @@ +<% content_for :title, title %> + +<%= govuk_table do |table| %> + <%= table.caption(size: "s", classes: %w[govuk-!-text-align-left govuk-!-margin-top-4 govuk-!-margin-bottom-4]) do |caption| %> + + <%= @pagy.count %> total <%= title.downcase %> + + <% end %> + <%= table.head do |head| %> + <%= head.row do |row| %> + <% row.cell(header: true, text: "Name") %> + <% row.cell(header: true, text: "Registration number") %> + <% row.cell(header: true, text: "Type") %> + <% end %> + <% end %> + <% @organisations.each do |organisation| %> + <%= table.body do |body| %> + <%= body.row do |row| %> + <% row.cell do %> + <%= govuk_link_to(organisation.name, "organisations/#{organisation.id}/logs", class: "govuk-!-font-weight-bold") %> + <% end %> + <% row.cell(text: organisation.housing_registration_no) %> + <% row.cell(text: display_provider_type(organisation.provider_type)) %> + <% end %> + <% end %> + <% end %> +<% end %> diff --git a/app/views/organisations/index.html.erb b/app/views/organisations/index.html.erb index 8b1378917..3fe0ab053 100644 --- a/app/views/organisations/index.html.erb +++ b/app/views/organisations/index.html.erb @@ -1 +1,2 @@ - +<%= render partial: "organisation_list", locals: { organisations: @organisations, title: "Organisations", pagy: @pagy } %> +<%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "organisations" } %> diff --git a/app/views/organisations/logs.erb b/app/views/organisations/logs.erb new file mode 100644 index 000000000..cb72cd15d --- /dev/null +++ b/app/views/organisations/logs.erb @@ -0,0 +1,22 @@ +<% content_for :title, "Logs" %> + +

+ <%= @organisation.name %> + <%= content_for(:title) %> +

+
+ <%= render NavigationComponent.new( + items: secondary_items(request.path, @organisation.id), + level: "sub" + ) %> +
+
+ + <%= render partial: "case_logs/log_filters" %> + <% if @case_logs.present? %> +
+ <%= render partial: "case_logs/log_list", locals: { case_logs: @case_logs, title: "Logs", pagy: @pagy } %> + <%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "logs" } %> +
+ <% end %> +
diff --git a/app/views/organisations/show.html.erb b/app/views/organisations/show.html.erb index 50eb5d5fc..dae556d97 100644 --- a/app/views/organisations/show.html.erb +++ b/app/views/organisations/show.html.erb @@ -5,6 +5,15 @@ <% end %>
+ +<% if current_user.support? %> +
+ <%= render NavigationComponent.new( + items: secondary_items(request.path, @organisation.id), + level: "sub", + ) %> +
+<% end %>
<%= govuk_summary_list do |summary_list| %> <% @organisation.display_attributes.each do |attr| %> diff --git a/config/routes.rb b/config/routes.rb index f8269ed12..33c9f0a9a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -67,6 +67,7 @@ Rails.application.routes.draw do get "details", to: "organisations#details" get "users", to: "organisations#users" get "users/invite", to: "users/account#new" + get "logs", to: "organisations#logs" end end diff --git a/spec/components/primary_navigation_component_spec.rb b/spec/components/primary_navigation_component_spec.rb index 46f45166d..e37f8320b 100644 --- a/spec/components/primary_navigation_component_spec.rb +++ b/spec/components/primary_navigation_component_spec.rb @@ -1,6 +1,6 @@ require "rails_helper" -RSpec.describe PrimaryNavigationComponent, type: :component do +RSpec.describe NavigationComponent, type: :component do let(:items) do [ NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", true), diff --git a/spec/features/organisation_spec.rb b/spec/features/organisation_spec.rb index ef54ff2a2..75277a28a 100644 --- a/spec/features/organisation_spec.rb +++ b/spec/features/organisation_spec.rb @@ -80,4 +80,35 @@ RSpec.describe "User Features" do end end end + + context "when user is support user" do + context "when viewing logs for specific organisation" do + let(:user) { FactoryBot.create(:user, :support) } + let(:number_of_case_logs) { 4 } + let(:first_log) { organisation.case_logs.first } + let(:otp) { "999111" } + + before do + FactoryBot.create_list(:case_log, number_of_case_logs, owning_organisation_id: organisation.id, managing_organisation_id: organisation.id) + first_log.update!(startdate: Time.utc(2022, 6, 2, 10, 36, 49)) + allow(SecureRandom).to receive(:random_number).and_return(otp) + click_link("Sign out") + sign_in user + fill_in("code", with: otp) + click_button("Submit") + visit("/organisations/#{org_id}/logs") + end + + it "can filter case logs" do + expect(page).to have_content("#{number_of_case_logs} total logs") + organisation.case_logs.map(&:id).each do |case_log_id| + expect(page).to have_link case_log_id.to_s, href: "/logs/#{case_log_id}" + end + check("years-2021-field") + click_button("Apply filters") + expect(page).to have_current_path("/organisations/#{org_id}/logs?years[]=&years[]=2021&status[]=&user=all") + expect(page).not_to have_link first_log.id.to_s, href: "/logs/#{first_log.id}" + end + end + end end diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb index f9e164b38..342c6f36c 100644 --- a/spec/requests/organisations_controller_spec.rb +++ b/spec/requests/organisations_controller_spec.rb @@ -2,7 +2,7 @@ require "rails_helper" RSpec.describe OrganisationsController, type: :request do let(:organisation) { user.organisation } - let(:unauthorised_organisation) { FactoryBot.create(:organisation) } + let!(:unauthorised_organisation) { FactoryBot.create(:organisation) } let(:headers) { { "Accept" => "text/html" } } let(:page) { Capybara::Node::Simple.new(response.body) } let(:user) { FactoryBot.create(:user, :data_coordinator) } @@ -58,10 +58,13 @@ RSpec.describe OrganisationsController, type: :request do end context "with a data coordinator user" do + before do + sign_in user + end + context "when we access the details tab" do context "with an organisation that the user belongs to" do before do - sign_in user get "/organisations/#{organisation.id}/details", headers:, params: {} end @@ -89,7 +92,6 @@ RSpec.describe OrganisationsController, type: :request do context "with organisation that are not in scope for the user, i.e. that they do not belong to" do before do - sign_in user get "/organisations/#{unauthorised_organisation.id}/details", headers:, params: {} end @@ -106,7 +108,6 @@ RSpec.describe OrganisationsController, type: :request do let!(:other_org_user) { FactoryBot.create(:user, name: "User 4") } before do - sign_in user get "/organisations/#{organisation.id}/users", headers:, params: {} end @@ -144,7 +145,6 @@ RSpec.describe OrganisationsController, type: :request do context "with an organisation that are not in scope for the user, i.e. that they do not belong to" do before do - sign_in user get "/organisations/#{unauthorised_organisation.id}/users", headers:, params: {} end @@ -157,7 +157,6 @@ RSpec.describe OrganisationsController, type: :request do describe "#edit" do context "with an organisation that the user belongs to" do before do - sign_in user get "/organisations/#{organisation.id}/edit", headers:, params: {} end @@ -170,20 +169,22 @@ RSpec.describe OrganisationsController, type: :request do context "with an organisation that the user does not belong to" do before do - sign_in user get "/organisations/#{unauthorised_organisation.id}/edit", headers:, params: {} end it "returns a 404 not found" do expect(response).to have_http_status(:not_found) end + + it "shows the 404 view" do + expect(page).to have_content("Page not found") + end end end describe "#update" do context "with an organisation that the user belongs to" do before do - sign_in user patch "/organisations/#{organisation.id}", headers:, params: end @@ -211,7 +212,6 @@ RSpec.describe OrganisationsController, type: :request do context "with an organisation that the user does not belong to" do before do - sign_in user patch "/organisations/#{unauthorised_organisation.id}", headers:, params: {} end @@ -220,15 +220,42 @@ RSpec.describe OrganisationsController, type: :request do end end end + + context "when viewing logs for other organisation" do + before do + get "/organisations/#{unauthorised_organisation.id}/logs", headers:, params: {} + end + + it "returns not found 404 from org details route" do + expect(response).to have_http_status(:not_found) + end + + it "shows the 404 view" do + expect(page).to have_content("Page not found") + end + end + + context "when viewing logs for your organisation" do + before do + get "/organisations/#{organisation.id}/logs", headers:, params: {} + end + + it "redirects to /logs page" do + expect(response).to redirect_to("/logs") + end + end end context "with a data provider user" do let(:user) { FactoryBot.create(:user) } + before do + sign_in user + end + context "when accessing the details tab" do context "with an organisation that the user belongs to" do before do - sign_in user get "/organisations/#{organisation.id}/details", headers:, params: {} end @@ -268,7 +295,6 @@ RSpec.describe OrganisationsController, type: :request do context "when accessing the users tab" do before do - sign_in user get "/organisations/#{organisation.id}/users", headers:, params: {} end @@ -279,7 +305,6 @@ RSpec.describe OrganisationsController, type: :request do describe "#edit" do before do - sign_in user get "/organisations/#{organisation.id}/edit", headers:, params: {} end @@ -290,7 +315,6 @@ RSpec.describe OrganisationsController, type: :request do describe "#update" do before do - sign_in user patch "/organisations/#{organisation.id}", headers:, params: end @@ -298,6 +322,162 @@ RSpec.describe OrganisationsController, type: :request do expect(response).to have_http_status(:unauthorized) end end + + context "when viewing logs for other organisation" do + before do + get "/organisations/#{unauthorised_organisation.id}/logs", headers:, params: {} + end + + it "returns not found 404 from org details route" do + expect(response).to have_http_status(:not_found) + end + + it "shows the 404 view" do + expect(page).to have_content("Page not found") + end + end + + context "when viewing logs for your organisation" do + before do + get "/organisations/#{organisation.id}/logs", headers:, params: {} + end + + it "redirects to /logs page" do + expect(response).to redirect_to("/logs") + end + end + end + + context "with a support user" do + let(:user) { FactoryBot.create(:user, :support) } + + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + get "/organisations" + end + + it "shows all organisations" do + total_number_of_orgs = Organisation.all.count + expect(page).to have_link organisation.name, href: "organisations/#{organisation.id}/logs" + expect(page).to have_link unauthorised_organisation.name, href: "organisations/#{unauthorised_organisation.id}/logs" + expect(page).to have_content("#{total_number_of_orgs} total organisations") + end + + context "when viewing a specific organisation" do + let(:number_of_org1_case_logs) { 2 } + let(:number_of_org2_case_logs) { 4 } + + before do + FactoryBot.create_list(:case_log, number_of_org1_case_logs, owning_organisation_id: organisation.id, managing_organisation_id: organisation.id) + FactoryBot.create_list(:case_log, number_of_org2_case_logs, owning_organisation_id: unauthorised_organisation.id, managing_organisation_id: unauthorised_organisation.id) + + get "/organisations/#{organisation.id}/logs", headers:, params: {} + end + + it "displays the name of the organisation in the header" do + expect(CGI.unescape_html(response.body)).to match("#{organisation.name}") + end + + it "only shows logs for that organisation" do + expect(page).to have_content("#{number_of_org1_case_logs} total logs") + organisation.case_logs.map(&:id).each do |case_log_id| + expect(page).to have_link case_log_id.to_s, href: "/logs/#{case_log_id}" + end + + unauthorised_organisation.case_logs.map(&:id).each do |case_log_id| + expect(page).not_to have_link case_log_id.to_s, href: "/logs/#{case_log_id}" + end + end + + it "has filters" do + expect(page).to have_content("Filters") + expect(page).to have_content("Collection year") + end + + it "does not have specific organisation filter" do + expect(page).not_to have_content("Specific organisation") + end + + it "has a sub-navigation with correct tabs" do + expect(page).to have_css(".app-sub-navigation") + expect(page).to have_content("About this organisation") + end + end + + context "when viewing a specific organisation details" do + before do + get "/organisations/#{organisation.id}/details", headers:, params: {} + end + + it "displays the name of the organisation" do + expect(page).to have_content(organisation.name) + end + + it "has a sub-navigation with correct tabs" do + expect(page).to have_css(".app-sub-navigation") + expect(page).to have_content("About this organisation") + end + + it "allows to edit the organisation details" do + expect(page).to have_link("Change", count: 3) + end + end + end + + context "when there are more than 20 organisations" do + let(:support_user) { FactoryBot.create(:user, :support) } + + let(:total_organisations_count) { Organisation.all.count } + + before do + FactoryBot.create_list(:organisation, 25) + allow(support_user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in support_user + get "/organisations" + end + + context "when on the first page" do + 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 + + it "shows which organisations are being shown on the current page" do + expect(CGI.unescape_html(response.body)).to match("Showing 1 to 20 of #{total_organisations_count} organisations") + end + + it "has pagination in the title" do + expect(page).to have_title("Organisations (page 1 of 2)") + end + end + + context "when on the second page" do + before do + get "/organisations?page=2", headers:, params: {} + end + + it "shows the total organisations count" do + expect(CGI.unescape_html(response.body)).to match("#{total_organisations_count} total organisations") + 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 logs are being shown on the current page" do + expect(CGI.unescape_html(response.body)).to match("Showing 21 to #{total_organisations_count} of #{total_organisations_count} organisations") + end + + it "has pagination in the title" do + expect(page).to have_title("Organisations (page 2 of 2)") + end + end end end end