Browse Source
* Dynamically display collection resources for years * Display mandatory resources on collection resources page * Move download resources to collection resources controller and refactor routes * Put managing resources button behind a feature flag * Everyone should be able to download mandatory resources * Remove mentions of legacy template and update bu path methods * Update styling * Update tests and routes * CLDC-3518 Allow updating mandatory collection resources (#2676) * Add update resource page * Allow updating mandatory collection resources * CLDC-3518 Add file validation to collection resources (#2678) * Add file validation to collection resources * Move some tests to feature tests * Extract validations into translations file * Rebase changes * More rebase updates * Read file * Update testspull/2683/head
kosiakkatrina
3 months ago
committed by
GitHub
30 changed files with 1058 additions and 250 deletions
@ -0,0 +1,112 @@
|
||||
class CollectionResourcesController < ApplicationController |
||||
include CollectionResourcesHelper |
||||
|
||||
before_action :authenticate_user!, except: %i[download_mandatory_collection_resource] |
||||
|
||||
def index |
||||
render_not_found unless current_user.support? |
||||
|
||||
@mandatory_lettings_collection_resources_per_year = MandatoryCollectionResourcesService.generate_resources("lettings", editable_collection_resource_years) |
||||
@mandatory_sales_collection_resources_per_year = MandatoryCollectionResourcesService.generate_resources("sales", editable_collection_resource_years) |
||||
end |
||||
|
||||
def download_mandatory_collection_resource |
||||
log_type = params[:log_type] |
||||
year = params[:year].to_i |
||||
resource_type = params[:resource_type] |
||||
|
||||
return render_not_found unless resource_for_year_can_be_downloaded?(year) |
||||
|
||||
resource = MandatoryCollectionResourcesService.generate_resource(log_type, year, resource_type) |
||||
return render_not_found unless resource |
||||
|
||||
download_resource(resource.download_filename) |
||||
end |
||||
|
||||
def edit |
||||
return render_not_found unless current_user.support? |
||||
|
||||
year = params[:year].to_i |
||||
resource_type = params[:resource_type] |
||||
log_type = params[:log_type] |
||||
|
||||
return render_not_found unless resource_for_year_can_be_updated?(year) |
||||
|
||||
@collection_resource = MandatoryCollectionResourcesService.generate_resource(log_type, year, resource_type) |
||||
|
||||
return render_not_found unless @collection_resource |
||||
|
||||
render "collection_resources/edit" |
||||
end |
||||
|
||||
def update |
||||
return render_not_found unless current_user.support? |
||||
|
||||
year = resource_params[:year].to_i |
||||
resource_type = resource_params[:resource_type] |
||||
log_type = resource_params[:log_type] |
||||
file = resource_params[:file] |
||||
|
||||
return render_not_found unless resource_for_year_can_be_updated?(year) |
||||
|
||||
@collection_resource = MandatoryCollectionResourcesService.generate_resource(log_type, year, resource_type) |
||||
render_not_found unless @collection_resource |
||||
|
||||
validate_file(file) |
||||
|
||||
return render "collection_resources/edit" if @collection_resource.errors.any? |
||||
|
||||
filename = @collection_resource.download_filename |
||||
begin |
||||
CollectionResourcesService.new.upload_collection_resource(filename, file) |
||||
rescue StandardError |
||||
@collection_resource.errors.add(:file, :error_uploading) |
||||
return render "collection_resources/edit" |
||||
end |
||||
|
||||
flash[:notice] = "The #{log_type} #{text_year_range_format(year)} #{@collection_resource.short_display_name.downcase} has been updated" |
||||
redirect_to collection_resources_path |
||||
end |
||||
|
||||
private |
||||
|
||||
def resource_params |
||||
params.require(:collection_resource).permit(:year, :log_type, :resource_type, :file) |
||||
end |
||||
|
||||
def download_resource(filename) |
||||
file = CollectionResourcesService.new.get_file(filename) |
||||
return render_not_found unless file |
||||
|
||||
send_data(file, disposition: "attachment", filename:) |
||||
end |
||||
|
||||
def resource_for_year_can_be_downloaded?(year) |
||||
return true if current_user&.support? && editable_collection_resource_years.include?(year) |
||||
|
||||
displayed_collection_resource_years.include?(year) |
||||
end |
||||
|
||||
def resource_for_year_can_be_updated?(year) |
||||
editable_collection_resource_years.include?(year) |
||||
end |
||||
|
||||
def validate_file(file) |
||||
return @collection_resource.errors.add(:file, :blank) unless file |
||||
return @collection_resource.errors.add(:file, :above_100_mb) if file.size > 100.megabytes |
||||
|
||||
argv = %W[file --brief --mime-type -- #{file.path}] |
||||
output = `#{argv.shelljoin}` |
||||
|
||||
case @collection_resource.resource_type |
||||
when "paper_form" |
||||
unless output.match?(/application\/pdf/) |
||||
@collection_resource.errors.add(:file, :must_be_pdf) |
||||
end |
||||
when "bulk_upload_template", "bulk_upload_specification" |
||||
unless output.match?(/application\/vnd\.ms-excel|application\/vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet/) |
||||
@collection_resource.errors.add(:file, :must_be_xlsx, resource: @collection_resource.short_display_name.downcase) |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,10 @@
|
||||
class CollectionResource |
||||
include ActiveModel::Model |
||||
include Rails.application.routes.url_helpers |
||||
|
||||
attr_accessor :resource_type, :display_name, :short_display_name, :year, :log_type, :download_filename, :file |
||||
|
||||
def download_path |
||||
download_mandatory_collection_resource_path(log_type:, year:, resource_type:) |
||||
end |
||||
end |
@ -0,0 +1,56 @@
|
||||
class MandatoryCollectionResourcesService |
||||
MANDATORY_RESOURCES = %w[paper_form bulk_upload_template bulk_upload_specification].freeze |
||||
|
||||
def self.generate_resources(log_type, collection_years) |
||||
mandatory_resources_per_year = {} |
||||
collection_years.map do |year| |
||||
mandatory_resources_per_year[year] = resources_per_year(year, log_type) |
||||
end |
||||
mandatory_resources_per_year |
||||
end |
||||
|
||||
def self.resources_per_year(year, log_type) |
||||
MANDATORY_RESOURCES.map do |resource| |
||||
generate_resource(log_type, year, resource) |
||||
end |
||||
end |
||||
|
||||
def self.generate_resource(log_type, year, resource_type) |
||||
return unless log_type && year && resource_type |
||||
return unless %w[lettings sales].include?(log_type) |
||||
return unless MANDATORY_RESOURCES.include?(resource_type) |
||||
|
||||
CollectionResource.new( |
||||
resource_type:, |
||||
display_name: display_name(resource_type, year, log_type), |
||||
short_display_name: resource_type.humanize, |
||||
year:, |
||||
log_type:, |
||||
download_filename: download_filename(resource_type, year, log_type), |
||||
) |
||||
end |
||||
|
||||
def self.display_name(resource, year, log_type) |
||||
year_range = "#{year} to #{year + 1}" |
||||
case resource |
||||
when "paper_form" |
||||
"#{log_type} log for tenants (#{year_range})" |
||||
when "bulk_upload_template" |
||||
"#{log_type} bulk upload template (#{year_range})" |
||||
when "bulk_upload_specification" |
||||
"#{log_type} bulk upload specification (#{year_range})" |
||||
end |
||||
end |
||||
|
||||
def self.download_filename(resource, year, log_type) |
||||
year_range = "#{year}_#{(year + 1) % 100}" |
||||
case resource |
||||
when "paper_form" |
||||
"#{year_range}_#{log_type}_paper_form.pdf" |
||||
when "bulk_upload_template" |
||||
"bulk-upload-#{log_type}-template-#{year_range.dasherize}.xlsx" |
||||
when "bulk_upload_specification" |
||||
"bulk-upload-#{log_type}-specification-#{year_range.dasherize}.xlsx" |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,32 @@
|
||||
<div class="govuk-grid-row"> |
||||
<div class="govuk-grid-column-two-thirds"> |
||||
<%= govuk_summary_list do |summary_list| %> |
||||
<% mandatory_resources.each do |resource| %> |
||||
<% summary_list.with_row do |row| %> |
||||
<% row.with_key { resource.short_display_name } %> |
||||
<% if file_exists_on_s3?(resource.download_filename) %> |
||||
<% row.with_value do %> |
||||
<%= render DocumentListComponent.new(items: document_list_edit_component_items([resource]), label: "") %> |
||||
<% end %> |
||||
<% row.with_action( |
||||
text: "Change", |
||||
href: edit_mandatory_collection_resource_path(year: resource.year, log_type: resource.log_type, resource_type: resource.resource_type), |
||||
) %> |
||||
<% else %> |
||||
<% row.with_value do %> |
||||
<p class="govuk-body app-!-colour-muted">No file uploaded</p> |
||||
<% end %> |
||||
<% row.with_action( |
||||
text: "Upload", |
||||
href: "/", |
||||
) %> |
||||
<% end %> |
||||
<% end %> |
||||
<% end %> |
||||
<% end %> |
||||
<div class="govuk-!-margin-bottom-6"> |
||||
<%= govuk_link_to "Add new #{mandatory_resources.first.log_type} #{text_year_range_format(mandatory_resources.first.year)} resource", href: "/" %> |
||||
</div> |
||||
<hr class="govuk-section-break govuk-section-break--visible govuk-section-break--m"> |
||||
</div> |
||||
</div> |
@ -0,0 +1,28 @@
|
||||
<% content_for :before_content do %> |
||||
<%= govuk_back_link href: collection_resources_path %> |
||||
<% end %> |
||||
|
||||
<div class="govuk-grid-row"> |
||||
<div class="govuk-grid-column-two-thirds"> |
||||
<%= form_with model: @collection_resource, url: update_mandatory_collection_resource_path, method: :patch do |f| %> |
||||
<%= f.hidden_field :year %> |
||||
<%= f.hidden_field :log_type %> |
||||
<%= f.hidden_field :resource_type %> |
||||
|
||||
<%= f.govuk_error_summary %> |
||||
|
||||
<span class="govuk-caption-l"><%= "#{@collection_resource.log_type.humanize} #{text_year_range_format(@collection_resource.year)}" %></span> |
||||
<h1 class="govuk-heading-l">Change the <%= @collection_resource.resource_type.humanize.downcase %></h1> |
||||
|
||||
<p class="govuk-body"> |
||||
This file will be available for all users to download. |
||||
</p> |
||||
|
||||
<%= f.govuk_file_field :file, |
||||
label: { text: "Upload file", size: "m" } %> |
||||
|
||||
<%= f.govuk_submit "Save changes" %> |
||||
<%= govuk_button_link_to "Cancel", collection_resources_path, secondary: true %> |
||||
<% end %> |
||||
</div> |
||||
</div> |
@ -0,0 +1,21 @@
|
||||
<% title = "Collection resources" %> |
||||
<% content_for :title, title %> |
||||
<% content_for :before_content do %> |
||||
<%= govuk_back_link(href: :back) %> |
||||
<% end %> |
||||
|
||||
<h1 class="govuk-heading-l"><%= title %></h1> |
||||
|
||||
<% @mandatory_lettings_collection_resources_per_year.each do |year, mandatory_resources| %> |
||||
<h2 class="govuk-heading-m"> |
||||
Lettings <%= text_year_range_format(year) %> |
||||
</h2> |
||||
<%= render partial: "collection_resource_summary_list", locals: { mandatory_resources: } %> |
||||
<% end %> |
||||
|
||||
<% @mandatory_sales_collection_resources_per_year.each do |year, mandatory_resources| %> |
||||
<h2 class="govuk-heading-m"> |
||||
Sales <%= text_year_range_format(year) %> |
||||
</h2> |
||||
<%= render partial: "collection_resource_summary_list", locals: { mandatory_resources: } %> |
||||
<% end %> |
@ -0,0 +1,10 @@
|
||||
FactoryBot.define do |
||||
factory :collection_resource, class: "CollectionResource" do |
||||
resource_type { "paper_form" } |
||||
display_name { "lettings log for tenants (2021 to 2022)" } |
||||
short_display_name { "Paper Form" } |
||||
year { 2024 } |
||||
log_type { "lettings" } |
||||
download_filename { "24_25_lettings_paper_form.pdf" } |
||||
end |
||||
end |
@ -0,0 +1,168 @@
|
||||
require "rails_helper" |
||||
|
||||
RSpec.describe "Collection resources" do |
||||
let(:user) { create(:user, :support) } |
||||
let(:collection_resources_service) { instance_double(CollectionResourcesService, file_exists_on_s3?: true) } |
||||
|
||||
before do |
||||
allow(CollectionResourcesService).to receive(:new).and_return(collection_resources_service) |
||||
allow(collection_resources_service).to receive(:upload_collection_resource) |
||||
allow(collection_resources_service).to receive(:get_file_metadata).and_return({ "content_type" => "application/pdf", "content_length" => 1000 }) |
||||
allow(user).to receive(:need_two_factor_authentication?).and_return(false) |
||||
sign_in user |
||||
end |
||||
|
||||
context "when uploading paper form" do |
||||
it "only allows pdf files for lettings" do |
||||
visit("/collection-resources/lettings/2024/paper_form/edit") |
||||
|
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("Select which file to upload") |
||||
|
||||
expect(page).to have_content("Change the paper form") |
||||
expect(page).to have_content("Lettings 2024 to 2025") |
||||
|
||||
attach_file "file", file_fixture("excel_file.xlsx") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("The paper form must be a PDF.") |
||||
|
||||
attach_file "file", file_fixture("pdf_file.pdf") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).not_to have_content("The paper form must be a PDF.") |
||||
expect(collection_resources_service).to have_received(:upload_collection_resource).with("2024_25_lettings_paper_form.pdf", anything) |
||||
expect(page).to have_content("The lettings 2024 to 2025 paper form has been updated") |
||||
end |
||||
|
||||
it "only allows pdf files for sales" do |
||||
visit("/collection-resources/sales/2024/paper_form/edit") |
||||
|
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("Select which file to upload") |
||||
|
||||
expect(page).to have_content("Change the paper form") |
||||
expect(page).to have_content("Sales 2024 to 2025") |
||||
|
||||
attach_file "file", file_fixture("excel_file.xlsx") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("The paper form must be a PDF.") |
||||
|
||||
attach_file "file", file_fixture("pdf_file.pdf") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).not_to have_content("The paper form must be a PDF.") |
||||
expect(collection_resources_service).to have_received(:upload_collection_resource).with("2024_25_sales_paper_form.pdf", anything) |
||||
expect(page).to have_content("The sales 2024 to 2025 paper form has been updated") |
||||
end |
||||
end |
||||
|
||||
context "when uploading bu template" do |
||||
it "only allows excel files for lettings" do |
||||
visit("/collection-resources/lettings/2024/bulk_upload_template/edit") |
||||
|
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("Select which file to upload") |
||||
|
||||
expect(page).to have_content("Change the bulk upload template") |
||||
expect(page).to have_content("Lettings 2024 to 2025") |
||||
|
||||
attach_file "file", file_fixture("pdf_file.pdf") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("The bulk upload template must be a Microsoft Excel file.") |
||||
|
||||
attach_file "file", file_fixture("excel_file.xlsx") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).not_to have_content("The bulk upload template must be a Microsoft Excel file.") |
||||
expect(collection_resources_service).to have_received(:upload_collection_resource).with("bulk-upload-lettings-template-2024-25.xlsx", anything) |
||||
expect(page).to have_content("The lettings 2024 to 2025 bulk upload template has been updated") |
||||
end |
||||
|
||||
it "only allows excel files for sales" do |
||||
visit("/collection-resources/sales/2024/bulk_upload_template/edit") |
||||
|
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("Select which file to upload") |
||||
|
||||
expect(page).to have_content("Change the bulk upload template") |
||||
expect(page).to have_content("Sales 2024 to 2025") |
||||
|
||||
attach_file "file", file_fixture("pdf_file.pdf") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("The bulk upload template must be a Microsoft Excel file.") |
||||
|
||||
attach_file "file", file_fixture("excel_file.xlsx") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).not_to have_content("The bulk upload template must be a Microsoft Excel file.") |
||||
expect(collection_resources_service).to have_received(:upload_collection_resource).with("bulk-upload-sales-template-2024-25.xlsx", anything) |
||||
expect(page).to have_content("The sales 2024 to 2025 bulk upload template has been updated") |
||||
end |
||||
end |
||||
|
||||
context "when uploading bu specification" do |
||||
it "only allows excel files for lettings" do |
||||
visit("/collection-resources/lettings/2024/bulk_upload_specification/edit") |
||||
|
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("Select which file to upload") |
||||
|
||||
expect(page).to have_content("Change the bulk upload specification") |
||||
expect(page).to have_content("Lettings 2024 to 2025") |
||||
|
||||
attach_file "file", file_fixture("pdf_file.pdf") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("The bulk upload specification must be a Microsoft Excel file.") |
||||
|
||||
attach_file "file", file_fixture("excel_file.xlsx") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).not_to have_content("The bulk upload specification must be a Microsoft Excel file.") |
||||
expect(collection_resources_service).to have_received(:upload_collection_resource).with("bulk-upload-lettings-specification-2024-25.xlsx", anything) |
||||
expect(page).to have_content("The lettings 2024 to 2025 bulk upload specification has been updated") |
||||
end |
||||
|
||||
it "only allows excel files for sales" do |
||||
visit("/collection-resources/sales/2024/bulk_upload_specification/edit") |
||||
|
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("Select which file to upload") |
||||
|
||||
expect(page).to have_content("Change the bulk upload specification") |
||||
expect(page).to have_content("Sales 2024 to 2025") |
||||
|
||||
attach_file "file", file_fixture("pdf_file.pdf") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("The bulk upload specification must be a Microsoft Excel file.") |
||||
|
||||
attach_file "file", file_fixture("excel_file.xlsx") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).not_to have_content("The bulk upload specification must be a Microsoft Excel file.") |
||||
expect(collection_resources_service).to have_received(:upload_collection_resource).with("bulk-upload-sales-specification-2024-25.xlsx", anything) |
||||
expect(page).to have_content("The sales 2024 to 2025 bulk upload specification has been updated") |
||||
end |
||||
|
||||
it "displays error message if the upload fails" do |
||||
allow(collection_resources_service).to receive(:upload_collection_resource).and_raise(StandardError) |
||||
|
||||
visit("/collection-resources/sales/2024/bulk_upload_specification/edit") |
||||
attach_file "file", file_fixture("excel_file.xlsx") |
||||
click_button("Save changes") |
||||
|
||||
expect(page).to have_content("There was an error uploading this file.") |
||||
end |
||||
end |
||||
end |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,302 @@
|
||||
require "rails_helper" |
||||
|
||||
RSpec.describe CollectionResourcesController, type: :request do |
||||
let(:page) { Capybara::Node::Simple.new(response.body) } |
||||
let(:storage_service) { instance_double(Storage::S3Service, get_file_metadata: nil) } |
||||
|
||||
before do |
||||
allow(Storage::S3Service).to receive(:new).and_return(storage_service) |
||||
allow(storage_service).to receive(:configuration).and_return(OpenStruct.new(bucket_name: "core-test-collection-resources")) |
||||
end |
||||
|
||||
describe "GET #index" do |
||||
context "when user is not signed in" do |
||||
it "redirects to the sign in page" do |
||||
get collection_resources_path |
||||
expect(response).to redirect_to(new_user_session_path) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a data coordinator" do |
||||
let(:user) { create(:user, :data_coordinator) } |
||||
|
||||
before do |
||||
sign_in user |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
get collection_resources_path |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a data provider" do |
||||
let(:user) { create(:user, :data_provider) } |
||||
|
||||
before do |
||||
sign_in user |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
get collection_resources_path |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a support user" do |
||||
let(:user) { create(:user, :support) } |
||||
|
||||
before do |
||||
allow(Time.zone).to receive(:today).and_return(Time.zone.local(2025, 1, 8)) |
||||
allow(user).to receive(:need_two_factor_authentication?).and_return(false) |
||||
allow(storage_service).to receive(:file_exists?).and_return(true) |
||||
sign_in user |
||||
end |
||||
|
||||
it "displays collection resources" do |
||||
get collection_resources_path |
||||
|
||||
expect(page).to have_content("Lettings 2024 to 2025") |
||||
expect(page).to have_content("Lettings 2025 to 2026") |
||||
expect(page).to have_content("Sales 2024 to 2025") |
||||
expect(page).to have_content("Sales 2025 to 2026") |
||||
end |
||||
|
||||
it "displays mandatory filed" do |
||||
get collection_resources_path |
||||
|
||||
expect(page).to have_content("Paper form") |
||||
expect(page).to have_content("Bulk upload template") |
||||
expect(page).to have_content("Bulk upload specification") |
||||
end |
||||
|
||||
context "when files are on S3" do |
||||
before do |
||||
allow(storage_service).to receive(:file_exists?).and_return(true) |
||||
get collection_resources_path |
||||
end |
||||
|
||||
it "displays file names with download links" do |
||||
expect(page).to have_link("2024_25_lettings_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "paper_form")) |
||||
expect(page).to have_link("bulk-upload-lettings-template-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("bulk-upload-lettings-specification-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_specification")) |
||||
expect(page).to have_link("2024_25_sales_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "paper_form")) |
||||
expect(page).to have_link("bulk-upload-sales-template-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("bulk-upload-sales-specification-2024-25.xlsx", href: download_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_specification")) |
||||
|
||||
expect(page).to have_link("2025_26_lettings_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "paper_form")) |
||||
expect(page).to have_link("bulk-upload-lettings-template-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("bulk-upload-lettings-specification-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_specification")) |
||||
expect(page).to have_link("2025_26_sales_paper_form.pdf", href: download_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "paper_form")) |
||||
expect(page).to have_link("bulk-upload-sales-template-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("bulk-upload-sales-specification-2025-26.xlsx", href: download_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_specification")) |
||||
end |
||||
|
||||
it "displays change links" do |
||||
expect(page).to have_selector(:link_or_button, "Change", count: 12) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "paper_form")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "lettings", resource_type: "bulk_upload_specification")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "paper_form")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_specification")) |
||||
|
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "paper_form")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "lettings", resource_type: "bulk_upload_specification")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "paper_form")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_template")) |
||||
expect(page).to have_link("Change", href: edit_mandatory_collection_resource_path(year: 2025, log_type: "sales", resource_type: "bulk_upload_specification")) |
||||
end |
||||
end |
||||
|
||||
context "when files are not on S3" do |
||||
before do |
||||
allow(storage_service).to receive(:file_exists?).and_return(false) |
||||
get collection_resources_path |
||||
end |
||||
|
||||
it "displays No file uploaded" do |
||||
expect(page).to have_content("No file uploaded") |
||||
end |
||||
|
||||
it "displays upload links" do |
||||
expect(page).to have_selector(:link_or_button, "Upload", count: 12) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe "GET #download_mandatory_collection_resource" do |
||||
before do |
||||
# rubocop:disable RSpec/AnyInstance |
||||
allow_any_instance_of(CollectionResourcesHelper).to receive(:editable_collection_resource_years).and_return([2025, 2026]) |
||||
allow_any_instance_of(CollectionResourcesHelper).to receive(:displayed_collection_resource_years).and_return([2025]) |
||||
# rubocop:enable RSpec/AnyInstance |
||||
allow(user).to receive(:need_two_factor_authentication?).and_return(false) |
||||
sign_in user |
||||
end |
||||
|
||||
context "when user is signed in as a data coordinator" do |
||||
let(:user) { create(:user, :data_coordinator) } |
||||
|
||||
context "when the file exists on S3" do |
||||
before do |
||||
allow(storage_service).to receive(:get_file).and_return("file") |
||||
get download_mandatory_collection_resource_path(log_type: "lettings", year: 2025, resource_type: "paper_form") |
||||
end |
||||
|
||||
it "downloads the file" do |
||||
expect(response.body).to eq("file") |
||||
end |
||||
end |
||||
|
||||
context "when the file does not exist on S3" do |
||||
before do |
||||
allow(storage_service).to receive(:get_file).and_return(nil) |
||||
get download_mandatory_collection_resource_path(log_type: "lettings", year: 2024, resource_type: "paper_form") |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
|
||||
context "when resource isn't a mandatory resources" do |
||||
before do |
||||
get download_mandatory_collection_resource_path(log_type: "lettings", year: 2024, resource_type: "invalid_resource") |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
|
||||
context "when year not in displayed_collection_resource_years" do |
||||
before do |
||||
get download_mandatory_collection_resource_path(log_type: "lettings", year: 2026, resource_type: "paper_form") |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a support user" do |
||||
let(:user) { create(:user, :support) } |
||||
|
||||
context "when year is in editable_collection_resource_years but not in displayed_collection_resource_years" do |
||||
before do |
||||
allow(storage_service).to receive(:get_file).and_return("file") |
||||
get download_mandatory_collection_resource_path(log_type: "lettings", year: 2026, resource_type: "paper_form") |
||||
end |
||||
|
||||
it "downloads the file" do |
||||
expect(response.status).to eq(200) |
||||
expect(response.body).to eq("file") |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe "GET #edit_mandatory_collection_resource" do |
||||
context "when user is not signed in" do |
||||
it "redirects to the sign in page" do |
||||
get edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template") |
||||
expect(response).to redirect_to(new_user_session_path) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a data coordinator" do |
||||
let(:user) { create(:user, :data_coordinator) } |
||||
|
||||
before do |
||||
sign_in user |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
get edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template") |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a data provider" do |
||||
let(:user) { create(:user, :data_provider) } |
||||
|
||||
before do |
||||
sign_in user |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
get edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template") |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a support user" do |
||||
let(:user) { create(:user, :support) } |
||||
|
||||
before do |
||||
allow(Time.zone).to receive(:today).and_return(Time.zone.local(2025, 1, 8)) |
||||
allow(user).to receive(:need_two_factor_authentication?).and_return(false) |
||||
sign_in user |
||||
end |
||||
|
||||
it "displays update collection resources page content" do |
||||
get edit_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template") |
||||
|
||||
expect(page).to have_content("Sales 2024 to 2025") |
||||
expect(page).to have_content("Change the bulk upload template") |
||||
expect(page).to have_content("This file will be available for all users to download.") |
||||
expect(page).to have_content("Upload file") |
||||
expect(page).to have_button("Save changes") |
||||
expect(page).to have_link("Back", href: collection_resources_path) |
||||
expect(page).to have_link("Cancel", href: collection_resources_path) |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe "PATCH #update_mandatory_collection_resource" do |
||||
let(:some_file) { File.open(file_fixture("blank_bulk_upload_sales.csv")) } |
||||
let(:params) { { collection_resource: { year: 2024, log_type: "sales", resource_type: "bulk_upload_template", file: some_file } } } |
||||
let(:collection_resource_service) { instance_double(CollectionResourcesService) } |
||||
|
||||
before do |
||||
allow(CollectionResourcesService).to receive(:new).and_return(collection_resource_service) |
||||
end |
||||
|
||||
context "when user is not signed in" do |
||||
it "redirects to the sign in page" do |
||||
patch update_mandatory_collection_resource_path(year: 2024, log_type: "sales", resource_type: "bulk_upload_template", file: some_file) |
||||
expect(response).to redirect_to(new_user_session_path) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a data coordinator" do |
||||
let(:user) { create(:user, :data_coordinator) } |
||||
|
||||
before do |
||||
sign_in user |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
patch update_mandatory_collection_resource_path, params: params |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
|
||||
context "when user is signed in as a data provider" do |
||||
let(:user) { create(:user, :data_provider) } |
||||
|
||||
before do |
||||
sign_in user |
||||
end |
||||
|
||||
it "returns page not found" do |
||||
patch update_mandatory_collection_resource_path, params: params |
||||
expect(response).to have_http_status(:not_found) |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,19 @@
|
||||
require "rails_helper" |
||||
|
||||
describe CollectionResourcesService do |
||||
let(:service) { described_class.new } |
||||
let(:some_file) { File.open(file_fixture("blank_bulk_upload_sales.csv")) } |
||||
let(:storage_service) { instance_double(Storage::S3Service) } |
||||
|
||||
describe "#upload_collection_resource" do |
||||
before do |
||||
allow(Storage::S3Service).to receive(:new).and_return(storage_service) |
||||
allow(storage_service).to receive(:write_file) |
||||
end |
||||
|
||||
it "calls write_file on S3 service" do |
||||
expect(storage_service).to receive(:write_file).with("2025_26_lettings_paper_form.pdf", some_file) |
||||
service.upload_collection_resource("2025_26_lettings_paper_form.pdf", some_file) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,42 @@
|
||||
require "rails_helper" |
||||
|
||||
describe MandatoryCollectionResourcesService do |
||||
let(:service) { described_class } |
||||
|
||||
describe "#generate_resource" do |
||||
it "returns a CollectionResource object" do |
||||
resource = service.generate_resource("lettings", 2024, "paper_form") |
||||
expect(resource).to be_a(CollectionResource) |
||||
end |
||||
|
||||
it "returns nil if resource type is not in the MANDATORY_RESOURCES list" do |
||||
resource = service.generate_resource("lettings", 2024, "invalid_resource") |
||||
expect(resource).to be_nil |
||||
end |
||||
|
||||
it "returns a CollectionResource object with the correct attributes" do |
||||
resource = service.generate_resource("lettings", 2024, "paper_form") |
||||
expect(resource.resource_type).to eq("paper_form") |
||||
expect(resource.display_name).to eq("lettings log for tenants (2024 to 2025)") |
||||
expect(resource.short_display_name).to eq("Paper form") |
||||
expect(resource.year).to eq(2024) |
||||
expect(resource.log_type).to eq("lettings") |
||||
expect(resource.download_filename).to eq("2024_25_lettings_paper_form.pdf") |
||||
end |
||||
end |
||||
|
||||
describe "#generate_resources" do |
||||
it "generates all mandatory resources for given years" do |
||||
resources = service.generate_resources("lettings", [2024, 2025]) |
||||
expect(resources[2024].map(&:resource_type)).to eq(%w[paper_form bulk_upload_template bulk_upload_specification]) |
||||
expect(resources[2025].map(&:resource_type)).to eq(%w[paper_form bulk_upload_template bulk_upload_specification]) |
||||
end |
||||
end |
||||
|
||||
describe "#resources_per_year" do |
||||
it "generates all mandatory resources for a specific year" do |
||||
resources = service.resources_per_year(2024, "lettings") |
||||
expect(resources.map(&:resource_type)).to eq(%w[paper_form bulk_upload_template bulk_upload_specification]) |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue