From b39d4da2f88125aea5e6ed1e8d1cc5ca467516b6 Mon Sep 17 00:00:00 2001 From: Jamie Date: Thu, 30 Jan 2025 11:11:31 +0000 Subject: [PATCH] Improve validation for clawback payer response upload --- .../upload_esfa_response_controller.rb | 3 +- .../upload_provider_response_controller.rb | 3 +- .../_confirmation_step.html.erb | 40 ++++++- .../_upload_errors_step.html.erb | 110 +++++++++--------- .../_upload_step.html.erb | 2 +- .../_confirmation_step.html.erb | 2 +- .../upload_esfa_clawback_response_wizard.rb | 7 +- .../confirmation_step.rb | 12 +- .../upload_errors_step.rb | 24 ++-- .../upload_step.rb | 76 ++++++------ .../confirmation_step.rb | 6 +- .../upload_step.rb | 2 +- config/locales/en/activemodel.yml | 5 +- .../claims/clawbacks/upload_esfa_response.yml | 3 +- .../samplings/upload_provider_response.yml | 4 +- .../upload_esfa_clawback_response_wizard.yml | 39 ++++--- .../upload_provider_response_wizard.yml | 2 +- ...containing_an_invalid_claim_status_spec.rb | 14 +-- ...th_the_status_clawback_in_progress_spec.rb | 15 +-- ...s_a_csv_containing_invalid_headers_spec.rb | 110 ++++++++++++++++++ ..._csv_containing_invalid_references_spec.rb | 18 ++- ...th_the_status_clawback_in_progress_spec.rb | 23 +++- ...th_the_status_sampling_in_progress_spec.rb | 5 +- .../confirmation_step_spec.rb | 32 ++++- .../upload_errors_step_spec.rb | 57 +++++---- .../upload_step_spec.rb | 72 ++++++++++-- ...load_esfa_clawback_response_wizard_spec.rb | 34 ------ .../confirmation_step_spec.rb | 13 +-- 28 files changed, 467 insertions(+), 266 deletions(-) create mode 100644 spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_headers_spec.rb diff --git a/app/controllers/claims/support/claims/clawbacks/upload_esfa_response_controller.rb b/app/controllers/claims/support/claims/clawbacks/upload_esfa_response_controller.rb index c8dc53715..60395768c 100644 --- a/app/controllers/claims/support/claims/clawbacks/upload_esfa_response_controller.rb +++ b/app/controllers/claims/support/claims/clawbacks/upload_esfa_response_controller.rb @@ -14,7 +14,8 @@ def update @wizard.upload_esfa_responses @wizard.reset_state redirect_to index_path, flash: { - heading: t(".success"), + heading: t(".heading"), + body: t(".body"), } end end diff --git a/app/controllers/claims/support/claims/samplings/upload_provider_response_controller.rb b/app/controllers/claims/support/claims/samplings/upload_provider_response_controller.rb index d3b16124a..a936a0210 100644 --- a/app/controllers/claims/support/claims/samplings/upload_provider_response_controller.rb +++ b/app/controllers/claims/support/claims/samplings/upload_provider_response_controller.rb @@ -14,7 +14,8 @@ def update @wizard.upload_provider_responses @wizard.reset_state redirect_to index_path, flash: { - heading: t(".success"), + heading: t(".heading"), + body: t(".body"), } end end diff --git a/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_confirmation_step.html.erb b/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_confirmation_step.html.erb index e2766554b..c9826bb27 100644 --- a/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_confirmation_step.html.erb +++ b/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_confirmation_step.html.erb @@ -1,18 +1,50 @@ <% content_for(:page_title) { sanitize t(".page_title") } %>
-
+
<%= t(".caption") %>

<%= t(".title") %>

<%= form_for(current_step, url: current_step_path, method: :put) do |f| %> <%= f.govuk_error_summary %> -

- <%= t(".claims_count", count: current_step.claims_count) %> +

<%= current_step.file_name %>

+ +
+ <%= govuk_table do |table| %> + <% table.with_head do |head| %> + <% head.with_row do |row| %> + <% row.with_cell text: 1 %> + <% current_step.csv_headers.each do |header| %> + <% row.with_cell text: header %> + <% end %> + <% end %> + <% end %> + + <% table.with_body do |body| %> + <% current_step.csv.each_with_index do |csv_row, index| %> + <% if csv_row["claim_reference"].present? %> + <% body.with_row do |row| %> + <% row.with_cell text: index + 2 %> + <% current_step.csv_headers.each do |header| %> + <%= row.with_cell text: csv_row[header] %> + <% end %> + <% end %> + <% end %> + <% end %> + <% end %> + <% end %> +
+ +

+ <% if current_step.csv.count > 5 %> + <%= t(".only_showing_first_five_rows") %> + <% else %> + <%= t(".showing_all_rows") %> + <% end %>

- <%= f.govuk_submit(t(".upload_data")) %> + <%= f.govuk_submit(t(".confirm_upload")) %> <% end %>
diff --git a/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_errors_step.html.erb b/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_errors_step.html.erb index 71e260f50..7cc5638f7 100644 --- a/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_errors_step.html.erb +++ b/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_errors_step.html.erb @@ -1,75 +1,69 @@ -<% content_for(:page_title) { sanitize t(".page_title") } %> +<% content_for(:page_title) { sanitize title_with_error_prefix(t(".page_title"), error: true) } %>
-
+
<%= t(".caption") %>

<%= t(".title") %>

- <% if current_step.invalid_claim_references.present? %> -

- <%= t(".incorrect_claim_reference") %> -

- <%= govuk_summary_list(actions: false) do |summary_list| %> - <% current_step.invalid_claim_references.each do |invalid_claim_references| %> - <% summary_list.with_row do |row| %> - <% row.with_key( - text: invalid_claim_references, - ) %> - <% end %> - <% end %> - <% end %> - <% end %> +
+
+

+ <%= t(".error_summary.title") %> +

+
+
+ <% if current_step.error_count > 0 %> +

+ <%= t(".error_summary.errors_to_fix", count: current_step.error_count) %> +

+ <% end %> +
+
+
+
- <% if current_step.invalid_status_claims.present? %> -

- <%= t(".incorrect_status") %> -

+

<%= current_step.file_name %>

+ + <%= govuk_table do |table| %> + <% table.with_head do |head| %> + <% head.with_row do |row| %> + <% row.with_cell text: 1 %> + <% row.with_cell text: t(".csv_table.headers.claim_reference") %> + <% row.with_cell text: t(".csv_table.headers.claim_status") %> - <%= govuk_summary_list do |summary_list| %> - <% current_step.invalid_status_claims.each do |invalid_claim| %> - <% summary_list.with_row do |row| %> - <% row.with_key( - text: invalid_claim.reference, - ) %> - <% row.with_action( - text: t(".view"), - href: claims_support_claim_path(invalid_claim), - visually_hidden_text: invalid_claim.reference, - html_attributes: { - class: "govuk-link--no-visited-state", - target: "_blank", - new_tab: true, - }, - ) %> - <% end %> <% end %> <% end %> - <% end %> - - <% if current_step.invalid_updated_status_claims.present? %> -

- <%= t(".invalid_updated_status") %> -

- <%= govuk_summary_list do |summary_list| %> - <% current_step.invalid_updated_status_claims.each do |invalid_claim| %> - <% summary_list.with_row do |row| %> - <% row.with_key( - text: invalid_claim.reference, - ) %> - <% row.with_action( - text: t(".view"), - href: claims_support_claim_path(invalid_claim), - visually_hidden_text: invalid_claim.reference, - html_attributes: { class: "govuk-link--no-visited-state" }, - ) %> + <% table.with_body do |body| %> + <% current_step.row_indexes_with_errors.each do |csv_row_index| %> + <% csv_row = current_step.csv[csv_row_index] %> + <% body.with_row do |row| %> + <% row.with_cell(text: csv_row_index + 2) %> + <% row.with_cell do %> +

+ <% if current_step.invalid_claim_rows.include?(csv_row_index) %> + <%= t(".csv_table.errors.invalid_claim_reference") %>
+ <% end %> + <%= csv_row["claim_reference"] %> +

+ <% end %> + <% row.with_cell do %> +

+ <% if current_step.invalid_claim_status_rows.include?(csv_row_index) %> + <%= t(".csv_table.errors.invalid_claim_status") %>
+ <% end %> + <%= csv_row["claim_status"] %> +

+ <% end %> <% end %> <% end %> <% end %> <% end %> - <%= govuk_warning_text do %> - <%= t(".upload_warning_html") %> - <% end %> +

+ <%= t(".only_showing_rows_with_errors") %> +

+ + <%= govuk_button_link_to t(".upload_your_file_again"), step_path(:upload) %>
diff --git a/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_step.html.erb b/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_step.html.erb index d3f443153..c4c0187bd 100644 --- a/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_step.html.erb +++ b/app/views/wizards/claims/upload_esfa_clawback_response_wizard/_upload_step.html.erb @@ -7,7 +7,7 @@

<%= t(".title") %>

<%= form_for(current_step, url: current_step_path, method: :put, multipart: true) do |f| %> - <%= f.govuk_error_summary %> + <%= f.govuk_error_summary(presenter: DetailedErrorSummaryPresenter) %> <%= f.govuk_file_field :csv_upload, label: { text: t(".upload_csv_file"), size: "s" } %> <%= govuk_details(summary_text: t(".csv_help")) do %> diff --git a/app/views/wizards/claims/upload_provider_response_wizard/_confirmation_step.html.erb b/app/views/wizards/claims/upload_provider_response_wizard/_confirmation_step.html.erb index 669a05687..5434dc04d 100644 --- a/app/views/wizards/claims/upload_provider_response_wizard/_confirmation_step.html.erb +++ b/app/views/wizards/claims/upload_provider_response_wizard/_confirmation_step.html.erb @@ -41,7 +41,7 @@

<% if current_step.csv.count > 5 %> - <%= t(".only_showing_first_rows", row_count: current_step.csv.count) %> + <%= t(".only_showing_first_five_rows") %> <% else %> <%= t(".showing_all_rows") %> <% end %> diff --git a/app/wizards/claims/upload_esfa_clawback_response_wizard.rb b/app/wizards/claims/upload_esfa_clawback_response_wizard.rb index 485baa5cc..f2f28cc01 100644 --- a/app/wizards/claims/upload_esfa_clawback_response_wizard.rb +++ b/app/wizards/claims/upload_esfa_clawback_response_wizard.rb @@ -33,10 +33,6 @@ def clawback_in_progress_claims @clawback_in_progress_claims ||= Claims::Claim.clawback_in_progress end - def claims_count - csv_rows.count - end - private attr_reader :current_user @@ -52,8 +48,7 @@ def csv_inputs_valid? end def csv_rows - csv = steps.fetch(:upload).csv_content - CSV.parse(csv, headers: true, skip_blanks: true).reject do |row| + steps.fetch(:upload).csv.reject do |row| row["claim_reference"].blank? end end diff --git a/app/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step.rb b/app/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step.rb index e46ae3afc..e0c007646 100644 --- a/app/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step.rb +++ b/app/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step.rb @@ -1,3 +1,13 @@ class Claims::UploadESFAClawbackResponseWizard::ConfirmationStep < BaseStep - delegate :claims_count, to: :wizard + delegate :file_name, :csv, to: :upload_step + + def csv_headers + @csv_headers ||= csv.headers + end + + private + + def upload_step + @upload_step ||= wizard.steps.fetch(:upload) + end end diff --git a/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step.rb b/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step.rb index 1caef94a6..dee4e5f8b 100644 --- a/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step.rb +++ b/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step.rb @@ -1,23 +1,25 @@ class Claims::UploadESFAClawbackResponseWizard::UploadErrorsStep < BaseStep - delegate :invalid_claim_references, - :invalid_status_claim_references, - :invalid_updated_status_claim_references, + delegate :invalid_claim_rows, + :invalid_claim_status_rows, + :file_name, + :csv, to: :upload_step - def invalid_status_claims - return [] if invalid_status_claim_references.blank? - - Claims::Claim.where(reference: invalid_status_claim_references) + def row_indexes_with_errors + combined_errors.uniq.sort end - def invalid_updated_status_claims - return [] if invalid_updated_status_claim_references.blank? - - Claims::Claim.where(reference: invalid_updated_status_claim_references) + def error_count + combined_errors.count end private + def combined_errors + invalid_claim_rows + + invalid_claim_status_rows + end + def upload_step @upload_step ||= wizard.steps.fetch(:upload) end diff --git a/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_step.rb b/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_step.rb index 5389d9e36..86abcc232 100644 --- a/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_step.rb +++ b/app/wizards/claims/upload_esfa_clawback_response_wizard/upload_step.rb @@ -1,15 +1,17 @@ class Claims::UploadESFAClawbackResponseWizard::UploadStep < BaseStep attribute :csv_upload attribute :csv_content + attribute :file_name # input validation attributes - attribute :invalid_claim_references, default: [] - attribute :invalid_status_claim_references, default: [] - attribute :invalid_updated_status_claim_references, default: [] + attribute :invalid_claim_rows, default: [] + attribute :invalid_claim_status_rows, default: [] validates :csv_upload, presence: true, if: -> { csv_content.blank? } validate :validate_csv_file, if: -> { csv_upload.present? } + validate :validate_csv_headers, if: -> { csv_content.present? } VALID_UPLOAD_STATUSES = %w[clawback_in_progress clawback_complete].freeze + REQUIRED_HEADERS = %w[claim_reference claim_status].freeze delegate :clawback_in_progress_claims, to: :wizard @@ -28,6 +30,7 @@ def process_csv return if errors.present? assign_csv_content + self.file_name = csv_upload.original_filename self.csv_upload = nil end @@ -36,11 +39,36 @@ def csv_inputs_valid? return true if csv_content.blank? reset_input_attributes - validate_csv_rows + csv.each_with_index do |row, i| + next if row["claim_reference"].blank? - invalid_claim_references && - invalid_status_claim_references.blank? && - invalid_updated_status_claim_references.blank? + validate_claim_reference(row, i) + validate_claim_status(row, i) + end + + invalid_claim_rows.blank? && + invalid_claim_status_rows.blank? + end + + def validate_csv_headers + csv_headers = csv.headers + missing_columns = REQUIRED_HEADERS - csv_headers + return if missing_columns.empty? + + errors.add(:csv_upload, + :invalid_headers, + missing_columns: missing_columns.map { |string| + "‘#{string}’" + }.to_sentence) + errors.add(:csv_upload, + :uploaded_headers, + uploaded_headers: csv_headers.map { |string| + "‘#{string}’" + }.to_sentence) + end + + def csv + @csv ||= CSV.parse(read_csv, headers: true, skip_blanks: true) end private @@ -58,39 +86,21 @@ def read_csv end def reset_input_attributes - self.invalid_claim_references = [] - self.invalid_status_claim_references = [] - self.invalid_updated_status_claim_references = [] + self.invalid_claim_rows = [] + self.invalid_claim_status_rows = [] end ### CSV input valiations - def validate_csv_rows - rows = CSV.parse(read_csv, headers: true).reject { |row| row.all?(&:nil?) } - validate_claims(rows) - validate_updated_statuses(rows) - end - - def validate_claims(rows) - claim_references = rows.pluck("claim_reference").compact.flatten - existing_claims = Claims::Claim.where(reference: claim_references) - existing_claims_references = existing_claims.pluck(:reference) + def validate_claim_reference(row, row_number) + return if clawback_in_progress_claims.find_by(reference: row["claim_reference"]).present? - invalid_references = claim_references - existing_claims_references - self.invalid_claim_references = invalid_references if invalid_references.present? - - valid_status_references = clawback_in_progress_claims.where(reference: claim_references).pluck(:reference) - invalid_status_references = claim_references - valid_status_references - self.invalid_status_claim_references = invalid_status_references if invalid_status_references.present? + invalid_claim_rows << row_number end - def validate_updated_statuses(rows) - invalid_rows = rows.reject do |row| - VALID_UPLOAD_STATUSES.include?(row["claim_status"]) || - row["claim_reference"].blank? - end - return if invalid_rows.blank? + def validate_claim_status(row, row_number) + return if VALID_UPLOAD_STATUSES.include?(row["claim_status"]) - self.invalid_updated_status_claim_references = invalid_rows.pluck("claim_reference") + invalid_claim_status_rows << row_number end end diff --git a/app/wizards/claims/upload_provider_response_wizard/confirmation_step.rb b/app/wizards/claims/upload_provider_response_wizard/confirmation_step.rb index bf3f92d59..25bd9d2ea 100644 --- a/app/wizards/claims/upload_provider_response_wizard/confirmation_step.rb +++ b/app/wizards/claims/upload_provider_response_wizard/confirmation_step.rb @@ -1,9 +1,5 @@ class Claims::UploadProviderResponseWizard::ConfirmationStep < BaseStep - delegate :file_name, :csv, :grouped_csv_rows, to: :upload_step - - def claims_count - grouped_csv_rows.keys.compact.count - end + delegate :file_name, :csv, to: :upload_step def csv_headers @csv_headers ||= csv.headers diff --git a/app/wizards/claims/upload_provider_response_wizard/upload_step.rb b/app/wizards/claims/upload_provider_response_wizard/upload_step.rb index 90c4a1ad0..c354cbeb2 100644 --- a/app/wizards/claims/upload_provider_response_wizard/upload_step.rb +++ b/app/wizards/claims/upload_provider_response_wizard/upload_step.rb @@ -61,7 +61,7 @@ def validate_csv_file end def validate_csv_headers - csv_headers = CSV.parse(read_csv, headers: true).headers + csv_headers = csv.headers missing_columns = REQUIRED_HEADERS - csv_headers return if missing_columns.empty? diff --git a/config/locales/en/activemodel.yml b/config/locales/en/activemodel.yml index 58e93b427..a711a4097 100644 --- a/config/locales/en/activemodel.yml +++ b/config/locales/en/activemodel.yml @@ -236,4 +236,7 @@ en: csv_upload: blank: Select a CSV file to upload invalid: The selected file must be a CSV - invalid_data: The selected CSV file contains invalid data + invalid_headers: + Your file needs a column name called %{missing_columns}. + uploaded_headers: + Right now it has columns called %{uploaded_headers}. diff --git a/config/locales/en/claims/support/claims/clawbacks/upload_esfa_response.yml b/config/locales/en/claims/support/claims/clawbacks/upload_esfa_response.yml index 04d78834d..495136496 100644 --- a/config/locales/en/claims/support/claims/clawbacks/upload_esfa_response.yml +++ b/config/locales/en/claims/support/claims/clawbacks/upload_esfa_response.yml @@ -7,4 +7,5 @@ en: edit: cancel: Cancel update: - success: ESFA response uploaded \ No newline at end of file + heading: Payer response uploaded + body: It may take a moment for the responses to load \ No newline at end of file diff --git a/config/locales/en/claims/support/claims/samplings/upload_provider_response.yml b/config/locales/en/claims/support/claims/samplings/upload_provider_response.yml index f52a63195..041065eaa 100644 --- a/config/locales/en/claims/support/claims/samplings/upload_provider_response.yml +++ b/config/locales/en/claims/support/claims/samplings/upload_provider_response.yml @@ -7,4 +7,6 @@ en: edit: cancel: Cancel update: - success: Provider response uploaded + heading: Provider response uploaded + body: It may take a moment for the responses to load + diff --git a/config/locales/en/wizards/claims/upload_esfa_clawback_response_wizard.yml b/config/locales/en/wizards/claims/upload_esfa_clawback_response_wizard.yml index 501bf62da..607689f33 100644 --- a/config/locales/en/wizards/claims/upload_esfa_clawback_response_wizard.yml +++ b/config/locales/en/wizards/claims/upload_esfa_clawback_response_wizard.yml @@ -24,29 +24,32 @@ en: - claim_submission_date - claim_status confirmation_step: - page_title: Are you sure you want to upload the ESFA response? - Clawbacks - Claims - title: Are you sure you want to upload the ESFA response? + page_title: Confirm you want to upload the payer response - Clawbacks - Claims + title: Confirm you want to upload the payer response caption: Clawbacks - claims_count: - one: There is %{count} claim included in this upload. - other: There are %{count} claims included in this upload. - upload_data: Upload responses + confirm_upload: Confirm upload + only_showing_first_five_rows: Only showing the first 5 rows + showing_all_rows: Showing all rows no_claims_step: title: You cannot upload a payer response page_title: You cannot upload a payer response - Clawbacks - Claims caption: Clawbacks you_cannot_upload: You cannot upload a payer response as there are no claims waiting for a response. upload_errors_step: - title: There is a problem with the CSV file + title: Upload payer response caption: Clawbacks - page_title: There is a problem with the CSV file - Clawbacks - Claims - status: Status - claim_reference: Claim reference - view: View (opens in new tab) - incorrect_claim_reference: There are no claims associated with the following references:- - incorrect_status: The following claims do not have the status 'Clawback in progress':- - invalid_updated_status: The following claims are being updated to an invalid status:- - upload_warning_html: | - You can only upload the ESFA's CSV once they have completed all rows. -

- Email the ESFA and ask them to complete the CSV with the missing information. + page_title: Upload payer response - Clawbacks - Claims + error_summary: + title: There is a problem + errors_to_fix: + one: You need to fix %{count} error related to specific rows + other: You need to fix %{count} errors related to specific rows + csv_table: + headers: + claim_reference: claim_reference + claim_status: claim_status + errors: + invalid_claim_reference: Not a valid claim reference + invalid_claim_status: Not a valid claim status + only_showing_rows_with_errors: Only showing rows with errors + upload_your_file_again: Upload your file again diff --git a/config/locales/en/wizards/claims/upload_provider_response_wizard.yml b/config/locales/en/wizards/claims/upload_provider_response_wizard.yml index a241bf1ce..a1dfd42ac 100644 --- a/config/locales/en/wizards/claims/upload_provider_response_wizard.yml +++ b/config/locales/en/wizards/claims/upload_provider_response_wizard.yml @@ -30,7 +30,7 @@ en: caption: Auditing confirm_upload_details: Confirm these are the provider details you want to upload. confirm_upload: Confirm upload - only_showing_first_rows: Only showing the first %{row_count} rows + only_showing_first_five_rows: Only showing the first 5 rows showing_all_rows: Showing all rows no_claims_step: title: You cannot upload a provider response diff --git a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_an_invalid_claim_status_spec.rb b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_an_invalid_claim_status_spec.rb index 885c30762..9619c6dd8 100644 --- a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_an_invalid_claim_status_spec.rb +++ b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_an_invalid_claim_status_spec.rb @@ -118,17 +118,15 @@ def when_i_upload_a_file_not_containing_an_assured_status_for_each_mentor def then_i_see_the_errors_page expect(page).to have_title( - "There is a problem with the CSV file - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", + "Upload payer response - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", ) - expect(page).to have_h1("There is a problem with the CSV file") + expect(page).to have_h1("Upload payer response") end def and_i_see_the_csv_contained_claims_without_an_assured_status_for_each_mentor - expect(page).to have_h2("The following claims are being updated to an invalid status:-") - expect(page).to have_element(:dl, text: "11111111", class: "govuk-summary-list") - expect(page).to have_warning_text( - "You can only upload the ESFA's CSV once they have completed all rows." \ - " Email the ESFA and ask them to complete the CSV with the missing information.", - ) + expect(page).to have_h1("Upload payer response") + expect(page).to have_element(:div, text: "You need to fix 1 error related to specific rows", class: "govuk-error-summary") + expect(page).to have_element(:td, text: "Not a valid claim status paid", class: "govuk-table__cell", count: 1) + expect(page).to have_element(:p, text: "Only showing rows with errors", class: "govuk-!-text-align-centre") end end diff --git a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_claims_not_with_the_status_clawback_in_progress_spec.rb b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_claims_not_with_the_status_clawback_in_progress_spec.rb index 7c70ec9d5..eac713628 100644 --- a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_claims_not_with_the_status_clawback_in_progress_spec.rb +++ b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_claims_not_with_the_status_clawback_in_progress_spec.rb @@ -115,18 +115,15 @@ def when_i_upload_a_csv_containing_a_claim_not_with_the_status_clawback_in_progr def then_i_see_the_errors_page expect(page).to have_title( - "There is a problem with the CSV file - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", + "Upload payer response - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", ) - expect(page).to have_h1("There is a problem with the CSV file") + expect(page).to have_h1("Upload payer response") end def and_i_see_the_csv_contained_claims_not_with_the_status_clawback_in_progress - expect(page).to have_h2("The following claims do not have the status 'Clawback in progress':-") - expect(page).to have_element(:dl, text: "22222222", class: "govuk-summary-list") - expect(page).to have_link(text: "View (opens in new tab)", href: "/support/claims/#{@paid_claim.id}") - expect(page).to have_warning_text( - "You can only upload the ESFA's CSV once they have completed all rows." \ - " Email the ESFA and ask them to complete the CSV with the missing information.", - ) + expect(page).to have_h1("Upload payer response") + expect(page).to have_element(:div, text: "You need to fix 1 error related to specific rows", class: "govuk-error-summary") + expect(page).to have_element(:td, text: "Not a valid claim reference 22222222", class: "govuk-table__cell", count: 1) + expect(page).to have_element(:p, text: "Only showing rows with errors", class: "govuk-!-text-align-centre") end end diff --git a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_headers_spec.rb b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_headers_spec.rb new file mode 100644 index 000000000..4f844bd97 --- /dev/null +++ b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_headers_spec.rb @@ -0,0 +1,110 @@ +require "rails_helper" + +RSpec.describe "Support user uploads a CSV containing invalid headers", + service: :claims, + type: :system do + scenario do + given_claims_exist + and_i_am_signed_in + + when_i_navigate_to_the_clawback_claims_index_page + then_i_see_the_clawback_claims_index_page + and_i_see_a_claim_with_the_status_clawback_in_progress + + when_i_click_on_upload_esfa_response + then_i_see_the_upload_csv_page + + when_i_upload_a_csv_containing_invalid_headers + and_i_click_on_upload_csv_file + then_i_see_validation_error_regarding_invalid_headers + end + + private + + def given_claims_exist + @clawback_in_progress_claim = create(:claim, :submitted, status: :clawback_in_progress, reference: 11_111_111) + + mentor_john_smith = create(:claims_mentor, first_name: "John", last_name: "Smith") + mentor_jane_doe = create(:claims_mentor, first_name: "Jane", last_name: "Doe") + + _john_smith_mentor_training = create( + :mentor_training, + :rejected, + mentor: mentor_john_smith, + claim: @clawback_in_progress_claim, + hours_completed: 20, + ) + _jane_doe_mentor_training = create( + :mentor_training, + :rejected, + mentor: mentor_jane_doe, + claim: @clawback_in_progress_claim, + hours_completed: 20, + ) + end + + def and_i_am_signed_in + sign_in_claims_support_user + end + + def when_i_navigate_to_the_clawback_claims_index_page + within primary_navigation do + click_on "Claims" + end + + within secondary_navigation do + click_on "Clawbacks" + end + end + + def then_i_see_the_clawback_claims_index_page + expect(page).to have_title("Claims - Claim funding for mentor training - GOV.UK") + expect(page).to have_h1("Claims") + expect(primary_navigation).to have_current_item("Claims") + expect(secondary_navigation).to have_current_item("Clawbacks") + expect(page).to have_current_path(claims_support_claims_clawbacks_path, ignore_query: true) + end + + def then_i_see_the_upload_csv_page + expect(page).to have_h1("Upload payer response") + have_element(:span, text: "Clawback", class: "govuk-caption-l") + expect(page).to have_element(:label, text: "Upload CSV file") + end + + def and_i_see_a_claim_with_the_status_clawback_in_progress + expect(page).to have_h2("Clawbacks (1)") + expect(page).to have_claim_card({ + "title" => "11111111 - #{@clawback_in_progress_claim.school_name}", + "url" => "/support/claims/clawbacks/claims/#{@clawback_in_progress_claim.id}", + "status" => "Clawback in progress", + "academic_year" => @clawback_in_progress_claim.academic_year.name, + "provider_name" => @clawback_in_progress_claim.provider.name, + "submitted_at" => I18n.l(@clawback_in_progress_claim.submitted_at.to_date, format: :long), + "amount" => @clawback_in_progress_claim.amount.format(symbol: true, decimal_mark: ".", no_cents: true), + }) + end + + def when_i_click_on_upload_esfa_response + click_on "Upload payer response" + end + + def and_i_click_on_upload_csv_file + click_on "Upload CSV file" + end + + def when_i_upload_a_csv_containing_invalid_headers + attach_file "Upload CSV file", + "spec/fixtures/claims/sampling/provider_responses/example_provider_response_upload.csv" + end + + def then_i_see_validation_error_regarding_invalid_headers + expect(page).to have_validation_error( + "Your file needs a column name called ‘claim_status’.", + ) + expect(page).to have_element( + :ul, + text: "Right now it has columns called ‘claim_reference’, ‘mentor_full_name’, ‘claim_accepted’, and ‘rejection_reason’.", + class: "govuk-error-summary__list", + ) + end +end diff --git a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_references_spec.rb b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_references_spec.rb index b0de197a6..019c56d62 100644 --- a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_references_spec.rb +++ b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_a_csv_containing_invalid_references_spec.rb @@ -17,7 +17,7 @@ when_i_upload_a_file_not_containing_an_assured_status_for_each_mentor and_i_click_on_upload_csv_file then_i_see_the_errors_page - and_i_see_the_csv_contained_claims_without_an_assured_status_for_each_mentor + and_i_see_the_csv_contained_claims_with_an_invalid_reference end private @@ -118,17 +118,15 @@ def when_i_upload_a_file_not_containing_an_assured_status_for_each_mentor def then_i_see_the_errors_page expect(page).to have_title( - "There is a problem with the CSV file - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", + "Upload payer response - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", ) - expect(page).to have_h1("There is a problem with the CSV file") + expect(page).to have_h1("Upload payer response") end - def and_i_see_the_csv_contained_claims_without_an_assured_status_for_each_mentor - expect(page).to have_h2("There are no claims associated with the following references:-") - expect(page).to have_element(:dl, text: "11111111", class: "govuk-summary-list") - expect(page).to have_warning_text( - "You can only upload the ESFA's CSV once they have completed all rows." \ - " Email the ESFA and ask them to complete the CSV with the missing information.", - ) + def and_i_see_the_csv_contained_claims_with_an_invalid_reference + expect(page).to have_h1("Upload payer response") + expect(page).to have_element(:div, text: "You need to fix 1 error related to specific rows", class: "govuk-error-summary") + expect(page).to have_element(:td, text: "Not a valid claim reference 11111111", class: "govuk-table__cell", count: 1) + expect(page).to have_element(:p, text: "Only showing rows with errors", class: "govuk-!-text-align-centre") end end diff --git a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_esfa_responses_for_claims_with_the_status_clawback_in_progress_spec.rb b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_esfa_responses_for_claims_with_the_status_clawback_in_progress_spec.rb index d0c7e8a10..54781a90c 100644 --- a/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_esfa_responses_for_claims_with_the_status_clawback_in_progress_spec.rb +++ b/spec/system/claims/support/claims/clawbacks/upload_esfa_response/support_user_uploads_esfa_responses_for_claims_with_the_status_clawback_in_progress_spec.rb @@ -157,11 +157,21 @@ def when_i_upload_a_csv_containing_esfa_responses_for_all_claims_with_the_status def then_i_see_the_confirmation_page_for_uploading_esfa_responses expect(page).to have_title( - "Are you sure you want to upload the ESFA response? - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", + "Confirm you want to upload the payer response - Clawbacks - Claims - Claim funding for mentor training - GOV.UK", ) - expect(page).to have_h1("Are you sure you want to upload the ESFA response?") + expect(page).to have_h1("Confirm you want to upload the payer response") have_element(:span, text: "Clawbacks", class: "govuk-caption-l") - expect(page).to have_element(:p, text: "There are 2 claims included in this upload.", class: "govuk-body") + expect(page).to have_h2("example_esfa_clawback_response_upload.csv") + expect(page).to have_table_row( + "1" => "2", + "claim_reference" => "11111111", + "claim_status" => "clawback_complete", + ) + expect(page).to have_table_row( + "1" => "3", + "claim_reference" => "22222222", + "claim_status" => "clawback_complete", + ) end def when_i_click_on_cancel @@ -175,11 +185,14 @@ def when_i_click_on_back alias_method :and_i_click_on_back, :when_i_click_on_back def when_i_click_upload_responses - click_on "Upload responses" + click_on "Confirm upload" end def then_i_see_the_upload_has_been_successful - expect(page).to have_success_banner("ESFA response uploaded") + expect(page).to have_success_banner( + "Payer response uploaded", + "It may take a moment for the responses to load", + ) end def and_i_can_not_see_claim_11111111 diff --git a/spec/system/claims/support/claims/sampling/upload_provider_response/support_user_uploads_provider_responses_for_claims_with_the_status_sampling_in_progress_spec.rb b/spec/system/claims/support/claims/sampling/upload_provider_response/support_user_uploads_provider_responses_for_claims_with_the_status_sampling_in_progress_spec.rb index 7f0f62cd4..1b83ef7c0 100644 --- a/spec/system/claims/support/claims/sampling/upload_provider_response/support_user_uploads_provider_responses_for_claims_with_the_status_sampling_in_progress_spec.rb +++ b/spec/system/claims/support/claims/sampling/upload_provider_response/support_user_uploads_provider_responses_for_claims_with_the_status_sampling_in_progress_spec.rb @@ -198,7 +198,10 @@ def when_i_click_upload_responses end def then_i_see_the_upload_has_been_successful - expect(page).to have_success_banner("Provider response uploaded") + expect(page).to have_success_banner( + "Provider response uploaded", + "It may take a moment for the responses to load", + ) end def then_i_can_see_claim_11111111_has_the_status_provider_not_approved diff --git a/spec/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step_spec.rb b/spec/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step_spec.rb index bd001cdd5..88cf58fb3 100644 --- a/spec/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step_spec.rb +++ b/spec/wizards/claims/upload_esfa_clawback_response_wizard/confirmation_step_spec.rb @@ -5,12 +5,40 @@ let(:mock_wizard) do instance_double(Claims::UploadESFAClawbackResponseWizard).tap do |mock_wizard| - allow(mock_wizard).to receive(:claims_count).and_return(2) + allow(mock_wizard).to receive_messages(steps: { upload: mock_upload_step }) + end + end + let(:mock_upload_step) do + instance_double(Claims::UploadESFAClawbackResponseWizard::UploadStep).tap do |mock_upload_step| + allow(mock_upload_step).to receive_messages( + invalid_claim_rows:, + invalid_claim_status_rows:, + file_name:, + csv:, + ) end end let(:attributes) { nil } + let(:invalid_claim_rows) { nil } + let(:invalid_claim_status_rows) { nil } + let(:file_name) { "uploaded.csv" } + let(:csv) { CSV.parse(csv_content, headers: true, skip_blanks: true) } + let(:csv_content) do + "claim_reference,claim_status\r\n" \ + "11111111,clawback_in_progress\r\n" \ + "22222222,clawback_complete" + end describe "delegations" do - it { is_expected.to delegate_method(:claims_count).to(:wizard) } + it { is_expected.to delegate_method(:csv).to(:upload_step) } + it { is_expected.to delegate_method(:file_name).to(:upload_step) } + end + + describe "#csv_headers" do + it "returns the headers of the CSV file" do + expect(step.csv_headers).to match_array( + %w[claim_reference claim_status], + ) + end end end diff --git a/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step_spec.rb b/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step_spec.rb index 75249ce29..2ce51a55d 100644 --- a/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step_spec.rb +++ b/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_errors_step_spec.rb @@ -11,16 +11,18 @@ let(:mock_upload_step) do instance_double(Claims::UploadESFAClawbackResponseWizard::UploadStep).tap do |mock_upload_step| allow(mock_upload_step).to receive_messages( - invalid_claim_references:, - invalid_status_claim_references:, - invalid_updated_status_claim_references:, + csv_content:, + file_name:, + invalid_claim_rows:, + invalid_claim_status_rows:, ) end end let(:attributes) { nil } - let(:invalid_claim_references) { nil } - let(:invalid_status_claim_references) { nil } - let(:invalid_updated_status_claim_references) { nil } + let(:csv_content) { nil } + let(:file_name) { nil } + let(:invalid_claim_rows) { [] } + let(:invalid_claim_status_rows) { [] } let(:claim_1) { create(:claim, :submitted, status: :clawback_in_progress, reference: 11_111_111) } let(:claim_2) { create(:claim, :submitted, status: :clawback_in_progress, reference: 22_222_222) } let(:claim_3) { create(:claim, :submitted, status: :clawback_in_progress, reference: 33_333_333) } @@ -31,39 +33,32 @@ claim_3 end - describe "#invalid_status_claims" do - subject(:invalid_status_claims) { step.invalid_status_claims } + describe "delegations" do + it { is_expected.to delegate_method(:invalid_claim_rows).to(:upload_step) } + it { is_expected.to delegate_method(:invalid_claim_status_rows).to(:upload_step) } + it { is_expected.to delegate_method(:file_name).to(:upload_step) } + it { is_expected.to delegate_method(:csv).to(:upload_step) } + end - context "when the upload step invalid_claim_references attribute is nil" do - it "returns an empty array" do - expect(invalid_status_claims).to eq([]) - end - end + describe "#row_indexes_with_errors" do + subject(:row_indexes_with_errors) { step.row_indexes_with_errors } - context "when the upload step invalid_claim_references attribute contains a reference" do - let(:invalid_status_claim_references) { %w[11111111 22222222] } + let(:invalid_claim_rows) { [1] } + let(:invalid_claim_status_rows) { [1, 2, 3] } - it "returns a list of claims with the references in the invalid_claim_references attribute" do - expect(invalid_status_claims).to contain_exactly(claim_1, claim_2) - end + it "merges all the validation attributes containing row numbers together (removing duplicates)" do + expect(row_indexes_with_errors).to contain_exactly(1, 2, 3) end end - describe "#invalid_updated_status_claims" do - subject(:invalid_updated_status_claims) { step.invalid_updated_status_claims } - - context "when the upload step invalid_updated_status_claim_references attribute is nil" do - it "returns an empty array" do - expect(invalid_updated_status_claims).to eq([]) - end - end + describe "#error_count" do + subject(:error_count) { step.error_count } - context "when the upload step invalid_updated_status_claim_references attribute contains a reference" do - let(:invalid_updated_status_claim_references) { %w[11111111 22222222] } + let(:invalid_claim_rows) { [1] } + let(:invalid_claim_status_rows) { [1, 2, 3, 4] } - it "returns a list of claims with the references in theinvalid_updated_status_claim_references attribute" do - expect(invalid_updated_status_claims).to contain_exactly(claim_1, claim_2) - end + it "adds together the number of elements in validation attribute" do + expect(error_count).to eq(5) end end end diff --git a/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_step_spec.rb b/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_step_spec.rb index 172f01cf6..e277ed45d 100644 --- a/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_step_spec.rb +++ b/spec/wizards/claims/upload_esfa_clawback_response_wizard/upload_step_spec.rb @@ -15,9 +15,9 @@ expect(step).to have_attributes( csv_upload: nil, csv_content: nil, - invalid_claim_references: [], - invalid_status_claim_references: [], - invalid_updated_status_claim_references: [], + file_name: nil, + invalid_claim_rows: [], + invalid_claim_status_rows: [], ) } end @@ -106,6 +106,28 @@ end end end + + describe "#validate_csv_headers" do + context "when csv_content is present" do + context "when the csv content is missing valid headers" do + let(:csv_content) do + "something_random\r\n" \ + "blah" + end + let(:attributes) { { csv_content: } } + + it "returns errors for missing headers" do + expect(step.valid?).to be(false) + expect(step.errors.messages[:csv_upload]).to include( + "Your file needs a column name called ‘claim_reference’ and ‘claim_status’.", + ) + expect(step.errors.messages[:csv_upload]).to include( + "Right now it has columns called ‘something_random’.", + ) + end + end + end + end end describe "#csv_inputs_valid?" do @@ -126,9 +148,9 @@ before { create(:claim, :submitted, status: :paid, reference: 22_222_222) } - it "returns false and assigns the reference to the 'invalid_claim_references' attribute" do + it "returns false and assigns the csv row to the 'invalid_claim_rows' attribute" do expect(csv_inputs_valid).to be(false) - expect(step.invalid_claim_references).to contain_exactly("11111111") + expect(step.invalid_claim_rows).to contain_exactly(0) end end @@ -141,9 +163,9 @@ before { create(:claim, :submitted, status: :paid, reference: 11_111_111) } - it "returns false and assigns the reference to the 'invalid_status_claim_references' attribute" do + it "returns false and assigns the csv row to the 'invalid_claim_rows' attribute" do expect(csv_inputs_valid).to be(false) - expect(step.invalid_status_claim_references).to contain_exactly("11111111") + expect(step.invalid_claim_rows).to contain_exactly(0) end end @@ -156,9 +178,9 @@ before { create(:claim, :submitted, status: :paid, reference: 11_111_111) } - it "returns false and assigns the reference to the 'invalid_updated_status_claim_references' attribute" do + it "returns false and assigns the reference to the 'invalid_claim_status_rows' attribute" do expect(csv_inputs_valid).to be(false) - expect(step.invalid_updated_status_claim_references).to contain_exactly("11111111") + expect(step.invalid_claim_status_rows).to contain_exactly(0) end end @@ -236,4 +258,36 @@ ) end end + + describe "#csv" do + subject(:csv) { step.csv } + + let(:csv_content) do + "claim_reference,claim_status\r\n" \ + "11111111,clawback_complete\r\n" \ + "22222222,clawback_in_progress\r\n" \ + "" + end + let(:attributes) { { csv_content: } } + + it "converts the csv content into a CSV record" do + expect(csv).to be_a(CSV::Table) + expect(csv.headers).to match_array( + %w[claim_reference claim_status], + ) + expect(csv.count).to eq(2) + + expect(csv[0]).to be_a(CSV::Row) + expect(csv[0].to_h).to eq({ + "claim_reference" => "11111111", + "claim_status" => "clawback_complete", + }) + + expect(csv[1]).to be_a(CSV::Row) + expect(csv[1].to_h).to eq({ + "claim_reference" => "22222222", + "claim_status" => "clawback_in_progress", + }) + end + end end diff --git a/spec/wizards/claims/upload_esfa_clawback_response_wizard_spec.rb b/spec/wizards/claims/upload_esfa_clawback_response_wizard_spec.rb index 9ffce45e1..cd05be997 100644 --- a/spec/wizards/claims/upload_esfa_clawback_response_wizard_spec.rb +++ b/spec/wizards/claims/upload_esfa_clawback_response_wizard_spec.rb @@ -121,38 +121,4 @@ expect(clawback_in_progress_claims).to contain_exactly(clawback_in_progress_claim) end end - - describe "#claims_count" do - subject(:claims_count) { wizard.claims_count } - - let(:clawback_in_progress_claim_1) do - create(:claim, :submitted, status: :clawback_in_progress, reference: 11_111_111) - end - let(:clawback_in_progress_claim_2) do - create(:claim, :submitted, status: :clawback_in_progress, reference: 22_222_222) - end - let(:state) do - { - "upload" => { - "csv_upload" => nil, - "csv_content" => csv_content, - }, - } - end - let(:csv_content) do - "claim_reference,claim_status\r\n" \ - "11111111,clawback_complete\r\n" \ - "22222222,clawback_in_progress\r\n" \ - "," - end - - before do - clawback_in_progress_claim_1 - clawback_in_progress_claim_2 - end - - it "returns the number of rows within the CSV" do - expect(claims_count).to eq(2) - end - end end diff --git a/spec/wizards/claims/upload_provider_response_wizard/confirmation_step_spec.rb b/spec/wizards/claims/upload_provider_response_wizard/confirmation_step_spec.rb index b1b9f63d6..368ae3cdf 100644 --- a/spec/wizards/claims/upload_provider_response_wizard/confirmation_step_spec.rb +++ b/spec/wizards/claims/upload_provider_response_wizard/confirmation_step_spec.rb @@ -5,7 +5,7 @@ let(:mock_wizard) do instance_double(Claims::UploadProviderResponseWizard).tap do |mock_wizard| - allow(mock_wizard).to receive_messages(sampled_claims: Claims::Claim.sampling_in_progress, steps: { upload: mock_upload_step }) + allow(mock_wizard).to receive_messages(steps: { upload: mock_upload_step }) end end let(:mock_upload_step) do @@ -18,7 +18,6 @@ missing_rejection_reason_rows:, file_name:, csv:, - grouped_csv_rows:, ) end end @@ -35,22 +34,12 @@ "11111111,John Smith,yes,Some reason\r\n" \ "22222222,Jane Doe,no,Another reason" end - let(:grouped_csv_rows) do - csv.group_by { |row| row["claim_reference"] } - end describe "delegations" do - it { is_expected.to delegate_method(:grouped_csv_rows).to(:upload_step) } it { is_expected.to delegate_method(:csv).to(:upload_step) } it { is_expected.to delegate_method(:file_name).to(:upload_step) } end - describe "#claims_count" do - it "returns the number of keys returned by the upload steps grouping of claims references" do - expect(step.claims_count).to eq(2) - end - end - describe "#csv_headers" do it "returns the headers of the CSV file" do expect(step.csv_headers).to match_array(