diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 7da1a7724..f083a4ce7 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -5,40 +5,70 @@ class ReportsController < ApplicationController def index; end def features - data = Reports::FeatureReportService.report + forms = Reports::FormDocumentsService.live_form_documents + data = Reports::FeatureReportService.new(forms).report render template: "reports/features", locals: { data: } end def questions_with_answer_type answer_type = params.require(:answer_type) - questions = Reports::FeatureReportService.questions_with_answer_type(answer_type) + forms = Reports::FormDocumentsService.live_form_documents + questions = Reports::FeatureReportService.new(forms).questions_with_answer_type(answer_type) render template: "reports/questions_with_answer_type", locals: { answer_type:, questions: } end def questions_with_add_another_answer - questions = Reports::FeatureReportService.live_questions_with_add_another_answer + forms = Reports::FormDocumentsService.live_form_documents + questions = Reports::FeatureReportService.new(forms).questions_with_add_another_answer - render template: "reports/questions_with_add_another_answer", locals: { questions: } + if params[:format] == "csv" + send_data Reports::QuestionsCsvReportService.new(questions).csv, + type: "text/csv; charset=iso-8859-1", + disposition: "attachment; filename=#{csv_filename('live_questions_with_add_another_answer_report')}" + else + render template: "reports/feature_report", locals: { report: params[:action], records: questions } + end end def forms_with_routes - forms = Reports::FeatureReportService.live_forms_with_routes + forms = Reports::FormDocumentsService.live_form_documents + forms = Reports::FeatureReportService.new(forms).forms_with_routes - render template: "reports/forms_with_routes", locals: { forms: forms } + if params[:format] == "csv" + send_data Reports::FormsCsvReportService.new(forms).csv, + type: "text/csv; charset=iso-8859-1", + disposition: "attachment; filename=#{csv_filename('live_forms_with_routes_report')}" + else + render template: "reports/feature_report", locals: { report: params[:action], records: forms } + end end def forms_with_payments - forms = Reports::FeatureReportService.live_forms_with_payments + forms = Reports::FormDocumentsService.live_form_documents + forms = Reports::FeatureReportService.new(forms).forms_with_payments - render template: "reports/forms_with_payments", locals: { forms: forms } + if params[:format] == "csv" + send_data Reports::FormsCsvReportService.new(forms).csv, + type: "text/csv; charset=iso-8859-1", + disposition: "attachment; filename=#{csv_filename('live_forms_with_payments_report')}" + else + render template: "reports/feature_report", locals: { report: params[:action], records: forms } + end end def forms_with_csv_submission_enabled - forms = Reports::FeatureReportService.live_forms_with_csv_submission_enabled + forms = Reports::FormDocumentsService.live_form_documents + forms = Reports::FeatureReportService.new(forms).forms_with_csv_submission_enabled - render template: "reports/forms_with_csv_submission_enabled", locals: { forms: forms } + if params[:format] == "csv" + send_data Reports::FormsCsvReportService.new(forms).csv, + type: "text/csv; charset=iso-8859-1", + disposition: "attachment; filename=#{csv_filename('live_forms_with_csv_submission_enabled_report')}" + else + render template: "reports/feature_report", locals: { report: params[:action], records: forms } + end end def users @@ -82,42 +112,27 @@ def selection_questions_with_checkboxes def csv_downloads; end def live_forms_csv - send_data Reports::CsvReportsService.new.live_forms_csv, - type: "text/csv; charset=iso-8859-1", - disposition: "attachment; filename=#{csv_filename('live_forms_report')}" - end + forms = Reports::FormDocumentsService.live_form_documents - def live_forms_with_routes_csv - send_data Reports::CsvReportsService.new.live_forms_with_routes_csv, + send_data Reports::FormsCsvReportService.new(forms).csv, type: "text/csv; charset=iso-8859-1", - disposition: "attachment; filename=#{csv_filename('live_forms_with_routes_report')}" - end - - def live_forms_with_payments_csv - send_data Reports::CsvReportsService.new.live_forms_with_payments_csv, - type: "text/csv; charset=iso-8859-1", - disposition: "attachment; filename=#{csv_filename('live_forms_with_payments_report')}" - end - - def live_forms_with_csv_submission_enabled_csv - send_data Reports::CsvReportsService.new.live_forms_with_csv_submission_enabled_csv, - type: "text/csv; charset=iso-8859-1", - disposition: "attachment; filename=#{csv_filename('live_forms_with_csv_submission_enabled_report')}" + disposition: "attachment; filename=#{csv_filename('live_forms_report')}" end def live_questions_csv answer_type = params[:answer_type] - send_data Reports::CsvReportsService.new.live_questions_csv(answer_type:), + forms = Reports::FormDocumentsService.live_form_documents + questions = if answer_type + Reports::FeatureReportService.new(forms).questions_with_answer_type(answer_type) + else + Reports::FeatureReportService.new(forms).questions + end + + send_data Reports::QuestionsCsvReportService.new(questions).csv, type: "text/csv; charset=iso-8859-1", disposition: "attachment; filename=#{questions_csv_filename(answer_type)}" end - def live_questions_with_add_another_answer_csv - send_data Reports::CsvReportsService.new.live_questions_with_add_another_answer_csv, - type: "text/csv; charset=iso-8859-1", - disposition: "attachment; filename=#{csv_filename('live_questions_with_add_another_answer_report')}" - end - private def check_user_has_permission diff --git a/app/helpers/report_helper.rb b/app/helpers/report_helper.rb new file mode 100644 index 000000000..d2ddd4abb --- /dev/null +++ b/app/helpers/report_helper.rb @@ -0,0 +1,92 @@ +module ReportHelper + def report_table(records) + type = records.first.fetch("type", "form") + + if type == "form" + with_routes = records.first.dig("metadata", "number_of_routes").present? + + with_routes ? report_forms_with_routes_table(records) : report_forms_table(records) + elsif type == "question_page" + report_questions_table(records) + else + raise "type of records '#{type}' is not one of 'forms', 'question_page'" + end + end + + def report_forms_table(forms) + { + head: report_forms_table_head, + rows: report_forms_table_rows(forms), + } + end + + def report_forms_with_routes_table(forms) + { + head: report_forms_with_routes_table_head, + rows: report_forms_with_routes_table_rows(forms), + } + end + + def report_questions_table(questions) + { + head: report_questions_table_head, + rows: report_questions_table_rows(questions), + } + end + + def report_forms_table_head + [ + I18n.t("reports.form_or_questions_list_table.headings.form_name"), + I18n.t("reports.form_or_questions_list_table.headings.organisation"), + ] + end + + def report_forms_table_rows(forms) + forms.map { |form| report_forms_table_row(form) } + end + + def report_forms_with_routes_table_head + [ + *report_forms_table_head, + I18n.t("reports.form_or_questions_list_table.headings.number_of_routes"), + ] + end + + def report_forms_with_routes_table_rows(forms) + forms.map { |form| report_forms_with_routes_table_row(form) } + end + + def report_questions_table_head + [ + *report_forms_table_head, + I18n.t("reports.form_or_questions_list_table.headings.question_text"), + ] + end + + def report_questions_table_rows(questions) + questions.map { |question| report_questions_table_row(question) } + end + +private + + def report_forms_table_row(form) + [ + govuk_link_to(form["content"]["name"], live_form_pages_path(form_id: form["form_id"])), + form.dig("group", "organisation", "name") || "", + ] + end + + def report_forms_with_routes_table_row(form) + [ + *report_forms_table_row(form), + form["metadata"]["number_of_routes"].to_s, + ] + end + + def report_questions_table_row(question) + [ + *report_forms_table_row(question["form"]), + question["data"]["question_text"], + ] + end +end diff --git a/app/services/reports/csv_reports_service.rb b/app/services/reports/csv_reports_service.rb deleted file mode 100644 index d1afbad54..000000000 --- a/app/services/reports/csv_reports_service.rb +++ /dev/null @@ -1,183 +0,0 @@ -require "csv" - -class Reports::CsvReportsService - FORM_CSV_HEADERS = [ - "Form ID", - "Status", - "Form name", - "Slug", - "Organisation name", - "Organisation ID", - "Group name", - "Group ID", - "Created at", - "Updated at", - "Number of questions", - "Has routes", - "Payment URL", - "Support URL", - "Support URL text", - "Support email", - "Support phone", - "Privacy policy URL", - "What happens next markdown", - "Submission type", - ].freeze - - IS_REPEATABLE = "Is repeatable?".freeze - QUESTIONS_CSV_HEADERS = [ - "Form ID", - "Status", - "Form name", - "Organisation name", - "Organisation ID", - "Group name", - "Group ID", - "Question number in form", - "Question text", - "Answer type", - "Hint text", - "Page heading", - "Guidance markdown", - "Is optional?", - IS_REPEATABLE, - "Has routes?", - "Answer settings - Input type", - "Selection settings - Only one option?", - "Selection settings - Number of options", - "Name settings - Title needed?", - "Raw answer settings", - ].freeze - - IS_REPEATABLE_COLUMN_INDEX = QUESTIONS_CSV_HEADERS.find_index(IS_REPEATABLE) - - def live_forms_csv - CSV.generate do |csv| - csv << FORM_CSV_HEADERS - - Reports::FormDocumentsService.live_form_documents.each do |form_document| - csv << form_row(form_document) - end - end - end - - def live_forms_with_routes_csv - CSV.generate do |csv| - csv << FORM_CSV_HEADERS - - Reports::FormDocumentsService.live_form_documents.each do |form_document| - csv << form_row(form_document) if Reports::FormDocumentsService.has_routes?(form_document) - end - end - end - - def live_forms_with_payments_csv - CSV.generate do |csv| - csv << FORM_CSV_HEADERS - - Reports::FormDocumentsService.live_form_documents.each do |form_document| - csv << form_row(form_document) if Reports::FormDocumentsService.has_payments?(form_document) - end - end - end - - def live_forms_with_csv_submission_enabled_csv - CSV.generate do |csv| - csv << FORM_CSV_HEADERS - - Reports::FormDocumentsService.live_form_documents.each do |form_document| - csv << form_row(form_document) if Reports::FormDocumentsService.has_csv_submission_enabled?(form_document) - end - end - end - - def live_questions_csv(answer_type: nil) - CSV.generate do |csv| - csv << QUESTIONS_CSV_HEADERS - - Reports::FormDocumentsService.live_form_documents.each do |form_document| - question_rows = question_rows(form_document, answer_type).compact - - question_rows.each do |question| - csv << question - end - end - end - end - - def live_questions_with_add_another_answer_csv - CSV.generate do |csv| - csv << QUESTIONS_CSV_HEADERS - - Reports::FormDocumentsService.live_form_documents.each do |form_document| - question_rows = question_rows(form_document, nil).compact - - question_rows.each do |question| - csv << question if question[IS_REPEATABLE_COLUMN_INDEX] - end - end - end - end - -private - - def form_row(form) - form_id = form["form_id"] - group = GroupForm.find_by_form_id(form_id)&.group - [ - form_id, - form["tag"], - form["content"]["name"], - form["content"]["form_slug"], - group&.organisation&.name, - group&.organisation&.id, - group&.name, - group&.external_id, - form["content"]["created_at"], - form["content"]["updated_at"], - form["content"]["steps"].length, - form["content"]["steps"].any? { |step| step["routing_conditions"].present? }, - form["content"]["payment_url"], - form["content"]["support_url"], - form["content"]["support_url_text"], - form["content"]["support_email"], - form["content"]["support_phone"], - form["content"]["privacy_policy_url"], - form["content"]["what_happens_next_markdown"], - form["content"]["submission_type"], - ] - end - - def question_rows(form, answer_type) - form_id = form["form_id"] - group = GroupForm.find_by_form_id(form_id)&.group - - form["content"]["steps"].each_with_index.map do |step, index| - next if answer_type.present? && step["data"]["answer_type"] != answer_type - - [ - form_id, - form["tag"], - form["content"]["name"], - group&.organisation&.name, - group&.organisation&.id, - group&.name, - group&.external_id, - index + 1, - step["data"]["question_text"], - step["data"]["answer_type"], - step["data"]["hint_text"], - step["data"]["page_heading"], - step["data"]["guidance_markdown"], - step["data"]["is_optional"], - step["data"]["is_repeatable"], - step["routing_conditions"].present?, - step.dig("data", "answer_settings", "input_type"), - step.dig("data", "answer_settings", "only_one_option").presence.try { |o| o.to_s == "true" }, - step.dig("data", "answer_settings", "selection_options")&.length, - step.dig("data", "answer_settings", "title_needed"), - step["data"]["answer_settings"].as_json, - ] - end - end -end diff --git a/app/services/reports/feature_report_service.rb b/app/services/reports/feature_report_service.rb index c1479f21d..f8ebbb1b1 100644 --- a/app/services/reports/feature_report_service.rb +++ b/app/services/reports/feature_report_service.rb @@ -1,100 +1,111 @@ class Reports::FeatureReportService - class << self - def report - report = { - total_live_forms: 0, - live_forms_with_payment: 0, - live_forms_with_routing: 0, - live_forms_with_add_another_answer: 0, - live_forms_with_csv_submission_enabled: 0, - live_forms_with_answer_type: HashWithIndifferentAccess.new, - live_steps_with_answer_type: HashWithIndifferentAccess.new, - } - - Reports::FormDocumentsService.live_form_documents.each do |form| - report[:total_live_forms] += 1 - report[:live_forms_with_payment] += 1 if Reports::FormDocumentsService.has_payments?(form) - report[:live_forms_with_routing] += 1 if Reports::FormDocumentsService.has_routes?(form) - report[:live_forms_with_add_another_answer] += 1 if form["content"]["steps"].any? { |step| step["data"]["is_repeatable"] } - report[:live_forms_with_csv_submission_enabled] += 1 if Reports::FormDocumentsService.has_csv_submission_enabled?(form) - - answer_types_in_form = form["content"]["steps"].map { |step| step["data"]["answer_type"] } - - answer_types_in_form.uniq.each do |answer_type| - report[:live_forms_with_answer_type][answer_type] ||= 0 - report[:live_forms_with_answer_type][answer_type] += 1 - end - - answer_types_in_form.each do |answer_type| - report[:live_steps_with_answer_type][answer_type] ||= 0 - report[:live_steps_with_answer_type][answer_type] += 1 - end - end + attr_reader :form_documents - report - end + def initialize(form_documents) + @form_documents = form_documents + end + + def report + report = { + total_forms: 0, + forms_with_payment: 0, + forms_with_routing: 0, + forms_with_add_another_answer: 0, + forms_with_csv_submission_enabled: 0, + forms_with_answer_type: HashWithIndifferentAccess.new, + steps_with_answer_type: HashWithIndifferentAccess.new, + } - def questions_with_answer_type(answer_type) - Reports::FormDocumentsService.live_form_documents.flat_map do |form| - form["content"]["steps"].select { |step| step["data"]["answer_type"] == answer_type } - .map { |step| questions_details(form, step) } + form_documents.each do |form| + report[:total_forms] += 1 + report[:forms_with_payment] += 1 if Reports::FormDocumentsService.has_payments?(form) + report[:forms_with_routing] += 1 if Reports::FormDocumentsService.has_routes?(form) + report[:forms_with_add_another_answer] += 1 if form["content"]["steps"].any? { |step| step["data"]["is_repeatable"] } + report[:forms_with_csv_submission_enabled] += 1 if Reports::FormDocumentsService.has_csv_submission_enabled?(form) + + answer_types_in_form = form["content"]["steps"].map { |step| step["data"]["answer_type"] } + + answer_types_in_form.uniq.each do |answer_type| + report[:forms_with_answer_type][answer_type] ||= 0 + report[:forms_with_answer_type][answer_type] += 1 end - end - def live_questions_with_add_another_answer - Reports::FormDocumentsService.live_form_documents.flat_map do |form| - form["content"]["steps"].select { |step| step["data"]["is_repeatable"] } - .map { |step| questions_details(form, step) } + answer_types_in_form.each do |answer_type| + report[:steps_with_answer_type][answer_type] ||= 0 + report[:steps_with_answer_type][answer_type] += 1 end end - def live_forms_with_routes - Reports::FormDocumentsService.live_form_documents - .select { |form| Reports::FormDocumentsService.has_routes?(form) } - .map { |form| form_with_routes_details(form) } + report + end + + def questions + form_documents.flat_map do |form| + form["content"]["steps"] + .map { |step| questions_details(form, step) } end + end - def live_forms_with_payments - Reports::FormDocumentsService.live_form_documents - .select { |form| Reports::FormDocumentsService.has_payments?(form) } - .map { |form| form_details(form) } + def questions_with_answer_type(answer_type) + form_documents.flat_map do |form| + form["content"]["steps"] + .select { |step| step["data"]["answer_type"] == answer_type } + .map { |step| questions_details(form, step) } end + end - def live_forms_with_csv_submission_enabled - Reports::FormDocumentsService.live_form_documents - .select { |form| Reports::FormDocumentsService.has_csv_submission_enabled?(form) } - .map { |form| form_details(form) } + def questions_with_add_another_answer + form_documents.flat_map do |form| + form["content"]["steps"] + .select { |step| step["data"]["is_repeatable"] } + .map { |step| questions_details(form, step) } end + end - private + def forms_with_routes + form_documents + .select { |form| Reports::FormDocumentsService.has_routes?(form) } + .map { |form| form_with_routes_details(form) } + end - def questions_details(form, step) - form_id = form["form_id"] - { - form_name: form["content"]["name"], - form_id: form_id, - organisation_name: organisation_name(form_id), - question_text: step["data"]["question_text"], - } - end + def forms_with_payments + form_documents + .select { |form| Reports::FormDocumentsService.has_payments?(form) } + .map { |form| form_details(form) } + end - def form_with_routes_details(form) - form_details = form_details(form) - form_details[:number_of_routes] = form["content"]["steps"].count { |step| step["routing_conditions"].present? } - form_details - end + def forms_with_csv_submission_enabled + form_documents + .select { |form| Reports::FormDocumentsService.has_csv_submission_enabled?(form) } + .map { |form| form_details(form) } + end - def form_details(form) - form_id = form["form_id"] - { - form_name: form["content"]["name"], - form_id: form_id, - organisation_name: organisation_name(form_id), - } - end +private - def organisation_name(form_id) - GroupForm.find_by_form_id(form_id)&.group&.organisation&.name - end + def questions_details(form, step) + form = form_details(form) + step.dup.merge("form" => form) + end + + def form_with_routes_details(form) + form = form_details(form) + form["metadata"] = { + "number_of_routes" => form["content"]["steps"].count { |step| step["routing_conditions"].present? }, + } + form + end + + def form_details(form) + form = form.dup + form["group"] = { + "organisation" => { + "name" => organisation_name(form["form_id"]), + }, + } + form + end + + def organisation_name(form_id) + GroupForm.find_by_form_id(form_id)&.group&.organisation&.name end end diff --git a/app/services/reports/forms_csv_report_service.rb b/app/services/reports/forms_csv_report_service.rb new file mode 100644 index 000000000..ec75c74b7 --- /dev/null +++ b/app/services/reports/forms_csv_report_service.rb @@ -0,0 +1,71 @@ +require "csv" + +class Reports::FormsCsvReportService + FORM_CSV_HEADERS = [ + "Form ID", + "Status", + "Form name", + "Slug", + "Organisation name", + "Organisation ID", + "Group name", + "Group ID", + "Created at", + "Updated at", + "Number of questions", + "Has routes", + "Payment URL", + "Support URL", + "Support URL text", + "Support email", + "Support phone", + "Privacy policy URL", + "What happens next markdown", + "Submission type", + ].freeze + + attr_reader :form_documents + + def initialize(form_documents) + @form_documents = form_documents + end + + def csv + CSV.generate do |csv| + csv << FORM_CSV_HEADERS + + form_documents.each do |form_document| + csv << form_row(form_document) + end + end + end + +private + + def form_row(form) + form_id = form["form_id"] + group = GroupForm.find_by_form_id(form_id)&.group + [ + form_id, + form["tag"], + form["content"]["name"], + form["content"]["form_slug"], + group&.organisation&.name, + group&.organisation&.id, + group&.name, + group&.external_id, + form["content"]["created_at"], + form["content"]["updated_at"], + form["content"]["steps"].length, + form["content"]["steps"].any? { |step| step["routing_conditions"].present? }, + form["content"]["payment_url"], + form["content"]["support_url"], + form["content"]["support_url_text"], + form["content"]["support_email"], + form["content"]["support_phone"], + form["content"]["privacy_policy_url"], + form["content"]["what_happens_next_markdown"], + form["content"]["submission_type"], + ] + end +end diff --git a/app/services/reports/questions_csv_report_service.rb b/app/services/reports/questions_csv_report_service.rb new file mode 100644 index 000000000..c1e64e609 --- /dev/null +++ b/app/services/reports/questions_csv_report_service.rb @@ -0,0 +1,78 @@ +require "csv" + +class Reports::QuestionsCsvReportService + IS_REPEATABLE = "Is repeatable?".freeze + QUESTIONS_CSV_HEADERS = [ + "Form ID", + "Status", + "Form name", + "Organisation name", + "Organisation ID", + "Group name", + "Group ID", + "Question number in form", + "Question text", + "Answer type", + "Hint text", + "Page heading", + "Guidance markdown", + "Is optional?", + IS_REPEATABLE, + "Has routes?", + "Answer settings - Input type", + "Selection settings - Only one option?", + "Selection settings - Number of options", + "Name settings - Title needed?", + "Raw answer settings", + ].freeze + + IS_REPEATABLE_COLUMN_INDEX = QUESTIONS_CSV_HEADERS.find_index(IS_REPEATABLE) + + attr_reader :question_page_documents + + def initialize(question_page_documents) + @question_page_documents = question_page_documents + end + + def csv + CSV.generate do |csv| + csv << QUESTIONS_CSV_HEADERS + + question_page_documents.each do |question_page_document| + csv << question_row(question_page_document) + end + end + end + +private + + def question_row(step) + form = step["form"] + form_id = form["form_id"] + group = GroupForm.find_by_form_id(form_id)&.group + + [ + form_id, + form["tag"], + form["content"]["name"], + group&.organisation&.name, + group&.organisation&.id, + group&.name, + group&.external_id, + step["position"], + step["data"]["question_text"], + step["data"]["answer_type"], + step["data"]["hint_text"], + step["data"]["page_heading"], + step["data"]["guidance_markdown"], + step["data"]["is_optional"], + step["data"]["is_repeatable"], + step["routing_conditions"].present?, + step.dig("data", "answer_settings", "input_type"), + step.dig("data", "answer_settings", "only_one_option").presence.try { |o| o.to_s == "true" }, + step.dig("data", "answer_settings", "selection_options")&.length, + step.dig("data", "answer_settings", "title_needed"), + step["data"]["answer_settings"].as_json, + ] + end +end diff --git a/app/views/reports/feature_report.html.erb b/app/views/reports/feature_report.html.erb new file mode 100644 index 000000000..f71186f24 --- /dev/null +++ b/app/views/reports/feature_report.html.erb @@ -0,0 +1,13 @@ +<% set_page_title(t("reports.#{report}.heading"))%> +<% content_for :back_link, govuk_back_link_to(report_features_path, t("reports.back_to_feature_usage")) %> +
+
+

<%= t("reports.#{report}.heading")%>

+ +

<%=govuk_link_to(t("reports.#{report}.download_csv"), url_for(format: :csv))%>

+
+ +
+ <%= govuk_table(**report_table(records)) %> +
+
diff --git a/app/views/reports/features.html.erb b/app/views/reports/features.html.erb index a2ee9f902..725646a7c 100644 --- a/app/views/reports/features.html.erb +++ b/app/views/reports/features.html.erb @@ -8,23 +8,23 @@ <%= govuk_summary_list do |summary_list| %> <%= summary_list.with_row do |row| %> <%= row.with_key(text: t(".features.total_live_forms")) %> - <%= row.with_value(text: data[:total_live_forms]) %> + <%= row.with_value(text: data[:total_forms]) %> <% end %> <%= summary_list.with_row do |row| %> <%= row.with_key(text: t(".features.live_forms_with_routes")) %> - <%= row.with_value(text: govuk_link_to(data[:live_forms_with_routing], report_forms_with_routes_path, no_visited_state: true)) %> + <%= row.with_value(text: govuk_link_to(data[:forms_with_routing], report_forms_with_routes_path, no_visited_state: true)) %> <% end %> <%= summary_list.with_row do |row| %> <%= row.with_key(text: t(".features.live_forms_with_payments")) %> - <%= row.with_value(text: govuk_link_to(data[:live_forms_with_payment], report_forms_with_payments_path, no_visited_state: true)) %> + <%= row.with_value(text: govuk_link_to(data[:forms_with_payment], report_forms_with_payments_path, no_visited_state: true)) %> <% end %> <%= summary_list.with_row do |row| %> <%= row.with_key(text: t(".features.live_forms_with_add_another_answer")) %> - <%= row.with_value(text: govuk_link_to(data[:live_forms_with_add_another_answer], report_questions_with_add_another_answer_path, no_visited_state: true)) %> + <%= row.with_value(text: govuk_link_to(data[:forms_with_add_another_answer], report_questions_with_add_another_answer_path, no_visited_state: true)) %> <% end %> <%= summary_list.with_row do |row| %> <%= row.with_key(text: t(".features.live_forms_with_csv_submission_enabled")) %> - <%= row.with_value(text: govuk_link_to(data[:live_forms_with_csv_submission_enabled], report_forms_with_csv_submission_enabled_path, no_visited_state: true)) %> + <%= row.with_value(text: govuk_link_to(data[:forms_with_csv_submission_enabled], report_forms_with_csv_submission_enabled_path, no_visited_state: true)) %> <% end %> <% end %> @@ -46,11 +46,11 @@ <%= body.with_row do |row| %> <%= row.with_cell(header: true, text: t("helpers.label.page.answer_type_options.names.#{answer_type}")) %> <% if answer_type_links[answer_type].present? %> - <%= row.with_cell(text: govuk_link_to(data[:live_forms_with_answer_type][answer_type] || 0, answer_type_links[answer_type], no_visited_state: true), numeric: true, html_attributes: { data: { "live-forms-with-answer-type-#{answer_type.to_s.dasherize}": true } }) %> + <%= row.with_cell(text: govuk_link_to(data[:forms_with_answer_type][answer_type] || 0, answer_type_links[answer_type], no_visited_state: true), numeric: true, html_attributes: { data: { "live-forms-with-answer-type-#{answer_type.to_s.dasherize}": true } }) %> <% else %> - <%= row.with_cell(text: data[:live_forms_with_answer_type][answer_type] || 0, numeric: true, html_attributes: { data: { "live-forms-with-answer-type-#{answer_type.to_s.dasherize}": true } }) %> + <%= row.with_cell(text: data[:forms_with_answer_type][answer_type] || 0, numeric: true, html_attributes: { data: { "live-forms-with-answer-type-#{answer_type.to_s.dasherize}": true } }) %> <% end %> - <%= row.with_cell(text: govuk_link_to(data[:live_steps_with_answer_type][answer_type] || 0, report_questions_with_answer_type_path(answer_type:), no_visited_state: true), numeric: true, html_attributes: { data: { "live-pages-with-answer-type-#{answer_type.to_s.dasherize}": true } }) %> + <%= row.with_cell(text: govuk_link_to(data[:steps_with_answer_type][answer_type] || 0, report_questions_with_answer_type_path(answer_type:), no_visited_state: true), numeric: true, html_attributes: { data: { "live-pages-with-answer-type-#{answer_type.to_s.dasherize}": true } }) %> <% end %> <% end %> <% end %> diff --git a/app/views/reports/forms_with_csv_submission_enabled.html.erb b/app/views/reports/forms_with_csv_submission_enabled.html.erb deleted file mode 100644 index c1d5563fa..000000000 --- a/app/views/reports/forms_with_csv_submission_enabled.html.erb +++ /dev/null @@ -1,29 +0,0 @@ -<% set_page_title(t(".heading"))%> -<% content_for :back_link, govuk_back_link_to(report_features_path, t("reports.back_to_feature_usage")) %> -
-
-

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

- -

<%=govuk_link_to(t(".download_csv"), report_live_forms_with_csv_submission_enabled_csv_path)%>

-
- -
- <%= govuk_table do |table| %> - - <%= table.with_head do |head| %> - <%= head.with_row do |row| %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.form_name")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.organisation")) %> - <% end %> - <% end %> - <%= table.with_body do |body| %> - <% forms.each do |form| %> - <%= body.with_row do |row| %> - <%= row.with_cell(text: govuk_link_to(form[:form_name], live_form_path(form_id: form[:form_id]))) %> - <%= row.with_cell(text: form[:organisation_name]) %> - <% end %> - <% end %> - <% end %> - <% end %> -
-
diff --git a/app/views/reports/forms_with_payments.html.erb b/app/views/reports/forms_with_payments.html.erb deleted file mode 100644 index 229ea4b2f..000000000 --- a/app/views/reports/forms_with_payments.html.erb +++ /dev/null @@ -1,29 +0,0 @@ -<% set_page_title(t(".heading"))%> -<% content_for :back_link, govuk_back_link_to(report_features_path, t("reports.back_to_feature_usage")) %> -
-
-

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

- -

<%=govuk_link_to(t(".download_csv"), report_live_forms_with_payments_csv_path)%>

-
- -
- <%= govuk_table do |table| %> - - <%= table.with_head do |head| %> - <%= head.with_row do |row| %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.form_name")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.organisation")) %> - <% end %> - <% end %> - <%= table.with_body do |body| %> - <% forms.each do |form| %> - <%= body.with_row do |row| %> - <%= row.with_cell(text: govuk_link_to(form[:form_name], live_form_path(form_id: form[:form_id]))) %> - <%= row.with_cell(text: form[:organisation_name]) %> - <% end %> - <% end %> - <% end %> - <% end %> -
-
diff --git a/app/views/reports/forms_with_routes.html.erb b/app/views/reports/forms_with_routes.html.erb deleted file mode 100644 index 35fd9dfa0..000000000 --- a/app/views/reports/forms_with_routes.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -<% set_page_title(t(".heading"))%> -<% content_for :back_link, govuk_back_link_to(report_features_path, t("reports.back_to_feature_usage")) %> -
-
-

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

- -

<%=govuk_link_to(t(".download_csv"), report_live_forms_with_routes_csv_path)%>

-
- -
- <%= govuk_table do |table| %> - - <%= table.with_head do |head| %> - <%= head.with_row do |row| %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.form_name")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.organisation")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.number_of_routes")) %> - <% end %> - <% end %> - <%= table.with_body do |body| %> - <% forms.each do |form| %> - <%= body.with_row do |row| %> - <%= row.with_cell(text: govuk_link_to(form[:form_name], live_form_pages_path(form_id: form[:form_id]))) %> - <%= row.with_cell(text: form[:organisation_name]) %> - <%= row.with_cell(text: form[:number_of_routes]) %> - <% end %> - <% end %> - <% end %> - <% end %> -
-
diff --git a/app/views/reports/questions_with_add_another_answer.html.erb b/app/views/reports/questions_with_add_another_answer.html.erb deleted file mode 100644 index 1eb305217..000000000 --- a/app/views/reports/questions_with_add_another_answer.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -<% set_page_title(t(".heading"))%> -<% content_for :back_link, govuk_back_link_to(report_features_path, t("reports.back_to_feature_usage")) %> -
-
-

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

- -

<%=govuk_link_to(t(".download_csv"), report_live_questions_with_add_another_answer_csv_path)%>

-
- -
- <%= govuk_table do |table| %> - - <%= table.with_head do |head| %> - <%= head.with_row do |row| %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.form_name")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.organisation")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.question_text")) %> - <% end %> - <% end %> - <%= table.with_body do |body| %> - <% questions.each do |question| %> - <%= body.with_row do |row| %> - <%= row.with_cell(text: govuk_link_to(question[:form_name], live_form_pages_path(form_id: question[:form_id]))) %> - <%= row.with_cell(text: question[:organisation_name]) %> - <%= row.with_cell(text: question[:question_text]) %> - <% end %> - <% end %> - <% end %> - <% end %> -
-
diff --git a/app/views/reports/questions_with_answer_type.html.erb b/app/views/reports/questions_with_answer_type.html.erb index 35e38ab02..caf3f82ce 100644 --- a/app/views/reports/questions_with_answer_type.html.erb +++ b/app/views/reports/questions_with_answer_type.html.erb @@ -8,24 +8,9 @@
- <%= govuk_table do |table| %> - - <%= table.with_head do |head| %> - <%= head.with_row do |row| %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.form_name")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.organisation")) %> - <%= row.with_cell(text: t("reports.form_or_questions_list_table.headings.question_text")) %> - <% end %> - <% end %> - <%= table.with_body do |body| %> - <% questions.each do |question| %> - <%= body.with_row do |row| %> - <%= row.with_cell(text: govuk_link_to(question[:form_name], live_form_pages_path(form_id: question[:form_id]))) %> - <%= row.with_cell(text: question[:organisation_name]) %> - <%= row.with_cell(text: question[:question_text]) %> - <% end %> - <% end %> - <% end %> - <% end %> + <%= govuk_table( + head: report_questions_table_head, + rows: report_questions_table_rows(questions), + ) %>
diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 6ba0ecc64..6e04a5680 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -132,6 +132,8 @@ ignore_unused: - 'errors.*' - 'date.formats.*' - 'helpers.*' +- 'reports.*.heading' +- 'reports.*.download_csv' - 'routing_page.{branch_routing,exit_pages}.*' ## Exclude these keys from the `i18n-tasks eq-base' report: diff --git a/config/routes.rb b/config/routes.rb index 9463f85b4..f5733054a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -192,14 +192,18 @@ resources :memberships, only: %i[destroy update] - scope :reports do + scope "/reports" do get "/", to: "reports#index", as: :reports - get "features", to: "reports#features", as: :report_features - get "questions-with-answer-type/:answer_type", to: "reports#questions_with_answer_type", as: :report_questions_with_answer_type - get "questions-with-add-another-answer", to: "reports#questions_with_add_another_answer", as: :report_questions_with_add_another_answer - get "forms-with-routes", to: "reports#forms_with_routes", as: :report_forms_with_routes - get "forms-with-payments", to: "reports#forms_with_payments", as: :report_forms_with_payments - get "forms-with-csv-submission-enabled", to: "reports#forms_with_csv_submission_enabled", as: :report_forms_with_csv_submission_enabled + + scope "/features" do + get "/", to: "reports#features", as: :report_features + get "questions-with-answer-type/:answer_type", to: "reports#questions_with_answer_type", as: :report_questions_with_answer_type + get "questions-with-add-another-answer", to: "reports#questions_with_add_another_answer", as: :report_questions_with_add_another_answer + get "forms-with-routes", to: "reports#forms_with_routes", as: :report_forms_with_routes + get "forms-with-payments", to: "reports#forms_with_payments", as: :report_forms_with_payments + get "forms-with-csv-submission-enabled", to: "reports#forms_with_csv_submission_enabled", as: :report_forms_with_csv_submission_enabled + end + get "users", to: "reports#users", as: :report_users get "add_another_answer", to: "reports#add_another_answer", as: :report_add_another_answer get "last-signed-in-at", to: "reports#last_signed_in_at", as: :report_last_signed_in_at @@ -209,11 +213,7 @@ get "selection-questions-with-checkboxes", to: "reports#selection_questions_with_checkboxes", as: :report_selection_questions_with_checkboxes get "csv-downloads", to: "reports#csv_downloads", as: :report_csv_downloads get "live-forms-csv", to: "reports#live_forms_csv", as: :report_live_forms_csv - get "live-forms-with-routes-csv", to: "reports#live_forms_with_routes_csv", as: :report_live_forms_with_routes_csv - get "live-forms-with-payments-csv", to: "reports#live_forms_with_payments_csv", as: :report_live_forms_with_payments_csv - get "live-forms-with-csv-submission-enabled-csv", to: "reports#live_forms_with_csv_submission_enabled_csv", as: :report_live_forms_with_csv_submission_enabled_csv get "live-questions-csv", to: "reports#live_questions_csv", as: :report_live_questions_csv - get "live-questions-with-add-another-answer-csv", to: "reports#live_questions_with_add_another_answer_csv", as: :report_live_questions_with_add_another_answer_csv end get "/maintenance" => "errors#maintenance", as: :maintenance_page diff --git a/spec/fixtures/files/form_documents_response.json b/spec/fixtures/files/form_documents_response.json index 80a585bd7..d05c906c3 100644 --- a/spec/fixtures/files/form_documents_response.json +++ b/spec/fixtures/files/form_documents_response.json @@ -425,5 +425,101 @@ }, "created_at": "2025-01-02T16:24:31.445Z", "updated_at": "2025-01-02T16:24:31.445Z" + }, + { + "id": 4, + "form_id": 4, + "tag": "live", + "content": { + "name": "Skip route form", + "steps": [ + { + "id": 17, + "data": { + "hint_text": null, + "answer_type": "selection", + "is_optional": false, + "page_heading": null, + "is_repeatable": false, + "question_text": "Would you like to submit anonymously?", + "answer_settings": { + "only_one_option": "true", + "selection_options": [ + { + "name": "Yes" + }, + { + "name": "No" + } + ] + }, + "guidance_markdown": null + }, + "type": "question_page", + "position": 1, + "next_step_id": 18, + "routing_conditions": [ + { + "id": 4, + "created_at": "2025-05-07T10:28:31.149Z", + "updated_at": "2025-05-07T10:28:31.149Z", + "skip_to_end": true, + "answer_value": "Yes", + "goto_page_id": null, + "check_page_id": 17, + "routing_page_id": 17, + "exit_page_heading": null, + "validation_errors": [], + "exit_page_markdown": null + } + ] + }, + { + "id": 18, + "data": { + "hint_text": null, + "answer_type": "name", + "is_optional": false, + "page_heading": null, + "is_repeatable": false, + "question_text": "What’s your name?", + "answer_settings": { + "input_type": "full_name", + "title_needed": false + }, + "guidance_markdown": null + }, + "type": "question_page", + "position": 2, + "next_step_id": null, + "routing_conditions": [] + } + ], + "form_id": "4", + "live_at": "2025-05-07T10:28:31.206Z", + "form_slug": "skip-route-form", + "created_at": "2025-05-07T10:28:31.128Z", + "creator_id": null, + "start_page": 17, + "updated_at": "2025-05-07T10:28:31.206Z", + "payment_url": null, + "support_url": null, + "support_email": "your.email+fakedata84701@gmail.com.gov.uk", + "support_phone": null, + "s3_bucket_name": null, + "submission_type": "email", + "declaration_text": "", + "s3_bucket_region": null, + "submission_email": "", + "support_url_text": null, + "privacy_policy_url": "https://www.gov.uk/help/privacy-notice", + "share_preview_completed": true, + "s3_bucket_aws_account_id": null, + "question_section_completed": true, + "what_happens_next_markdown": "This is a test form", + "declaration_section_completed": true + }, + "created_at": "2025-05-07T10:28:31.274Z", + "updated_at": "2025-05-07T10:28:31.274Z" } ] diff --git a/spec/helpers/report_helpers_spec.rb b/spec/helpers/report_helpers_spec.rb new file mode 100644 index 000000000..e5ddc041a --- /dev/null +++ b/spec/helpers/report_helpers_spec.rb @@ -0,0 +1,274 @@ +require "rails_helper" + +RSpec.describe ReportHelper, type: :helper do + let(:forms) do + [ + { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } }, + { "form_id" => 3, "content" => { "name" => "Branch route form" }, "group" => { "organisation" => { "name" => "Ministry of Tests" } } }, + { "form_id" => 4, "content" => { "name" => "Skip route form" }, "group" => { "organisation" => { "name" => "Department for Testing" } } }, + ] + end + + let(:forms_with_routes) do + [ + { "form_id" => 3, "content" => { "name" => "Branch route form" }, "group" => { "organisation" => { "name" => "Ministry of Tests" } }, "metadata" => { "number_of_routes" => 2 } }, + { "form_id" => 4, "content" => { "name" => "Skip route form" }, "group" => { "organisation" => { "name" => "Department for Testing" } }, "metadata" => { "number_of_routes" => 1 } }, + ] + end + + let(:questions) do + [ + { "type" => "question_page", "data" => { "question_text" => "Email address" }, "form" => { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } } }, + { "type" => "question_page", "data" => { "question_text" => "What’s your email address?" }, "form" => { "form_id" => 3, "content" => { "name" => "Branch route form" }, "group" => { "organisation" => { "name" => "Ministry of Tests" } } } }, + ] + end + + describe "#report_table" do + before do + allow(helper).to receive(:report_forms_table).and_call_original + allow(helper).to receive(:report_forms_with_routes_table).and_call_original + allow(helper).to receive(:report_questions_table).and_call_original + end + + context "with list of forms" do + it "calls #report_forms_table" do + helper.report_table(forms) + expect(helper).to have_received(:report_forms_table).with(forms) + end + end + + context "with list of forms with routes" do + it "calls #report_forms_with_routes_table" do + helper.report_table(forms_with_routes) + expect(helper).to have_received(:report_forms_with_routes_table).with(forms_with_routes) + end + end + + context "with list of questions" do + it "calls #report_questions_table" do + helper.report_table(questions) + expect(helper).to have_received(:report_questions_table).with(questions) + end + end + end + + describe "#report_forms_table" do + it "has table head" do + expect(helper.report_forms_table(forms)).to include( + head: helper.report_forms_table_head, + ) + end + + it "has table rows" do + expect(helper.report_forms_table(forms)).to include( + rows: helper.report_forms_table_rows(forms), + ) + end + end + + describe "#report_forms_with_routes_table" do + it "has table head" do + expect(helper.report_forms_with_routes_table(forms_with_routes)).to include( + head: helper.report_forms_with_routes_table_head, + ) + end + + it "has table rows" do + expect(helper.report_forms_with_routes_table(forms_with_routes)).to include( + rows: helper.report_forms_with_routes_table_rows(forms_with_routes), + ) + end + end + + describe "#report_questions_table" do + it "has table head" do + expect(helper.report_questions_table(questions)).to include( + head: helper.report_questions_table_head, + ) + end + + it "has table rows" do + expect(helper.report_questions_table(questions)).to include( + rows: helper.report_questions_table_rows(questions), + ) + end + end + + describe "#report_forms_table_head" do + it "returns the column headings for a table of forms" do + expect(helper.report_forms_table_head).to eq [ + "Form name", + "Organisation", + ] + end + end + + describe "#report_forms_table_rows" do + it "returns an array of arrays of strings" do + expect(helper.report_forms_table_rows(forms)) + .to be_an(Array) + .and(all(be_an(Array))) + .and(all(all(be_a(String)))) + end + + it "returns a row for each form" do + expect(helper.report_forms_table_rows(forms).length) + .to eq forms.length + end + + it "has a column in each row for each column heading" do + expect(helper.report_forms_table_rows(forms).map(&:length)) + .to all eq helper.report_forms_table_head.length + end + + it "formats a link for each form for the first column of each row" do + expect(helper.report_forms_table_rows(forms).map(&:first)).to eq [ + "All question types form", + "Branch route form", + "Skip route form", + ] + end + + it "includes the organisation name for each form for the second column of each row" do + expect(helper.report_forms_table_rows(forms).map(&:second)).to eq [ + "Government Digital Service", + "Ministry of Tests", + "Department for Testing", + ] + end + + context "when form is not in a group" do + let(:forms) do + [ + { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => nil }, + ] + end + + it "returns the empty string for the organisation name" do + expect(helper.report_forms_table_rows(forms).map(&:second)).to eq [ + "", + ] + end + end + end + + describe "#report_forms_with_routes_table_head" do + it "returns the column headings for a table of forms and details of their routes" do + expect(helper.report_forms_with_routes_table_head).to eq [ + "Form name", + "Organisation", + "Number of routes", + ] + end + end + + describe "#report_forms_with_routes_table_rows" do + let(:forms) { forms_with_routes } + + it "returns an array of arrays of strings" do + expect(helper.report_forms_with_routes_table_rows(forms)) + .to be_an(Array) + .and(all(be_an(Array))) + .and(all(all(be_a(String)))) + end + + it "returns a row for each form" do + expect(helper.report_forms_with_routes_table_rows(forms).length) + .to eq forms.length + end + + it "has a column in each row for each column heading" do + expect(helper.report_forms_with_routes_table_rows(forms).map(&:length)) + .to all eq helper.report_forms_with_routes_table_head.length + end + + it "formats a link for each form for the first column of each row" do + expect(helper.report_forms_with_routes_table_rows(forms).map(&:first)).to eq [ + "Branch route form", + "Skip route form", + ] + end + + it "includes the organisation name for each form for the second column of each row" do + expect(helper.report_forms_with_routes_table_rows(forms).map(&:second)).to eq [ + "Ministry of Tests", + "Department for Testing", + ] + end + + it "includes the number of routes in the form" do + expect(helper.report_forms_with_routes_table_rows(forms).map(&:third)).to eq %w[ + 2 + 1 + ] + end + + context "when form is not in a group" do + let(:forms) do + [ + { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => nil }, + ] + end + + it "returns the empty string for the organisation name" do + expect(helper.report_forms_table_rows(forms).map(&:second)).to eq [ + "", + ] + end + end + end + + describe "#report_questions_table_head" do + it "returns the column headings for a table of questions" do + expect(helper.report_questions_table_head).to eq [ + "Form name", + "Organisation", + "Question text", + ] + end + end + + describe "#report_questions_table_rows" do + it "returns an array of arrays of strings" do + expect(helper.report_questions_table_rows(questions)) + .to be_an(Array) + .and(all(be_an(Array))) + .and(all(all(be_a(String)))) + end + + it "formats a link for each form for the first column of each row" do + expect(helper.report_questions_table_rows(questions).map(&:first)).to eq [ + "All question types form", + "Branch route form", + ] + end + + it "includes the organisation name for each form for the second column of each row" do + expect(helper.report_questions_table_rows(questions).map(&:second)).to eq [ + "Government Digital Service", + "Ministry of Tests", + ] + end + + it "includes the question text for each question for the third column of each row" do + expect(helper.report_questions_table_rows(questions).map(&:third)).to eq [ + "Email address", + "What’s your email address?", + ] + end + + context "when form is not in a group" do + let(:questions) do + [ + { "type" => "question_page", "data" => { "question_text" => "Email address" }, "form" => { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => nil } }, + ] + end + + it "returns the empty string for the organisation name" do + expect(helper.report_questions_table_rows(questions).map(&:second)).to eq [ + "", + ] + end + end + end +end diff --git a/spec/requests/reports_controller_spec.rb b/spec/requests/reports_controller_spec.rb index 4407cd411..68321ff9e 100644 --- a/spec/requests/reports_controller_spec.rb +++ b/spec/requests/reports_controller_spec.rb @@ -233,7 +233,7 @@ end it "renders the features report view" do - expect(response).to render_template("reports/questions_with_add_another_answer") + expect(response).to render_template("reports/feature_report") end it "includes the report data" do @@ -291,7 +291,7 @@ end it "renders the features report view" do - expect(response).to render_template("reports/forms_with_routes") + expect(response).to render_template("reports/feature_report") end it "includes the report data" do @@ -349,7 +349,7 @@ end it "renders the features report view" do - expect(response).to render_template("reports/forms_with_payments") + expect(response).to render_template("reports/feature_report") end it "includes the report data" do @@ -407,7 +407,7 @@ end it "renders the features report view" do - expect(response).to render_template("reports/forms_with_csv_submission_enabled") + expect(response).to render_template("reports/feature_report") end it "includes the report data" do @@ -695,62 +695,158 @@ expect(response.body).to include "A question" end end + end - describe "#live_forms_csv" do - let(:csv_reports_service_mock) { instance_double(Reports::CsvReportsService) } - let(:dummy_csv) { '"Column 1", "Column 2"\n"Value 1", "Value 2"' } + describe "csv downloads" do + shared_examples_for "csv response" do + it "returns http code 200" do + expect(response).to have_http_status(:ok) + end - before do - allow(Reports::CsvReportsService).to receive(:new).and_return(csv_reports_service_mock) - allow(csv_reports_service_mock).to receive(:live_forms_csv).and_return(dummy_csv) + it "has content-type text/csv" do + expect(response.headers["content-type"]).to eq "text/csv; charset=iso-8859-1" + end + end + describe "#live_forms_csv" do + before do login_as_super_admin_user + + travel_to Time.utc(2025, 5, 15, 15, 31, 57) + get report_live_forms_csv_path end - it "returns http code 200" do - expect(response).to have_http_status(:ok) - end + it_behaves_like "csv response" it "responds with an attachment content-disposition header" do - expect(response.headers["content-disposition"]).to match(/attachment; filename=live_forms_report-.*?\.csv/) + expect(response.headers["content-disposition"]).to match("attachment; filename=live_forms_report-2025-05-15 15:31:57 UTC.csv") end - it "has content-type text/csv" do - expect(response.headers["content-type"]).to eq "text/csv; charset=iso-8859-1" + it "has expected response body" do + csv = CSV.parse(response.body, headers: true) + expect(csv.headers).to eq Reports::FormsCsvReportService::FORM_CSV_HEADERS + expect(csv.length).to eq 4 + end + end + + describe "#forms_with_routes as csv" do + before do + login_as_super_admin_user + + travel_to Time.utc(2025, 5, 15, 15, 31, 57) + + get report_forms_with_routes_path(format: :csv) + end + + it_behaves_like "csv response" + + it "responds with an attachment content-disposition header" do + expect(response.headers["content-disposition"]).to match("attachment; filename=live_forms_with_routes_report-2025-05-15 15:31:57 UTC.csv") end it "has expected response body" do - expect(response.body).to eq(dummy_csv) + csv = CSV.parse(response.body, headers: true) + expect(csv.headers).to eq Reports::FormsCsvReportService::FORM_CSV_HEADERS + expect(csv.length).to eq 2 + expect(csv.by_col["Form name"]).to eq [ + "Branch route form", + "Skip route form", + ] end end - describe "#live_questions_csv" do - let(:csv_reports_service_mock) { instance_double(Reports::CsvReportsService) } - let(:dummy_csv) { '"Column 1", "Column 2"\n"Value 1", "Value 2"' } + describe "#forms_with_payments as csv" do + before do + login_as_super_admin_user + + travel_to Time.utc(2025, 5, 15, 15, 31, 57) + + get report_forms_with_payments_path(format: :csv) + end + + it_behaves_like "csv response" + + it "responds with an attachment content-disposition header" do + expect(response.headers["content-disposition"]).to match("attachment; filename=live_forms_with_payments_report-2025-05-15 15:31:57 UTC.csv") + end + + it "has expected response body" do + csv = CSV.parse(response.body, headers: true) + expect(csv.headers).to eq Reports::FormsCsvReportService::FORM_CSV_HEADERS + expect(csv.length).to eq 1 + expect(csv.by_col["Form name"]).to eq [ + "All question types form", + ] + end + end + describe "#forms_with_csv_submission_enabled as csv" do before do - allow(Reports::CsvReportsService).to receive(:new).and_return(csv_reports_service_mock) - allow(csv_reports_service_mock).to receive(:live_questions_csv).and_return(dummy_csv) + login_as_super_admin_user + + travel_to Time.utc(2025, 5, 15, 15, 31, 57) + + get report_forms_with_csv_submission_enabled_path(format: :csv) + end + it_behaves_like "csv response" + + it "responds with an attachment content-disposition header" do + expect(response.headers["content-disposition"]).to match("attachment; filename=live_forms_with_csv_submission_enabled_report-2025-05-15 15:31:57 UTC.csv") + end + + it "has expected response body" do + csv = CSV.parse(response.body, headers: true) + expect(csv.headers).to eq Reports::FormsCsvReportService::FORM_CSV_HEADERS + expect(csv.length).to eq 1 + expect(csv.by_col["Form name"]).to eq [ + "All question types form", + ] + end + end + + describe "#live_questions_csv" do + before do login_as_super_admin_user + + travel_to Time.utc(2025, 5, 15, 15, 31, 57) + get report_live_questions_csv_path end - it "returns http code 200" do - expect(response).to have_http_status(:ok) - end + it_behaves_like "csv response" it "responds with an attachment content-disposition header" do - expect(response.headers["content-disposition"]).to match(/attachment; filename=live_questions_report-.*?\.csv/) + expect(response.headers["content-disposition"]).to match("attachment; filename=live_questions_report-2025-05-15 15:31:57 UTC.csv") end - it "has content-type text/csv" do - expect(response.headers["content-type"]).to eq "text/csv; charset=iso-8859-1" + it "has expected response body" do + csv = CSV.parse(response.body, headers: true) + expect(csv.headers).to eq Reports::QuestionsCsvReportService::QUESTIONS_CSV_HEADERS + expect(csv.length).to eq 17 + end + end + + describe "#questions_with_add_another_answer as csv" do + before do + login_as_super_admin_user + + travel_to Time.utc(2025, 5, 15, 15, 31, 57) + + get report_questions_with_add_another_answer_path(format: :csv) + end + + it_behaves_like "csv response" + + it "responds with an attachment content-disposition header" do + expect(response.headers["content-disposition"]).to match("attachment; filename=live_questions_with_add_another_answer_report-2025-05-15 15:31:57 UTC.csv") end it "has expected response body" do - expect(response.body).to eq(dummy_csv) + csv = CSV.parse(response.body, headers: true) + expect(csv.headers).to eq Reports::QuestionsCsvReportService::QUESTIONS_CSV_HEADERS + expect(csv.length).to eq 2 end end end diff --git a/spec/routing/reports_routing_spec.rb b/spec/routing/reports_routing_spec.rb new file mode 100644 index 000000000..c2aad0ddd --- /dev/null +++ b/spec/routing/reports_routing_spec.rb @@ -0,0 +1,65 @@ +require "rails_helper" + +RSpec.describe ReportsController, type: :routing do + describe "feature reports" do + describe "routing" do + it "routes to#features" do + expect(get: "/reports/features").to route_to("reports#features") + end + + it "routes to #questions_with_answer_type" do + expect(get: "/reports/features/questions-with-answer-type/text").to route_to("reports#questions_with_answer_type", answer_type: "text") + end + + it "routes to #questions_with_add_another_answer" do + expect(get: "/reports/features/questions-with-add-another-answer").to route_to("reports#questions_with_add_another_answer") + end + + it "routes to #questions_with_add_another_answer with csv format" do + expect(get: "/reports/features/questions-with-add-another-answer.csv").to route_to("reports#questions_with_add_another_answer", format: "csv") + end + + it "routes to #forms_with_routes" do + expect(get: "/reports/features/forms-with-routes").to route_to("reports#forms_with_routes") + end + + it "routes to #forms_with_routes with csv format" do + expect(get: "/reports/features/forms-with-routes.csv").to route_to("reports#forms_with_routes", format: "csv") + end + + it "routes to #forms_with_payments" do + expect(get: "/reports/features/forms-with-payments").to route_to("reports#forms_with_payments") + end + + it "routes to #forms_with_payments with csv format" do + expect(get: "/reports/features/forms-with-payments.csv").to route_to("reports#forms_with_payments", format: "csv") + end + + it "routes to #forms_with_csv_submission_enabled" do + expect(get: "/reports/features/forms-with-csv-submission-enabled").to route_to("reports#forms_with_csv_submission_enabled") + end + + it "routes to #forms_with_csv_submission_enabled with csv format" do + expect(get: "/reports/features/forms-with-csv-submission-enabled.csv").to route_to("reports#forms_with_csv_submission_enabled", format: "csv") + end + end + + describe "path helpers" do + it "routes to #questions_with_add_another_answer as csv" do + expect(get: report_questions_with_add_another_answer_path(format: :csv)).to route_to("reports#questions_with_add_another_answer", format: "csv") + end + + it "routes to #forms_with_routes as csv" do + expect(get: report_forms_with_routes_path(format: :csv)).to route_to("reports#forms_with_routes", format: "csv") + end + + it "routes to #forms_with_payments as csv" do + expect(get: report_forms_with_payments_path(format: :csv)).to route_to("reports#forms_with_payments", format: "csv") + end + + it "routes to #forms_with_csv_submission_enabled as csv" do + expect(get: report_forms_with_csv_submission_enabled_path(format: :csv)).to route_to("reports#forms_with_csv_submission_enabled", format: "csv") + end + end + end +end diff --git a/spec/services/reports/csv_reports_service_spec.rb b/spec/services/reports/csv_reports_service_spec.rb deleted file mode 100644 index 5d80e1f45..000000000 --- a/spec/services/reports/csv_reports_service_spec.rb +++ /dev/null @@ -1,257 +0,0 @@ -require "rails_helper" - -RSpec.describe Reports::CsvReportsService do - subject(:csv_reports_service) do - described_class.new - end - - let(:form_documents_response_json) { JSON.parse(file_fixture("form_documents_response.json").read) } - - let(:group) { create(:group) } - - before do - GroupForm.create!(form_id: 1, group:) - GroupForm.create!(form_id: 2, group:) - GroupForm.create!(form_id: 3, group:) - - allow(Reports::FormDocumentsService).to receive(:live_form_documents).and_return(form_documents_response_json) - end - - describe "#live_forms_csv" do - it "returns a CSV with 4 rows, including the header row" do - csv = csv_reports_service.live_forms_csv - rows = CSV.parse(csv) - expect(rows.length).to eq 4 - end - - it "has expected values" do - csv = csv_reports_service.live_forms_csv - rows = CSV.parse(csv) - expect(rows[1]).to eq([ - "1", - "live", - "All question types form", - "all-question-types-form", - group.organisation.name, - group.organisation.id.to_s, - group.name, - group.external_id, - "2025-01-02T16:24:31.203Z", - "2025-01-02T16:24:31.255Z", - "9", - "false", - "https://www.gov.uk/payments/your-payment-link", - nil, - nil, - "your.email+fakedata84701@gmail.com.gov.uk", - "08000800", - "https://www.gov.uk/help/privacy-notice", - "Test", - "email_with_csv", - ]) - end - end - - describe "#live_forms_with_routes_csv" do - it "returns a CSV with 2 rows, including the header row" do - csv = csv_reports_service.live_forms_with_routes_csv - rows = CSV.parse(csv) - expect(rows.length).to eq 2 - end - - it "includes form with routes" do - csv = csv_reports_service.live_forms_with_routes_csv - rows = CSV.parse(csv) - has_routes_column_index = rows[0].find_index("Has routes") - expect(rows[1][has_routes_column_index]).to eq "true" - end - end - - describe "#live_forms_with_payments_csv" do - it "returns a CSV with 2 rows, including the header row" do - csv = csv_reports_service.live_forms_with_payments_csv - rows = CSV.parse(csv) - expect(rows.length).to eq 2 - end - - it "includes form with payments" do - csv = csv_reports_service.live_forms_with_payments_csv - rows = CSV.parse(csv) - payment_url_column_index = rows[0].find_index("Payment URL") - expect(rows[1][payment_url_column_index]).to eq "https://www.gov.uk/payments/your-payment-link" - end - end - - describe "#live_forms_with_csv_submission_enabled_csv" do - it "returns a CSV with 2 rows, including the header row" do - csv = csv_reports_service.live_forms_with_csv_submission_enabled_csv - rows = CSV.parse(csv) - expect(rows.length).to eq 2 - end - - it "includes form with submission type email_with_csv" do - csv = csv_reports_service.live_forms_with_csv_submission_enabled_csv - rows = CSV.parse(csv) - submission_type_column_index = rows[0].find_index("Submission type") - expect(rows[1][submission_type_column_index]).to eq "email_with_csv" - end - end - - describe "#live_questions_csv" do - context "when answer_type is nil" do - it "returns a CSV with 16 rows, including the header row" do - csv = csv_reports_service.live_questions_csv - rows = CSV.parse(csv) - expect(rows.length).to eq 16 - end - - it "has expected values for text question" do - csv = csv_reports_service.live_questions_csv - rows = CSV.parse(csv) - text_question_row = rows.detect { |row| row.include? "Single line of text" } - expect(text_question_row).to eq([ - "1", - "live", - "All question types form", - group.organisation.name, - group.organisation.id.to_s, - group.name, - group.external_id, - "1", - "Single line of text", - "text", - nil, - nil, - nil, - "false", - "true", - "false", - "single_line", - nil, - nil, - nil, - "{\"input_type\" => \"single_line\"}", - ]) - end - - it "has expected values for selection question" do - csv = csv_reports_service.live_questions_csv - rows = CSV.parse(csv) - selection_question_row = rows.detect { |row| row.include? "Selection from a list of options" } - expect(selection_question_row).to eq([ - "1", - "live", - "All question types form", - group.organisation.name, - group.organisation.id.to_s, - group.name, - group.external_id, - "8", - "Selection from a list of options", - "selection", - nil, - nil, - nil, - "true", - "false", - "false", - nil, - "false", - "3", - nil, - "{\"only_one_option\" => \"0\", \"selection_options\" => [{\"name\" => \"Option 1\"}, {\"name\" => \"Option 2\"}, {\"name\" => \"Option 3\"}]}", - ]) - end - - it "has expected values for name question" do - csv = csv_reports_service.live_questions_csv - rows = CSV.parse(csv) - name_question_row = rows.detect { |row| row.include? "What’s your name?" } - expect(name_question_row).to eq([ - "3", - "live", - "Branch route form", - group.organisation.name, - group.organisation.id.to_s, - group.name, - group.external_id, - "2", - "What’s your name?", - "name", - nil, - nil, - nil, - "false", - "false", - "false", - "full_name", - nil, - nil, - "false", - "{\"input_type\" => \"full_name\", \"title_needed\" => false}", - ]) - end - - it "has expected values for question with routing conditions" do - csv = csv_reports_service.live_questions_csv - rows = CSV.parse(csv) - routing_question_row = rows.detect { |row| row.include? "How many times have you filled out this form?" } - expect(routing_question_row).to eq([ - "3", - "live", - "Branch route form", - group.organisation.name, - group.organisation.id.to_s, - group.name, - group.external_id, - "1", - "How many times have you filled out this form?", - "selection", - nil, - nil, - nil, - "false", - "false", - "true", - nil, - "true", - "2", - nil, - "{\"only_one_option\" => \"true\", \"selection_options\" => [{\"name\" => \"Once\"}, {\"name\" => \"More than once\"}]}", - ]) - end - end - - context "when answer_type is provided" do - it "returns 3 rows, including the header row" do - csv = csv_reports_service.live_questions_csv(answer_type: "email") - rows = CSV.parse(csv) - expect(rows.length).to eq 3 - end - - it "only includes the desired answer_type" do - csv = csv_reports_service.live_questions_csv(answer_type: "email") - rows = CSV.parse(csv) - answer_type_column_index = rows[0].find_index("Answer type") - expect(rows[1][answer_type_column_index]).to eq "email" - expect(rows[2][answer_type_column_index]).to eq "email" - end - end - end - - describe "#live_questions_with_add_another_answer_csv" do - it "returns 3 rows, including the header row" do - csv = csv_reports_service.live_questions_with_add_another_answer_csv - rows = CSV.parse(csv) - expect(rows.length).to eq 3 - end - - it "only includes questions with add another answer" do - csv = csv_reports_service.live_questions_with_add_another_answer_csv - rows = CSV.parse(csv) - answer_type_column_index = rows[0].find_index("Is repeatable?") - expect(rows[1][answer_type_column_index]).to eq "true" - expect(rows[2][answer_type_column_index]).to eq "true" - end - end -end diff --git a/spec/services/reports/feature_report_service_spec.rb b/spec/services/reports/feature_report_service_spec.rb index 1c4859803..949228e2d 100644 --- a/spec/services/reports/feature_report_service_spec.rb +++ b/spec/services/reports/feature_report_service_spec.rb @@ -1,127 +1,337 @@ require "rails_helper" RSpec.describe Reports::FeatureReportService do - let(:form_documents_response_json) { JSON.parse(file_fixture("form_documents_response.json").read) } + let(:form_documents) { JSON.parse(file_fixture("form_documents_response.json").read) } let(:group) { create(:group) } before do GroupForm.create!(form_id: 1, group:) GroupForm.create!(form_id: 2, group:) GroupForm.create!(form_id: 3, group:) - - allow(Reports::FormDocumentsService).to receive(:live_form_documents).and_return(form_documents_response_json) + GroupForm.create!(form_id: 4, group:) end describe "#report" do it "returns the feature report" do - report = described_class.report + report = described_class.new(form_documents).report expect(report).to eq({ - total_live_forms: 3, - live_forms_with_payment: 1, - live_forms_with_routing: 1, - live_forms_with_add_another_answer: 1, - live_forms_with_csv_submission_enabled: 1, - live_forms_with_answer_type: { + total_forms: 4, + forms_with_payment: 1, + forms_with_routing: 2, + forms_with_add_another_answer: 1, + forms_with_csv_submission_enabled: 1, + forms_with_answer_type: { "address" => 1, "date" => 1, "email" => 2, - "name" => 1, + "name" => 2, "national_insurance_number" => 1, "number" => 1, "phone_number" => 1, - "selection" => 2, + "selection" => 3, "text" => 3, }, - live_steps_with_answer_type: { + steps_with_answer_type: { "address" => 1, "date" => 1, "email" => 2, - "name" => 1, + "name" => 2, "national_insurance_number" => 1, "number" => 1, "phone_number" => 1, - "selection" => 2, + "selection" => 3, "text" => 5, }, }) end end + describe "#questions" do + it "returns all questions in all forms given" do + questions = described_class.new(form_documents).questions + expect(questions.length).to eq 17 + end + + it "returns details needed to render report" do + questions = described_class.new(form_documents).questions + expect(questions).to all match( + a_hash_including( + "form" => a_hash_including( + "form_id" => an_instance_of(Integer), + "content" => a_hash_including( + "name" => a_kind_of(String), + ), + ), + "data" => a_hash_including( + "question_text" => a_kind_of(String), + ), + ), + ) + end + + it "includes a reference to the form document" do + questions = described_class.new(form_documents).questions_with_answer_type("text") + expect(questions).to all include( + "form" => a_hash_including( + "form_id", + "content" => a_hash_including( + "name", + ), + ), + ) + end + end + describe "#questions_with_answer_type" do + it "returns details needed to render report" do + questions = described_class.new(form_documents).questions_with_answer_type("email") + expect(questions).to match [ + a_hash_including( + "form" => a_hash_including( + "form_id" => 1, + "content" => a_hash_including( + "name" => "All question types form", + ), + ), + "data" => a_hash_including( + "question_text" => "Email address", + ), + ), + a_hash_including( + "form" => a_hash_including( + "form_id" => 3, + "content" => a_hash_including( + "name" => "Branch route form", + ), + ), + "data" => a_hash_including( + "question_text" => "What’s your email address?", + ), + ), + ] + end + it "returns questions with the given answer type" do - questions = described_class.questions_with_answer_type("email") + questions = described_class.new(form_documents).questions_with_answer_type("name") expect(questions.length).to eq 2 - expect(questions).to include( - { - form_name: "All question types form", - form_id: 1, - organisation_name: group.organisation.name, - question_text: "Email address", - }, + expect(questions).to all match( + a_hash_including( + "data" => a_hash_including( + "answer_type" => "name", + ), + ), + ) + end + + it "includes a reference to the form document" do + questions = described_class.new(form_documents).questions_with_answer_type("text") + expect(questions).to all include( + "form" => a_hash_including( + "form_id", + "content" => a_hash_including( + "name", + ), + ), ) - expect(questions).to include({ - form_name: "Branch route form", - form_id: 3, - organisation_name: group.organisation.name, - question_text: "What’s your email address?", - }) end end - describe "#live_questions_with_add_another_answer" do + describe "#questions_with_add_another_answer" do + it "returns details needed to render report" do + questions = described_class.new(form_documents).questions_with_add_another_answer + expect(questions).to match [ + a_hash_including( + "form" => a_hash_including( + "form_id" => 1, + "content" => a_hash_including( + "name" => "All question types form", + ), + "group" => a_hash_including( + "organisation" => a_hash_including( + "name" => group.organisation.name, + ), + ), + ), + "data" => a_hash_including( + "question_text" => "Single line of text", + ), + ), + a_hash_including( + "form" => a_hash_including( + "form_id" => 1, + "content" => a_hash_including( + "name" => "All question types form", + ), + "group" => a_hash_including( + "organisation" => a_hash_including( + "name" => group.organisation.name, + ), + ), + ), + "data" => a_hash_including( + "question_text" => "Number", + ), + ), + ] + end + it "returns questions with add another answer" do - questions = described_class.live_questions_with_add_another_answer - expect(questions.length).to eq 2 - expect(questions).to include( - { - form_name: "All question types form", - form_id: 1, - organisation_name: group.organisation.name, - question_text: "Single line of text", - }, + questions = described_class.new(form_documents).questions_with_add_another_answer + expect(questions).to all match( + a_hash_including( + "data" => a_hash_including( + "is_repeatable" => true, + ), + ), + ) + end + + it "includes a reference to the form document" do + questions = described_class.new(form_documents).questions_with_answer_type("text") + expect(questions).to all include( + "form" => a_hash_including( + "form_id", + "content" => a_hash_including( + "name", + ), + ), + ) + end + + it "includes a reference to the organisation record" do + questions = described_class.new(form_documents).questions_with_answer_type("text") + expect(questions).to all include( + "form" => a_hash_including( + "group" => a_hash_including( + "organisation" => a_hash_including( + "name", + ), + ), + ), ) - expect(questions).to include({ - form_name: "All question types form", - form_id: 1, - organisation_name: group.organisation.name, - question_text: "Number", - }) end end - describe "#live_forms_with_routes" do + describe "#forms_with_routes" do + it "returns details needed to render report" do + forms = described_class.new(form_documents).forms_with_routes + expect(forms).to match [ + a_hash_including( + "form_id" => 3, + "content" => a_hash_including( + "name" => "Branch route form", + ), + "group" => a_hash_including( + "organisation" => a_hash_including( + "name" => group.organisation.name, + ), + ), + "metadata" => { + "number_of_routes" => 2, + }, + ), + a_hash_including( + "form_id" => 4, + "content" => a_hash_including( + "name" => "Skip route form", + ), + "group" => a_hash_including( + "organisation" => a_hash_including( + "name" => group.organisation.name, + ), + ), + "metadata" => { + "number_of_routes" => 1, + }, + ), + ] + end + it "returns forms with routes" do - forms = described_class.live_forms_with_routes - expect(forms.length).to eq 1 - expect(forms).to include( - form_name: "Branch route form", - form_id: 3, - organisation_name: group.organisation.name, - number_of_routes: 2, + forms = described_class.new(form_documents).forms_with_routes + expect(forms).to match [ + a_hash_including( + "form_id" => 3, + "content" => a_hash_including( + "name" => "Branch route form", + ), + ), + a_hash_including( + "form_id" => 4, + "content" => a_hash_including( + "name" => "Skip route form", + ), + ), + ] + end + + it "includes counts of routes" do + forms = described_class.new(form_documents).forms_with_routes + expect(forms).to all include( + "metadata" => a_hash_including( + "number_of_routes" => an_instance_of(Integer), + ), + ) + end + + it "includes a reference to the organisation record" do + forms = described_class.new(form_documents).forms_with_routes + expect(forms).to all include( + "group" => a_hash_including( + "organisation" => a_hash_including( + "name", + ), + ), ) end end - describe "#live_forms_with_payments" do + describe "#forms_with_payments" do it "returns live forms with payments" do - forms = described_class.live_forms_with_payments - expect(forms.length).to eq 1 - expect(forms).to include( - form_name: "All question types form", - form_id: 1, - organisation_name: group.organisation.name, + forms = described_class.new(form_documents).forms_with_payments + expect(forms).to match [ + a_hash_including( + "form_id" => 1, + "content" => a_hash_including( + "name" => "All question types form", + ), + ), + ] + end + + it "includes a reference to the organisation record" do + forms = described_class.new(form_documents).forms_with_routes + expect(forms).to all include( + "group" => a_hash_including( + "organisation" => a_hash_including( + "name", + ), + ), ) end end - describe "#live_forms_with_csv_submission_enabled" do + describe "#forms_with_csv_submission_enabled" do it "returns live forms with csv enabled" do - forms = described_class.live_forms_with_csv_submission_enabled - expect(forms.length).to eq 1 - expect(forms).to include( - form_name: "All question types form", - form_id: 1, - organisation_name: group.organisation.name, + forms = described_class.new(form_documents).forms_with_csv_submission_enabled + expect(forms).to match [ + a_hash_including( + "form_id" => 1, + "content" => a_hash_including( + "name" => "All question types form", + ), + ), + ] + end + + it "includes a reference to the organisation record" do + forms = described_class.new(form_documents).forms_with_routes + expect(forms).to all include( + "group" => a_hash_including( + "organisation" => a_hash_including( + "name", + ), + ), ) end end diff --git a/spec/services/reports/form_documents_service_spec.rb b/spec/services/reports/form_documents_service_spec.rb index bad1082e3..c4639a0fd 100644 --- a/spec/services/reports/form_documents_service_spec.rb +++ b/spec/services/reports/form_documents_service_spec.rb @@ -1,80 +1,83 @@ require "rails_helper" RSpec.describe Reports::FormDocumentsService do - let(:form_documents_url) { "#{Settings.forms_api.base_url}/api/v2/form-documents".freeze } - # This response JSON was generated by making a real API request to forms-api with the data from the database seeds. - # Once we have transitioned to using the V2 API in forms-admin, it might make more sense to use factories to generate - # the response. - let(:form_documents_response_json) { file_fixture("form_documents_response.json").read } + describe ".live_form_documents" do + let(:form_documents_url) { "#{Settings.forms_api.base_url}/api/v2/form-documents".freeze } + # This response JSON was generated by making a real API request to forms-api with the data from the database seeds. + # Once we have transitioned to using the V2 API in forms-admin, it might make more sense to use factories to generate + # the response. + let(:form_documents_response_json) { file_fixture("form_documents_response.json").read } - before do - stub_request(:get, form_documents_url) - .with(query: { page: "1", per_page: "3", tag: "live" }) - .to_return(body: form_documents_response_json, headers: response_headers(9, 0, 3)) - stub_request(:get, form_documents_url) - .with(query: { page: "2", per_page: "3", tag: "live" }) - .to_return(body: form_documents_response_json, headers: response_headers(9, 3, 3)) - stub_request(:get, form_documents_url) - .with(query: { page: "3", per_page: "3", tag: "live" }) - .to_return(body: form_documents_response_json, headers: response_headers(9, 6, 3)) - end - - it "makes request to forms-api for each page of results" do - form_documents = described_class.live_form_documents.to_a - expect(form_documents.size).to eq(9) - assert_requested(:get, form_documents_url, query: { page: "1", per_page: "3", tag: "live" }, headers:, times: 1) - assert_requested(:get, form_documents_url, query: { page: "2", per_page: "3", tag: "live" }, headers:, times: 1) - assert_requested(:get, form_documents_url, query: { page: "3", per_page: "3", tag: "live" }, headers:, times: 1) - end - - it "returns form documents" do - form_document = described_class.live_form_documents.first - expect(form_document).to be_a(Hash) - expect(form_document).to have_key("form_id") - end - - context "when forms-api responds with a non-success status code" do before do + allow(Settings.reports).to receive(:forms_api_forms_per_request_page).and_return 4 + + stub_request(:get, form_documents_url) + .with(query: { page: "1", per_page: "4", tag: "live" }) + .to_return(body: form_documents_response_json, headers: response_headers(12, 0, 4)) stub_request(:get, form_documents_url) - .with(query: { page: "1", per_page: "3", tag: "live" }) - .to_return(body: "There was an error", status: 400) + .with(query: { page: "2", per_page: "4", tag: "live" }) + .to_return(body: form_documents_response_json, headers: response_headers(12, 4, 4)) + stub_request(:get, form_documents_url) + .with(query: { page: "3", per_page: "4", tag: "live" }) + .to_return(body: form_documents_response_json, headers: response_headers(12, 8, 4)) end - it "raises a StandardError" do - expect { described_class.live_form_documents.first }.to raise_error( - StandardError, "Forms API responded with a non-success HTTP code when retrieving form documents: status 400" - ) + it "makes request to forms-api for each page of results" do + form_documents = described_class.live_form_documents.to_a + expect(form_documents.size).to eq(12) + assert_requested(:get, form_documents_url, query: { page: "1", per_page: "4", tag: "live" }, headers:, times: 1) + assert_requested(:get, form_documents_url, query: { page: "2", per_page: "4", tag: "live" }, headers:, times: 1) + assert_requested(:get, form_documents_url, query: { page: "3", per_page: "4", tag: "live" }, headers:, times: 1) end - end - context "when there are forms from internal organisations" do - let(:organisation) { build :organisation, id: 1, internal: false } - let(:internal_organisation) { build :organisation, id: 1, internal: true } - let(:group) { build :group, id: 1, organisation: } - let(:internal_group) { build :group, id: 1, organisation: internal_organisation } - let(:group_form) { GroupForm.new(group:) } - let(:internal_group_form) { GroupForm.new(group: internal_group) } + it "returns form documents" do + form_document = described_class.live_form_documents.first + expect(form_document).to be_a(Hash) + expect(form_document).to have_key("form_id") + end - before do - allow(GroupForm).to receive(:find_by_form_id).with(1).and_return(group_form) - allow(GroupForm).to receive(:find_by_form_id).with(2).and_return(group_form) - allow(GroupForm).to receive(:find_by_form_id).with(3).and_return(internal_group_form) + context "when forms-api responds with a non-success status code" do + before do + stub_request(:get, form_documents_url) + .with(query: { page: "1", per_page: "4", tag: "live" }) + .to_return(body: "There was an error", status: 400) + end + + it "raises a StandardError" do + expect { described_class.live_form_documents.first }.to raise_error( + StandardError, "Forms API responded with a non-success HTTP code when retrieving form documents: status 400" + ) + end end - it "does not include these forms in the live_form_documents output" do - form_documents = described_class.live_form_documents.to_a - expect(form_documents.size).to eq(6) + context "when there are forms from internal organisations" do + let(:organisation) { build :organisation, id: 1, internal: false } + let(:internal_organisation) { build :organisation, id: 1, internal: true } + let(:group) { build :group, id: 1, organisation: } + let(:internal_group) { build :group, id: 1, organisation: internal_organisation } + let(:group_form) { GroupForm.new(group:) } + let(:internal_group_form) { GroupForm.new(group: internal_group) } - form_documents_with_internal_id = form_documents.filter { it["id"] == 3 } - expect(form_documents_with_internal_id).to be_empty + before do + allow(GroupForm).to receive(:find_by_form_id).and_return(group_form) + allow(GroupForm).to receive(:find_by_form_id).with(3).and_return(internal_group_form) + end + + it "does not include these forms in the live_form_documents output" do + form_documents = described_class.live_form_documents.to_a + expect(form_documents.size).to eq(9) + + form_documents_with_internal_id = form_documents.filter { it["id"] == 3 } + expect(form_documents_with_internal_id).to be_empty + end end - end - def response_headers(total, offset, limit) - { - "pagination-total" => total.to_s, - "pagination-offset" => offset.to_s, - "pagination-limit" => limit.to_s, - } + def response_headers(total, offset, limit) + { + "pagination-total" => total.to_s, + "pagination-offset" => offset.to_s, + "pagination-limit" => limit.to_s, + } + end end end diff --git a/spec/services/reports/forms_csv_report_service_spec.rb b/spec/services/reports/forms_csv_report_service_spec.rb new file mode 100644 index 000000000..c6eff3072 --- /dev/null +++ b/spec/services/reports/forms_csv_report_service_spec.rb @@ -0,0 +1,53 @@ +require "rails_helper" + +RSpec.describe Reports::FormsCsvReportService do + subject(:csv_reports_service) do + described_class.new(form_documents) + end + + let(:form_documents) { JSON.parse(file_fixture("form_documents_response.json").read) } + + let(:group) { create(:group) } + + before do + GroupForm.create!(form_id: 1, group:) + GroupForm.create!(form_id: 2, group:) + GroupForm.create!(form_id: 3, group:) + GroupForm.create!(form_id: 4, group:) + end + + describe "#csv" do + it "returns a CSV with a header row and a row for each form" do + csv = csv_reports_service.csv + rows = CSV.parse(csv) + expect(rows.length).to eq 5 + end + + it "has expected values" do + csv = csv_reports_service.csv + rows = CSV.parse(csv) + expect(rows[1]).to eq([ + "1", + "live", + "All question types form", + "all-question-types-form", + group.organisation.name, + group.organisation.id.to_s, + group.name, + group.external_id, + "2025-01-02T16:24:31.203Z", + "2025-01-02T16:24:31.255Z", + "9", + "false", + "https://www.gov.uk/payments/your-payment-link", + nil, + nil, + "your.email+fakedata84701@gmail.com.gov.uk", + "08000800", + "https://www.gov.uk/help/privacy-notice", + "Test", + "email_with_csv", + ]) + end + end +end diff --git a/spec/services/reports/questions_csv_report_service_spec.rb b/spec/services/reports/questions_csv_report_service_spec.rb new file mode 100644 index 000000000..f6ccf96ab --- /dev/null +++ b/spec/services/reports/questions_csv_report_service_spec.rb @@ -0,0 +1,143 @@ +require "rails_helper" + +RSpec.describe Reports::QuestionsCsvReportService do + subject(:csv_reports_service) do + described_class.new(question_page_documents) + end + + let(:question_page_documents) { Reports::FeatureReportService.new(form_documents).questions } + let(:form_documents) { JSON.parse(file_fixture("form_documents_response.json").read) } + + let(:group) { create(:group) } + + before do + GroupForm.create!(form_id: 1, group:) + GroupForm.create!(form_id: 2, group:) + GroupForm.create!(form_id: 3, group:) + GroupForm.create!(form_id: 4, group:) + end + + describe "#csv" do + it "returns a CSV with a header row and a rows for each question" do + csv = csv_reports_service.csv + rows = CSV.parse(csv) + expect(rows.length).to eq 18 + end + + it "has expected values for text question" do + csv = csv_reports_service.csv + rows = CSV.parse(csv) + text_question_row = rows.detect { |row| row.include? "Single line of text" } + expect(text_question_row).to eq([ + "1", + "live", + "All question types form", + group.organisation.name, + group.organisation.id.to_s, + group.name, + group.external_id, + "1", + "Single line of text", + "text", + nil, + nil, + nil, + "false", + "true", + "false", + "single_line", + nil, + nil, + nil, + "{\"input_type\" => \"single_line\"}", + ]) + end + + it "has expected values for selection question" do + csv = csv_reports_service.csv + rows = CSV.parse(csv) + selection_question_row = rows.detect { |row| row.include? "Selection from a list of options" } + expect(selection_question_row).to eq([ + "1", + "live", + "All question types form", + group.organisation.name, + group.organisation.id.to_s, + group.name, + group.external_id, + "8", + "Selection from a list of options", + "selection", + nil, + nil, + nil, + "true", + "false", + "false", + nil, + "false", + "3", + nil, + "{\"only_one_option\" => \"0\", \"selection_options\" => [{\"name\" => \"Option 1\"}, {\"name\" => \"Option 2\"}, {\"name\" => \"Option 3\"}]}", + ]) + end + + it "has expected values for name question" do + csv = csv_reports_service.csv + rows = CSV.parse(csv) + name_question_row = rows.detect { |row| row.include? "What’s your name?" } + expect(name_question_row).to eq([ + "3", + "live", + "Branch route form", + group.organisation.name, + group.organisation.id.to_s, + group.name, + group.external_id, + "2", + "What’s your name?", + "name", + nil, + nil, + nil, + "false", + "false", + "false", + "full_name", + nil, + nil, + "false", + "{\"input_type\" => \"full_name\", \"title_needed\" => false}", + ]) + end + + it "has expected values for question with routing conditions" do + csv = csv_reports_service.csv + rows = CSV.parse(csv) + routing_question_row = rows.detect { |row| row.include? "How many times have you filled out this form?" } + expect(routing_question_row).to eq([ + "3", + "live", + "Branch route form", + group.organisation.name, + group.organisation.id.to_s, + group.name, + group.external_id, + "1", + "How many times have you filled out this form?", + "selection", + nil, + nil, + nil, + "false", + "false", + "true", + nil, + "true", + "2", + nil, + "{\"only_one_option\" => \"true\", \"selection_options\" => [{\"name\" => \"Once\"}, {\"name\" => \"More than once\"}]}", + ]) + end + end +end diff --git a/spec/views/reports/feature_report.html.erb_spec.rb b/spec/views/reports/feature_report.html.erb_spec.rb new file mode 100644 index 000000000..9d8cd48ca --- /dev/null +++ b/spec/views/reports/feature_report.html.erb_spec.rb @@ -0,0 +1,202 @@ +require "rails_helper" + +describe "reports/feature_report" do + let(:report) {} + let(:records) { [] } + + before do + controller.request.path_parameters[:action] = report + + render locals: { report:, records: } + end + + context "with forms_with_csv_submission_enabled report" do + let(:report) { "forms_with_csv_submission_enabled" } + let(:records) do + [ + { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } }, + { "form_id" => 3, "content" => { "name" => "Branch route form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } }, + ] + end + + describe "page title" do + it "matches the heading" do + expect(view.content_for(:title)).to eq "Live forms with CSV submission enabled" + end + end + + it "has a back link to feature usage report" do + expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) + end + + it "has a link to download the CSV" do + expect(rendered).to have_link("Download data about all live forms with CSV submission enabled as a CSV file", href: report_forms_with_csv_submission_enabled_path(format: :csv)) + end + + describe "questions table" do + it "has the correct headers" do + page = Capybara.string(rendered.html) + within(page.find(".govuk-table__head")) do + expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" + expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" + end + end + + it "has rows for each question" do + page = Capybara.string(rendered.html) + within(page.find_all(".govuk-table__row")[1]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + end + within(page.find_all(".govuk-table__row")[2]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + end + end + end + end + + context "with forms_with_payments report" do + let(:report) { "forms_with_payments" } + let(:records) do + [ + { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } }, + { "form_id" => 3, "content" => { "name" => "Branch route form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } }, + ] + end + + describe "page title" do + it "matches the heading" do + expect(view.content_for(:title)).to eq "Live forms with payments" + end + end + + it "has a back link to feature usage report" do + expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) + end + + it "has a link to download the CSV" do + expect(rendered).to have_link("Download data about all live forms with payments as a CSV file", href: report_forms_with_payments_path(format: :csv)) + end + + describe "questions table" do + it "has the correct headers" do + page = Capybara.string(rendered.html) + within(page.find(".govuk-table__head")) do + expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" + expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" + end + end + + it "has rows for each question" do + page = Capybara.string(rendered.html) + within(page.find_all(".govuk-table__row")[1]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + end + within(page.find_all(".govuk-table__row")[2]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + end + end + end + end + + context "with forms_with_routes report" do + let(:report) { "forms_with_routes" } + let(:records) do + [ + { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } }, "metadata" => { "number_of_routes" => 1 } }, + { "form_id" => 3, "content" => { "name" => "Branch route form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } }, "metadata" => { "number_of_routes" => 2 } }, + ] + end + + describe "page title" do + it "matches the heading" do + expect(view.content_for(:title)).to eq "Live forms with routes" + end + end + + it "has a back link to feature usage report" do + expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) + end + + it "has a link to download the CSV" do + expect(rendered).to have_link("Download data about all live forms with routes as a CSV file", href: report_forms_with_routes_path(format: :csv)) + end + + describe "questions table" do + it "has the correct headers" do + page = Capybara.string(rendered.html) + within(page.find(".govuk-table__head")) do + expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" + expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" + expect(page.find_all(".govuk-table__header"[2])).to have_text "Number of routes" + end + end + + it "has rows for each question" do + page = Capybara.string(rendered.html) + within(page.find_all(".govuk-table__row")[1]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + expect(page.find_all(".govuk-table__cell"[2])).to have_text "1" + end + within(page.find_all(".govuk-table__row")[2]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + expect(page.find_all(".govuk-table__cell"[2])).to have_text "2" + end + end + end + end + + context "with questions_with_add_another_answer report" do + let(:report) { "questions_with_add_another_answer" } + let(:records) do + [ + { "type" => "question_page", "data" => { "question_text" => "email address" }, "form" => { "form_id" => 1, "content" => { "name" => "all question types form" }, "group" => { "organisation" => { "name" => "government digital service" } } } }, + { "type" => "question_page", "data" => { "question_text" => "what’s your email address?" }, "form" => { "form_id" => 3, "content" => { "name" => "branch route form" }, "group" => { "organisation" => { "name" => "government digital service" } } } }, + ] + end + + describe "page title" do + it "matches the heading" do + expect(view.content_for(:title)).to eq "Questions with add another answer in live forms" + end + end + + it "has a back link to feature usage report" do + expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) + end + + it "has a link to download the CSV" do + expect(rendered).to have_link("Download all questions with add another answer in live forms as a CSV file", href: report_questions_with_add_another_answer_path(format: :csv)) + end + + describe "questions table" do + it "has the correct headers" do + page = Capybara.string(rendered.html) + within(page.find(".govuk-table__head")) do + expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" + expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" + expect(page.find_all(".govuk-table__header"[2])).to have_text "Question text" + end + end + + it "has rows for each question" do + page = Capybara.string(rendered.html) + within(page.find_all(".govuk-table__row")[1]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + expect(page.find_all(".govuk-table__cell"[2])).to have_text "Email address" + end + within(page.find_all(".govuk-table__row")[2]) do + expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" + expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" + expect(page.find_all(".govuk-table__cell"[2])).to have_text "What's your email address?" + end + end + end + end +end diff --git a/spec/views/reports/features.html.erb_spec.rb b/spec/views/reports/features.html.erb_spec.rb index 7942960d0..e1976b111 100644 --- a/spec/views/reports/features.html.erb_spec.rb +++ b/spec/views/reports/features.html.erb_spec.rb @@ -3,8 +3,8 @@ describe "reports/features.html.erb" do let(:report) do { - total_live_forms: 3, - live_forms_with_answer_type: { + total_forms: 3, + forms_with_answer_type: { address: 1, date: 1, email: 1, @@ -16,7 +16,7 @@ selection: 3, text: 3, }.with_indifferent_access, - live_steps_with_answer_type: { + steps_with_answer_type: { address: 1, date: 1, email: 1, @@ -28,10 +28,10 @@ selection: 4, text: 5, }.with_indifferent_access, - live_forms_with_payment: 1, - live_forms_with_routing: 2, - live_forms_with_add_another_answer: 3, - live_forms_with_csv_submission_enabled: 2, + forms_with_payment: 1, + forms_with_routing: 2, + forms_with_add_another_answer: 3, + forms_with_csv_submission_enabled: 2, } end @@ -54,7 +54,7 @@ end it "includes the number of total live forms" do - expect(rendered).to have_css(".govuk-summary-list__row", text: "Total live forms#{report[:total_live_forms]}") + expect(rendered).to have_css(".govuk-summary-list__row", text: "Total live forms#{report[:total_forms]}") end Page::ANSWER_TYPES.map(&:to_sym).each do |answer_type| @@ -63,49 +63,49 @@ end it "includes the number of live forms with #{answer_type}" do - expect(rendered).to have_css("[data-live-forms-with-answer-type-#{answer_type.to_s.dasherize}]", text: report[:live_forms_with_answer_type][answer_type].to_s) + expect(rendered).to have_css("[data-live-forms-with-answer-type-#{answer_type.to_s.dasherize}]", text: report[:forms_with_answer_type][answer_type].to_s) end it "includes the number of live pages with #{answer_type}" do - expect(rendered).to have_css("[data-live-pages-with-answer-type-#{answer_type.to_s.dasherize}]", text: report[:live_steps_with_answer_type][answer_type].to_s) + expect(rendered).to have_css("[data-live-pages-with-answer-type-#{answer_type.to_s.dasherize}]", text: report[:steps_with_answer_type][answer_type].to_s) end end context "when an answer type is missing from the data" do let(:report) do { - total_live_forms: 3, - live_forms_with_answer_type: { address: 1 }, - live_steps_with_answer_type: { address: 1 }, - live_forms_with_payment: 1, - live_forms_with_routing: 2, - live_forms_with_add_another_answer: 3, - live_forms_with_csv_submission_enabled: 2, + total_forms: 3, + forms_with_answer_type: { address: 1 }, + steps_with_answer_type: { address: 1 }, + forms_with_payment: 1, + forms_with_routing: 2, + forms_with_add_another_answer: 3, + forms_with_csv_submission_enabled: 2, } end - it "displays 0 for live_forms_with_answer_type" do + it "displays 0 for forms_with_answer_type" do expect(rendered).to have_css("[data-live-forms-with-answer-type-number]", text: "0") end - it "displays 0 for live_steps_with_answer_type" do + it "displays 0 for steps_with_answer_type" do expect(rendered).to have_css("[data-live-pages-with-answer-type-number]", text: "0") end end it "includes the number of live forms with routes" do - expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with routes#{report[:live_forms_with_routing]}") + expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with routes#{report[:forms_with_routing]}") end it "includes the number of live forms with payments" do - expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with payments#{report[:live_forms_with_payment]}") + expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with payments#{report[:forms_with_payment]}") end it "includes the number of live forms with add another answer" do - expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with add another answer#{report[:live_forms_with_add_another_answer]}") + expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with add another answer#{report[:forms_with_add_another_answer]}") end it "includes the number of live forms with CSV submission enabled" do - expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with CSV submission enabled#{report[:live_forms_with_csv_submission_enabled]}") + expect(rendered).to have_css(".govuk-summary-list__row", text: "Live forms with CSV submission enabled#{report[:forms_with_csv_submission_enabled]}") end end diff --git a/spec/views/reports/forms_with_csv_submission_enabled.html.erb_spec.rb b/spec/views/reports/forms_with_csv_submission_enabled.html.erb_spec.rb deleted file mode 100644 index 05c7fa133..000000000 --- a/spec/views/reports/forms_with_csv_submission_enabled.html.erb_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -require "rails_helper" - -describe "reports/forms_with_csv_submission_enabled.html.erb" do - let(:forms) do - [ - { - form_name: "All question types form", - form_id: 1, - organisation_name: "Government Digital Service", - }, - { - form_name: "Branch route form", - form_id: 3, - organisation_name: "Government Digital Service", - }, - ] - end - - before do - render template: "reports/forms_with_csv_submission_enabled", locals: { forms: } - end - - describe "page title" do - it "matches the heading" do - expect(view.content_for(:title)).to eq "Live forms with CSV submission enabled" - end - end - - it "has a back link to feature usage report" do - expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) - end - - it "has a link to download the CSV" do - expect(rendered).to have_link("Download data about all live forms with CSV submission enabled as a CSV file", href: report_live_forms_with_csv_submission_enabled_csv_path) - end - - describe "questions table" do - it "has the correct headers" do - page = Capybara.string(rendered.html) - within(page.find(".govuk-table__head")) do - expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" - expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" - end - end - - it "has rows for each question" do - page = Capybara.string(rendered.html) - within(page.find_all(".govuk-table__row")[1]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - end - within(page.find_all(".govuk-table__row")[2]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - end - end - end -end diff --git a/spec/views/reports/forms_with_payments.html.erb_spec.rb b/spec/views/reports/forms_with_payments.html.erb_spec.rb deleted file mode 100644 index e8fec4211..000000000 --- a/spec/views/reports/forms_with_payments.html.erb_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -require "rails_helper" - -describe "reports/forms_with_payments.html.erb" do - let(:forms) do - [ - { - form_name: "All question types form", - form_id: 1, - organisation_name: "Government Digital Service", - }, - { - form_name: "Branch route form", - form_id: 3, - organisation_name: "Government Digital Service", - }, - ] - end - - before do - render template: "reports/forms_with_payments", locals: { forms: } - end - - describe "page title" do - it "matches the heading" do - expect(view.content_for(:title)).to eq "Live forms with payments" - end - end - - it "has a back link to feature usage report" do - expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) - end - - it "has a link to download the CSV" do - expect(rendered).to have_link("Download data about all live forms with payments as a CSV file", href: report_live_forms_with_payments_csv_path) - end - - describe "questions table" do - it "has the correct headers" do - page = Capybara.string(rendered.html) - within(page.find(".govuk-table__head")) do - expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" - expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" - end - end - - it "has rows for each question" do - page = Capybara.string(rendered.html) - within(page.find_all(".govuk-table__row")[1]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - end - within(page.find_all(".govuk-table__row")[2]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - end - end - end -end diff --git a/spec/views/reports/forms_with_routes.html.erb_spec.rb b/spec/views/reports/forms_with_routes.html.erb_spec.rb deleted file mode 100644 index 7e1947a4d..000000000 --- a/spec/views/reports/forms_with_routes.html.erb_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -require "rails_helper" - -describe "reports/forms_with_routes.html.erb" do - let(:forms) do - [ - { - form_name: "All question types form", - form_id: 1, - organisation_name: "Government Digital Service", - number_of_routes: 1, - }, - { - form_name: "Branch route form", - form_id: 3, - organisation_name: "Government Digital Service", - number_of_routes: 2, - }, - ] - end - - before do - render template: "reports/forms_with_routes", locals: { forms: } - end - - describe "page title" do - it "matches the heading" do - expect(view.content_for(:title)).to eq "Live forms with routes" - end - end - - it "has a back link to feature usage report" do - expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) - end - - it "has a link to download the CSV" do - expect(rendered).to have_link("Download data about all live forms with routes as a CSV file", href: report_live_forms_with_routes_csv_path) - end - - describe "questions table" do - it "has the correct headers" do - page = Capybara.string(rendered.html) - within(page.find(".govuk-table__head")) do - expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" - expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" - expect(page.find_all(".govuk-table__header"[2])).to have_text "Number of routes" - end - end - - it "has rows for each question" do - page = Capybara.string(rendered.html) - within(page.find_all(".govuk-table__row")[1]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - expect(page.find_all(".govuk-table__cell"[2])).to have_text "1" - end - within(page.find_all(".govuk-table__row")[2]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - expect(page.find_all(".govuk-table__cell"[2])).to have_text "2" - end - end - end -end diff --git a/spec/views/reports/questions_with_add_another_answer.html.erb_spec.rb b/spec/views/reports/questions_with_add_another_answer.html.erb_spec.rb deleted file mode 100644 index a19bfcd0e..000000000 --- a/spec/views/reports/questions_with_add_another_answer.html.erb_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -require "rails_helper" - -describe "reports/questions_with_add_another_answer.html.erb" do - let(:questions) do - [ - { - form_name: "All question types form", - form_id: 1, - organisation_name: "Government Digital Service", - question_text: "Email address", - }, - { - form_name: "Branch route form", - form_id: 3, - organisation_name: "Government Digital Service", - question_text: "What’s your email address?", - }, - ] - end - - before do - render template: "reports/questions_with_add_another_answer", locals: { answer_type: "email", questions: } - end - - describe "page title" do - it "matches the heading" do - expect(view.content_for(:title)).to eq "Questions with add another answer in live forms" - end - end - - it "has a back link to feature usage report" do - expect(view.content_for(:back_link)).to have_link("Back to feature and answer type usage", href: report_features_path) - end - - it "has a link to download the CSV" do - expect(rendered).to have_link("Download all questions with add another answer in live forms as a CSV file", href: report_live_questions_with_add_another_answer_csv_path) - end - - describe "questions table" do - it "has the correct headers" do - page = Capybara.string(rendered.html) - within(page.find(".govuk-table__head")) do - expect(page.find_all(".govuk-table__header"[0])).to have_text "Form name" - expect(page.find_all(".govuk-table__header"[1])).to have_text "Organisation" - expect(page.find_all(".govuk-table__header"[2])).to have_text "Question text" - end - end - - it "has rows for each question" do - page = Capybara.string(rendered.html) - within(page.find_all(".govuk-table__row")[1]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "All question types form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - expect(page.find_all(".govuk-table__cell"[2])).to have_text "Email address" - end - within(page.find_all(".govuk-table__row")[2]) do - expect(page.find_all(".govuk-table__cell"[0])).to have_text "Branch route form" - expect(page.find_all(".govuk-table__cell"[1])).to have_text "Government Digital Service" - expect(page.find_all(".govuk-table__cell"[2])).to have_text "What's your email address?" - end - end - end -end diff --git a/spec/views/reports/questions_with_answer_type.html.erb_spec.rb b/spec/views/reports/questions_with_answer_type.html.erb_spec.rb index 09f2b7ca7..1c72a4add 100644 --- a/spec/views/reports/questions_with_answer_type.html.erb_spec.rb +++ b/spec/views/reports/questions_with_answer_type.html.erb_spec.rb @@ -1,25 +1,15 @@ require "rails_helper" -describe "reports/questions_with_answer_type.html.erb" do +describe "reports/questions_with_answer_type" do let(:questions) do [ - { - form_name: "All question types form", - form_id: 1, - organisation_name: "Government Digital Service", - question_text: "Email address", - }, - { - form_name: "Branch route form", - form_id: 3, - organisation_name: "Government Digital Service", - question_text: "What’s your email address?", - }, + { "data" => { "question_text" => "Email address" }, "form" => { "form_id" => 1, "content" => { "name" => "All question types form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } } }, + { "data" => { "question_text" => "What’s your email address?" }, "form" => { "form_id" => 3, "content" => { "name" => "Branch route form" }, "group" => { "organisation" => { "name" => "Government Digital Service" } } } }, ] end before do - render template: "reports/questions_with_answer_type", locals: { answer_type: "email", questions: } + render locals: { answer_type: "email", questions: } end describe "page title" do