From 524e1babc3677600bb61a800f58caad725d9fda5 Mon Sep 17 00:00:00 2001 From: Ben Baumann <34001723+benbaumann95@users.noreply.github.com> Date: Fri, 2 Jan 2026 14:40:27 +0000 Subject: [PATCH 1/2] Add end-to-end system tests for validation, consultation and assessement workflows for pre-apps --- .../spec/system/assessment_workflow_spec.rb | 579 ++++++++++++++++++ .../spec/system/consultation_workflow_spec.rb | 323 ++++++++++ .../spec/system/validation_workflow_spec.rb | 406 ++++++++++++ 3 files changed, 1308 insertions(+) create mode 100644 engines/bops_preapps/spec/system/assessment_workflow_spec.rb create mode 100644 engines/bops_preapps/spec/system/consultation_workflow_spec.rb create mode 100644 engines/bops_preapps/spec/system/validation_workflow_spec.rb diff --git a/engines/bops_preapps/spec/system/assessment_workflow_spec.rb b/engines/bops_preapps/spec/system/assessment_workflow_spec.rb new file mode 100644 index 0000000000..c386c3a70a --- /dev/null +++ b/engines/bops_preapps/spec/system/assessment_workflow_spec.rb @@ -0,0 +1,579 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe "Pre-application assessment workflow", type: :system do + let(:local_authority) { create(:local_authority, :default) } + let(:assessor) { create(:user, :assessor, local_authority:, name: "Alice Smith") } + let(:reviewer) { create(:user, :reviewer, local_authority:, name: "Bob Jones") } + let(:case_record) { build(:case_record, user: assessor, local_authority:) } + + let!(:application_type) { create(:application_type, :prior_approval, local_authority:) } + let!(:requirement) { create(:local_authority_requirement, local_authority:, category: "drawings", description: "Floor plans") } + let!(:policy_area) { create(:local_authority_policy_area, local_authority:, description: "Design") } + let!(:policy_reference) { create(:local_authority_policy_reference, local_authority:, code: "LP1", description: "Local design policy") } + + let(:planning_application) do + create(:planning_application, :pre_application, :in_assessment, + local_authority:, + case_record:, + recommended_application_type: application_type) + end + + before do + application_type.update!(requirements: [requirement]) + end + + describe "end-to-end assessment workflow" do + it "completes all assessment tasks in sequence with correct status transitions and icons" do + sign_in(assessor) + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + expect(page).to have_css(".bops-sidebar") + expect(page).to have_content("Assessment") + + within ".bops-sidebar" do + expect(page).to have_content("Check application") + expect(page).to have_content("Additional services") + expect(page).to have_content("Assessment summaries") + expect(page).to have_content("Complete assessment") + end + + check_app_details_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/check-application/check-application-details") + check_consultees_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/check-application/check-consultees-consulted") + check_site_history_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/check-application/check-site-history") + site_visit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/additional-services/site-visit") + meeting_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/additional-services/meeting") + site_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/site-description") + considerations_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/planning-considerations-and-advice") + heads_of_terms_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/suggest-heads-of-terms") + summary_of_advice_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/summary-of-advice") + choose_type_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/choose-application-type") + requirements_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/check-and-add-requirements") + review_submit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/review-and-submit-pre-application") + + expect(check_app_details_task).to be_not_started + expect(check_consultees_task).to be_not_started + expect(check_site_history_task).to be_not_started + expect(site_visit_task).to be_not_started + expect(meeting_task).to be_not_started + expect(site_description_task).to be_not_started + expect(considerations_task).to be_not_started + expect(heads_of_terms_task).to be_not_started + expect(summary_of_advice_task).to be_not_started + expect(choose_type_task).to be_not_started + expect(requirements_task).to be_not_started + expect(review_submit_task).to be_not_started + + within ".bops-sidebar" do + expect(page).to have_css("svg[aria-label='Not started']", minimum: 10) + end + + within ".bops-sidebar" do + click_link "Check application details" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/check-application/check-application-details") + expect(page).to have_selector("h1", text: "Check application details") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check application details") + expect(page).to have_css("a[aria-current='page']", text: "Check application details") + end + + within_fieldset("Does the description match the development or use in the plans?") { choose "Yes" } + within_fieldset("Are the plans consistent with each other?") { choose "Yes" } + within_fieldset("Are the proposal details consistent with the plans?") { choose "Yes" } + within_fieldset("Is the site map correct?") { choose "Yes" } + + click_button "Save and mark as complete" + + expect(check_app_details_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check application details") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Check consultees consulted" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/check-application/check-consultees-consulted") + expect(page).to have_selector("h1", text: "Check consultees consulted") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check consultees consulted") + end + + click_button "Save and mark as complete" + + expect(check_consultees_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check consultees consulted") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Check site history" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/check-application/check-site-history") + expect(page).to have_selector("h1", text: "Check site history") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check site history") + end + + click_button "Save and mark as complete" + + expect(check_site_history_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check site history") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Site visit" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/additional-services/site-visit") + expect(page).to have_selector("h1", text: "Site visit") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Site visit") + end + + expect(page).to have_content("No site visits have been recorded yet") + + click_button "Save and mark as complete" + + expect(site_visit_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Site visit") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Meeting" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/additional-services/meeting") + expect(page).to have_selector("h1", text: "Meeting") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Meeting") + end + + click_button "Save and mark as complete" + + expect(meeting_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Meeting") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Site description" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/site-description") + expect(page).to have_selector("h1", text: "Site description") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Site description") + end + + fill_in "Description of the site", with: "A detached house with garden." + + click_button "Save changes" + + expect(page).to have_content("Site description was successfully updated") + expect(site_description_task.reload).to be_in_progress + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Site description") do + expect(page).to have_css("svg[aria-label='In progress']") + end + end + + click_button "Save and mark as complete" + + expect(site_description_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Site description") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Planning considerations and advice" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/planning-considerations-and-advice") + expect(page).to have_selector("h1", text: "Planning considerations and advice") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Planning considerations and advice") + end + + click_button "Save and mark as complete" + + expect(considerations_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Planning considerations and advice") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Suggest heads of terms" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/suggest-heads-of-terms") + expect(page).to have_selector("h1", text: "Suggest heads of terms") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Suggest heads of terms") + end + + click_button "Save and mark as complete" + + expect(heads_of_terms_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Suggest heads of terms") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Summary of advice" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/summary-of-advice") + expect(page).to have_selector("h1", text: "Summary of advice") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Summary of advice") + end + + choose "Likely to be supported (recommended based on considerations)" + fill_in "Enter summary of planning considerations and advice. This should summarise any changes the applicant needs to make before they make an application.", with: "The proposal is acceptable." + + click_button "Save and mark as complete" + + expect(page).to have_content("Summary of advice successfully updated") + expect(summary_of_advice_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Summary of advice") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Choose application type" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/complete-assessment/choose-application-type") + expect(page).to have_selector("h1", text: "Choose application type") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Choose application type") + end + + expect(page).to have_content("What application type would the applicant need to apply for next?") + + select "Prior Approval - Larger extension to a house", from: "What application type would the applicant need to apply for next?" + click_button "Save and mark as complete" + + expect(page).to have_content("Recommended application type was successfully chosen") + expect(choose_type_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Choose application type") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Check and add requirements" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/complete-assessment/check-and-add-requirements") + expect(page).to have_selector("h1", text: "Check and add requirements") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check and add requirements") + end + + click_button "Save and mark as complete" + + expect(page).to have_content("Requirements were successfully saved") + expect(requirements_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check and add requirements") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Review and submit pre-application" + end + + expect(page).to have_selector("h1", text: "Pre-application report") + + click_button "Confirm and submit recommendation" + + expect(page).to have_content("Pre-application report submitted for review") + expect(review_submit_task.reload).to be_completed + + [ + check_app_details_task, + check_consultees_task, + check_site_history_task, + site_visit_task, + meeting_task, + site_description_task, + considerations_task, + heads_of_terms_task, + summary_of_advice_task, + choose_type_task, + requirements_task, + review_submit_task + ].each do |task| + expect(task.reload).to be_completed + end + end + + it "shows in progress status when task is partially completed" do + sign_in(assessor) + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + within ".bops-sidebar" do + click_link "Site description" + end + + fill_in "Description of the site", with: "Some text" + click_button "Save changes" + + expect(page).to have_content("Site description was successfully updated") + + site_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/site-description") + expect(site_description_task.reload).to be_in_progress + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Site description") do + expect(page).to have_css("svg[aria-label='In progress']") + end + end + end + + it "navigates correctly between all assessment task sections" do + sign_in(assessor) + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + tasks = [ + {name: "Check application details", path: "check-application/check-application-details"}, + {name: "Check consultees consulted", path: "check-application/check-consultees-consulted"}, + {name: "Check site history", path: "check-application/check-site-history"}, + {name: "Site visit", path: "additional-services/site-visit"}, + {name: "Meeting", path: "additional-services/meeting"}, + {name: "Site description", path: "assessment-summaries/site-description"}, + {name: "Planning considerations and advice", path: "assessment-summaries/planning-considerations-and-advice"}, + {name: "Suggest heads of terms", path: "assessment-summaries/suggest-heads-of-terms"}, + {name: "Summary of advice", path: "assessment-summaries/summary-of-advice"}, + {name: "Choose application type", path: "complete-assessment/choose-application-type"}, + {name: "Check and add requirements", path: "complete-assessment/check-and-add-requirements"} + ] + + tasks.each do |task| + within ".bops-sidebar" do + click_link task[:name] + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/#{task[:path]}") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: task[:name]) + expect(page).to have_css("a[aria-current='page']", text: task[:name]) + end + end + end + + it "hides buttons when application is determined" do + planning_application.update!(status: "determined", determined_at: Time.current) + + sign_in(assessor) + visit "/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/site-description" + + expect(page).not_to have_button("Save and mark as complete") + expect(page).not_to have_button("Save changes") + end + + it "maintains sidebar scroll position across navigation", js: true do + sign_in(assessor) + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + within ".bops-sidebar" do + click_link "Summary of advice" + end + + expect(page).to have_css(".bops-sidebar[data-controller='sidebar-scroll']") + end + end + + describe "review and submit workflow with reviewer" do + before do + planning_application.case_record.update!(user: assessor) + create(:assessment_detail, planning_application:, category: :summary_of_work, entry: "Test summary") + create(:assessment_detail, planning_application:, category: :site_description, entry: "Test site") + create(:assessment_detail, planning_application:, category: :consultation_summary, entry: "Test consultation") + planning_application.create_consideration_set! if planning_application.consideration_set.nil? + end + + it "handles the full review workflow with action_required status" do + sign_in(assessor) + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + within ".bops-sidebar" do + click_link "Review and submit pre-application" + end + + review_submit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/review-and-submit-pre-application") + expect(review_submit_task).to be_not_started + + click_button "Confirm and submit recommendation" + + expect(page).to have_content("Pre-application report submitted for review") + expect(review_submit_task.reload).to be_completed + + sign_out(assessor) + sign_in(reviewer) + + visit "/reports/planning_applications/#{planning_application.reference}?origin=review_and_submit_pre_application" + + within_fieldset "Do you agree with the advice?" do + choose "No (return the case for assessment)" + fill_in "Reviewer comment", with: "Needs more detail on considerations" + end + + click_button "Confirm and submit pre-application report" + + expect(page).to have_content("Pre-application report has been sent back to the case officer for amendments") + expect(review_submit_task.reload).to be_action_required + + sign_out(reviewer) + sign_in(assessor) + + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Review and submit pre-application") do + expect(page).to have_css("svg[aria-label='Action required']") + end + end + + within ".bops-sidebar" do + click_link "Review and submit pre-application" + end + + fill_in "Assessor comment", with: "Added the requested details" + click_button "Confirm and submit recommendation" + + expect(page).to have_content("Pre-application report submitted for review") + expect(review_submit_task.reload).to be_completed + + sign_out(assessor) + sign_in(reviewer) + + visit "/reports/planning_applications/#{planning_application.reference}?origin=review_and_submit_pre_application" + + within_fieldset "Do you agree with the advice?" do + choose "Yes" + end + + click_button "Confirm and submit pre-application report" + + expect(page).to have_content("Pre-application report has been sent to the applicant") + expect(review_submit_task.reload).to be_completed + end + end + + describe "site visit recording" do + it "allows adding a site visit with date and comments" do + sign_in(assessor) + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + within ".bops-sidebar" do + click_link "Site visit" + end + + site_visit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/additional-services/site-visit") + expect(site_visit_task).to be_not_started + + expect(page).to have_content("No site visits have been recorded yet") + + within "#new-site-visit-form" do + click_button "Add site visit" + end + + yesterday = Date.yesterday + within "#new-site-visit-form" do + fill_in "Day", with: yesterday.day + fill_in "Month", with: yesterday.month + fill_in "Year", with: yesterday.year + fill_in "Comment", with: "Inspected front and rear of property" + click_button "Add site visit" + end + + click_button "Save changes" + + expect(site_visit_task.reload).to be_in_progress + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Site visit") do + expect(page).to have_css("svg[aria-label='In progress']") + end + end + + expect(page).not_to have_content("No site visits have been recorded yet") + + within("#site-visit-history") do + expect(page).to have_content("Inspected front and rear of property") + end + end + end + + describe "check application details with issues" do + it "shows request links when selecting No for checks" do + sign_in(assessor) + visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + + within ".bops-sidebar" do + click_link "Check application details" + end + + within_fieldset("Does the description match the development or use in the plans?") { choose "No" } + + expect(page).to have_link("Request a change to the description") + + within_fieldset("Are the plans consistent with each other?") { choose "No" } + + expect(page).to have_link("Request a new document") + end + end +end diff --git a/engines/bops_preapps/spec/system/consultation_workflow_spec.rb b/engines/bops_preapps/spec/system/consultation_workflow_spec.rb new file mode 100644 index 0000000000..22854913e4 --- /dev/null +++ b/engines/bops_preapps/spec/system/consultation_workflow_spec.rb @@ -0,0 +1,323 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe "Pre-application consultation workflow", type: :system do + let(:local_authority) { create(:local_authority, :default) } + let(:user) { create(:user, local_authority:, name: "Alice Smith") } + + let(:planning_application) do + create(:planning_application, :pre_application, :not_started, local_authority:) + end + + before do + sign_in(user) + end + + describe "end-to-end consultation workflow" do + it "completes all consultation tasks in sequence with correct status transitions and icons" do + visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + + expect(page).to have_css(".bops-sidebar") + expect(page).to have_content("Consultation") + + determine_task = planning_application.case_record.find_task_by_slug_path!("consultees/determine-consultation-requirement") + consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") + add_consultees_task = consultees_section.tasks.find_by(slug: "add-and-assign-consultees") + send_emails_task = consultees_section.tasks.find_by(slug: "send-emails-to-consultees") + view_responses_task = consultees_section.tasks.find_by(slug: "view-consultee-responses") + + expect(determine_task).to be_not_started + expect(add_consultees_task).to be_hidden + expect(send_emails_task).to be_hidden + expect(view_responses_task).to be_hidden + + within ".bops-sidebar" do + expect(page).to have_link("Determine consultation requirement") + expect(page).not_to have_link("Add and assign consultees") + expect(page).not_to have_link("Send emails to consultees") + expect(page).not_to have_link("View consultee responses") + end + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Determine consultation requirement") do + expect(page).to have_css("svg[aria-label='Not started']") + end + end + + expect(page).to have_selector("h1", text: "Determine consultation requirement") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Determine consultation requirement") + expect(page).to have_css("a[aria-current='page']", text: "Determine consultation requirement") + end + + expect(page).to have_content("Is consultation required?") + expect(page).to have_field("Yes") + expect(page).to have_field("No") + + choose "Yes" + click_button "Save and mark as complete" + + expect(page).to have_content("Consultation requirement was successfully updated") + expect(determine_task.reload).to be_completed + expect(planning_application.reload.consultation_required).to be true + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Determine consultation requirement") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + expect(add_consultees_task.reload).not_to be_hidden + expect(send_emails_task.reload).not_to be_hidden + expect(view_responses_task.reload).not_to be_hidden + + within ".bops-sidebar" do + expect(page).to have_link("Add and assign consultees") + expect(page).to have_link("Send emails to consultees") + expect(page).to have_link("View consultee responses") + end + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Add and assign consultees") do + expect(page).to have_css("svg[aria-label='Not started']") + end + within(".bops-sidebar__task", text: "Send emails to consultees") do + expect(page).to have_css("svg[aria-label='Not started']") + end + within(".bops-sidebar__task", text: "View consultee responses") do + expect(page).to have_css("svg[aria-label='Not started']") + end + end + + within ".bops-sidebar" do + click_link "Add and assign consultees" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/add-and-assign-consultees") + expect(page).to have_selector("h1", text: "Add and assign consultees") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Add and assign consultees") + end + + expect(page).to have_content("Select constraints that require consultation") + expect(page).to have_content("Assign consultees to each constraint") + + click_button "Save changes" + + expect(page).to have_content("Consultee assignments were successfully saved") + expect(add_consultees_task.reload).to be_in_progress + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Add and assign consultees") do + expect(page).to have_css("svg[aria-label='In progress']") + end + end + + click_button "Save and mark as complete" + + expect(page).to have_content("Consultee assignments were successfully saved") + expect(add_consultees_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Add and assign consultees") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Send emails to consultees" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/send-emails-to-consultees") + expect(page).to have_selector("h1", text: "Send emails to consultees") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Send emails to consultees") + end + + send_emails_task.complete! + + within ".bops-sidebar" do + click_link "View consultee responses" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/view-consultee-responses") + expect(page).to have_selector("h1", text: "View consultee responses") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "View consultee responses") + end + + expect(page).to have_content("No consultees have been added yet") + + click_button "Save and mark as complete" + + expect(page).to have_content("Consultee responses were successfully reviewed") + expect(view_responses_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "View consultee responses") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + [determine_task, add_consultees_task, send_emails_task, view_responses_task].each do |task| + expect(task.reload).to be_completed + end + end + + it "hides consultation tasks when consultation is not required" do + visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + + choose "No" + click_button "Save and mark as complete" + + expect(page).to have_content("Consultation requirement was successfully updated") + expect(planning_application.reload.consultation_required).to be false + + consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") + add_consultees_task = consultees_section.tasks.find_by(slug: "add-and-assign-consultees") + send_emails_task = consultees_section.tasks.find_by(slug: "send-emails-to-consultees") + view_responses_task = consultees_section.tasks.find_by(slug: "view-consultee-responses") + + expect(add_consultees_task.reload).to be_hidden + expect(send_emails_task.reload).to be_hidden + expect(view_responses_task.reload).to be_hidden + + within ".bops-sidebar" do + expect(page).not_to have_link("Add and assign consultees") + expect(page).not_to have_link("Send emails to consultees") + expect(page).not_to have_link("View consultee responses") + end + end + + it "navigates correctly between all consultation tasks" do + planning_application.update!(consultation_required: true) + consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") + consultees_section.tasks.update_all(hidden: false) + + tasks = [ + {name: "Determine consultation requirement", path: "determine-consultation-requirement"}, + {name: "Add and assign consultees", path: "add-and-assign-consultees"}, + {name: "Send emails to consultees", path: "send-emails-to-consultees"}, + {name: "View consultee responses", path: "view-consultee-responses"} + ] + + visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + + tasks.each do |task| + within ".bops-sidebar" do + click_link task[:name] + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/#{task[:path]}") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: task[:name]) + expect(page).to have_css("a[aria-current='page']", text: task[:name]) + end + end + end + + it "hides buttons when application is determined" do + planning_application.update!(status: "determined", determined_at: Time.current, consultation_required: true) + consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") + consultees_section.tasks.update_all(hidden: false) + + visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + + expect(page).not_to have_button("Save and mark as complete") + expect(page).not_to have_button("Save changes") + + visit "/preapps/#{planning_application.reference}/consultees/add-and-assign-consultees" + + expect(page).not_to have_button("Save and mark as complete") + expect(page).not_to have_button("Save changes") + end + + it "shows warning when changing consultation requirement with existing consultees" do + planning_application.update!(consultation_required: true) + consultation = planning_application.consultation || planning_application.create_consultation! + create(:consultee, consultation:, name: "Test Consultee") + + visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + + expect(page).to have_selector(".govuk-warning-text", text: "Changing this answer to \"No\" will remove all consultees") + end + + it "maintains sidebar scroll position across navigation", js: true do + planning_application.update!(consultation_required: true) + consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") + consultees_section.tasks.update_all(hidden: false) + + visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + + within ".bops-sidebar" do + click_link "View consultee responses" + end + + expect(page).to have_css(".bops-sidebar[data-controller='sidebar-scroll']") + end + end + + describe "consultee response handling" do + let(:consultation) { planning_application.consultation || planning_application.create_consultation! } + let!(:consultee_approved) do + consultee = create(:consultee, :consulted, consultation:, name: "Thames Water", status: :responded) + create(:consultee_response, consultee:, summary_tag: :approved, response: "No objection", email: consultee.email_address) + consultee + end + let!(:consultee_objected) do + consultee = create(:consultee, :consulted, consultation:, name: "Natural England", status: :responded) + create(:consultee_response, consultee:, summary_tag: :objected, response: "We object", email: consultee.email_address) + consultee + end + + before do + planning_application.update!(consultation_required: true) + consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") + consultees_section.tasks.update_all(hidden: false) + end + + it "displays consultee responses with correct status tags" do + visit "/preapps/#{planning_application.reference}/consultees/view-consultee-responses" + + expect(page).to have_content("Response summary") + expect(page).to have_content("Total consultees") + + expect(page).to have_link("All (2)") + expect(page).to have_link("No objection (1)") + expect(page).to have_link("Objection (1)") + + within("#consultee-tab-all") do + within(".consultee-panel", text: "Thames Water") do + expect(page).to have_content("No objection") + end + within(".consultee-panel", text: "Natural England") do + expect(page).to have_content("Objection") + end + end + end + + it "filters consultees by response type when clicking tabs" do + visit "/preapps/#{planning_application.reference}/consultees/view-consultee-responses" + + click_link "No objection (1)" + + within("#consultee-tab-approved") do + expect(page).to have_content("Thames Water") + expect(page).not_to have_content("Natural England") + end + + click_link "Objection (1)" + + within("#consultee-tab-objected") do + expect(page).to have_content("Natural England") + expect(page).not_to have_content("Thames Water") + end + end + end +end diff --git a/engines/bops_preapps/spec/system/validation_workflow_spec.rb b/engines/bops_preapps/spec/system/validation_workflow_spec.rb new file mode 100644 index 0000000000..d9d6150c3c --- /dev/null +++ b/engines/bops_preapps/spec/system/validation_workflow_spec.rb @@ -0,0 +1,406 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe "Pre-application validation workflow", type: :system do + let(:local_authority) { create(:local_authority, :default) } + let(:api_user) { create(:api_user, :planx, local_authority:) } + let(:user) { create(:user, local_authority:, name: "Alice Smith") } + + let(:boundary_geojson) do + { + type: "Feature", + properties: {}, + geometry: { + type: "Polygon", + coordinates: [[[-0.054597, 51.537331], [-0.054588, 51.537287], [-0.054453, 51.537313], [-0.054597, 51.537331]]] + } + } + end + + let(:proposal_details) do + [{"question" => "Planning Pre-Application Advice Services", "responses" => [{"value" => "Householder (£100)"}], "metadata" => {}}] + end + + let(:planning_application) do + create(:planning_application, :pre_application, :not_started, :with_constraints, + local_authority:, + api_user:, + boundary_geojson:, + proposal_details:) + end + + before do + sign_in(user) + end + + describe "end-to-end validation workflow" do + it "completes all validation tasks in sequence with correct status transitions and icons" do + visit "/planning_applications/#{planning_application.reference}/validation/tasks" + + expect(page).to have_css(".bops-sidebar") + expect(page).to have_content("Validation") + + within ".bops-sidebar" do + expect(page).to have_content("Check, tag, and confirm documents") + expect(page).to have_content("Check application details") + expect(page).to have_content("Other validation issues") + expect(page).to have_content("Review") + end + + review_documents_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-tag-and-confirm-documents/review-documents") + check_red_line_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-red-line-boundary") + check_constraints_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-constraints") + check_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-description") + add_reporting_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/add-reporting-details") + check_fee_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-fee") + other_requests_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/other-validation-issues/other-validation-requests") + review_requests_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/review/review-validation-requests") + send_decision_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/review/send-validation-decision") + + expect(review_documents_task).to be_not_started + expect(check_red_line_task).to be_not_started + expect(check_constraints_task).to be_not_started + expect(check_description_task).to be_not_started + expect(add_reporting_task).to be_not_started + expect(check_fee_task).to be_not_started + expect(other_requests_task).to be_not_started + expect(review_requests_task).to be_not_started + expect(send_decision_task).to be_not_started + + within ".bops-sidebar" do + expect(page).to have_css("svg[aria-label='Not started']", minimum: 7) + end + + within ".bops-sidebar" do + click_link "Review documents" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-tag-and-confirm-documents/review-documents") + expect(page).to have_selector("h1", text: "Review documents") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Review documents") + expect(page).to have_css("a[aria-current='page']", text: "Review documents") + end + + expect(page).to have_content("There are no active documents") + + click_button "Save and mark as complete" + + expect(page).to have_content("Successfully updated document review") + expect(review_documents_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Review documents") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Check red line boundary" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-red-line-boundary") + expect(page).to have_content("Check the digital red line boundary") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check red line boundary") + end + + expect(page).to have_field("Yes") + expect(page).to have_field("No") + + choose "Yes" + click_button "Save and mark as complete" + + expect(page).to have_content("Red line boundary check was successfully saved") + expect(check_red_line_task.reload).to be_completed + expect(planning_application.reload.valid_red_line_boundary).to be true + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check red line boundary") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Check constraints" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-constraints") + expect(page).to have_content("Check constraints") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check constraints") + end + + within(".identified-constraints-table") do + expect(page).to have_text("Conservation area") + expect(page).to have_text("Listed building outline") + end + + click_button "Save and mark as complete" + + expect(page).to have_content("Constraints were successfully marked as reviewed") + expect(check_constraints_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check constraints") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Check description" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-description") + expect(page).to have_selector("h1", text: "Check description") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check description") + end + + expect(page).to have_content("Does the description match the development or use in the plans?") + + choose "Yes" + click_button "Save and mark as complete" + + expect(page).to have_content("Description check was successfully saved") + expect(check_description_task.reload).to be_completed + expect(planning_application.reload.valid_description).to be true + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check description") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Add reporting details" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/add-reporting-details") + expect(page).to have_selector("h1", text: "Add reporting details") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Add reporting details") + end + + expect(page).to have_content("Is the local planning authority the owner of this land?") + + page.first(:radio_button, "No").choose + + click_button "Save and mark as complete" + + expect(page).to have_content("Reporting details were successfully saved") + expect(add_reporting_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Add reporting details") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Check fee" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-fee") + expect(page).to have_content("Check the application fee") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Check fee") + end + + expect(page).to have_content("Payment information") + expect(page).to have_content("Fee calculation") + expect(page).to have_content("Householder") + expect(page).to have_content("£100") + + choose "Yes" + click_button "Save and mark as complete" + + expect(page).to have_content("Fee check was successfully saved") + expect(check_fee_task.reload).to be_completed + expect(planning_application.reload.valid_fee).to be true + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check fee") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Other validation requests" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/other-validation-issues/other-validation-requests") + expect(page).to have_selector("h1", text: "Other validation requests") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Other validation requests") + end + + expect(page).to have_content("No other validation requests have been added") + + click_button "Save and mark as complete" + + expect(page).to have_content("Other validation requests was successfully saved") + expect(other_requests_task.reload).to be_completed + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Other validation requests") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + within ".bops-sidebar" do + click_link "Review validation requests" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/review/review-validation-requests") + expect(page).to have_selector("h1", text: "Review validation requests") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Review validation requests") + end + + expect(page).to have_content("There are no active validation requests") + + within ".bops-sidebar" do + click_link "Send validation decision" + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/review/send-validation-decision") + expect(page).to have_selector("h1", text: "Send validation decision") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: "Send validation decision") + end + + expect(page).to have_content("The application has not been marked as valid or invalid yet") + expect(page).to have_button("Mark the application as valid") + + click_button "Mark the application as valid" + + expect(page).to have_content("The application is marked as valid") + expect(send_decision_task.reload).to be_completed + expect(planning_application.reload).to be_valid + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Send validation decision") do + expect(page).to have_css("svg[aria-label='Completed']") + end + end + + [ + review_documents_task, + check_red_line_task, + check_constraints_task, + check_description_task, + add_reporting_task, + check_fee_task, + other_requests_task, + send_decision_task + ].each do |task| + expect(task.reload).to be_completed + end + end + + it "shows in progress status when task is partially completed" do + visit "/planning_applications/#{planning_application.reference}/validation/tasks" + + within ".bops-sidebar" do + click_link "Check constraints" + end + + click_button "Save changes" + + expect(page).to have_content("Constraints were successfully marked as reviewed") + + check_constraints_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-constraints") + expect(check_constraints_task.reload).to be_in_progress + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check constraints") do + expect(page).to have_css("svg[aria-label='In progress']") + end + end + end + + it "handles validation request flow with status transitions" do + visit "/planning_applications/#{planning_application.reference}/validation/tasks" + + within ".bops-sidebar" do + click_link "Check description" + end + + choose "No" + click_button "Save and mark as complete" + + expect(page).to have_current_path("/planning_applications/#{planning_application.reference}/validation/validation_requests/new?type=description_change") + + check_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-description") + expect(check_description_task.reload).to be_in_progress + expect(planning_application.reload.valid_description).to be false + + visit "/planning_applications/#{planning_application.reference}/validation/tasks" + + within ".bops-sidebar" do + within(".bops-sidebar__task", text: "Check description") do + expect(page).to have_css("svg[aria-label='In progress']") + end + end + end + + it "navigates correctly between all validation task sections" do + visit "/planning_applications/#{planning_application.reference}/validation/tasks" + + sections = [ + {name: "Review documents", path: "check-tag-and-confirm-documents/review-documents"}, + {name: "Check red line boundary", path: "check-application-details/check-red-line-boundary"}, + {name: "Check constraints", path: "check-application-details/check-constraints"}, + {name: "Check description", path: "check-application-details/check-description"}, + {name: "Add reporting details", path: "check-application-details/add-reporting-details"}, + {name: "Check fee", path: "check-application-details/check-fee"}, + {name: "Other validation requests", path: "other-validation-issues/other-validation-requests"}, + {name: "Review validation requests", path: "review/review-validation-requests"}, + {name: "Send validation decision", path: "review/send-validation-decision"} + ] + + sections.each do |section| + within ".bops-sidebar" do + click_link section[:name] + end + + expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/#{section[:path]}") + + within ".bops-sidebar" do + expect(page).to have_css(".bops-sidebar__task--active", text: section[:name]) + expect(page).to have_css("a[aria-current='page']", text: section[:name]) + end + end + end + + it "hides buttons when application is determined" do + planning_application.update!(status: "determined", determined_at: Time.current) + + visit "/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-description" + + expect(page).not_to have_button("Save and mark as complete") + expect(page).not_to have_button("Save changes") + end + + it "maintains sidebar scroll position across navigation", js: true do + visit "/planning_applications/#{planning_application.reference}/validation/tasks" + + within ".bops-sidebar" do + click_link "Send validation decision" + end + + expect(page).to have_css(".bops-sidebar[data-controller='sidebar-scroll']") + end + end +end From 015227c435309d41397a0379bd27b3b12d3aaa41 Mon Sep 17 00:00:00 2001 From: Ben Baumann <34001723+benbaumann95@users.noreply.github.com> Date: Mon, 5 Jan 2026 13:01:29 +0000 Subject: [PATCH 2/2] Add helpers and selectors to improve spec readability --- .../spec/system/assessment_workflow_spec.rb | 382 ++++++------------ .../spec/system/consultation_workflow_spec.rb | 193 ++++----- .../spec/system/validation_workflow_spec.rb | 262 ++++-------- spec/support/preapp_task_helpers.rb | 98 +++++ spec/support/sidebar_selectors.rb | 28 ++ 5 files changed, 401 insertions(+), 562 deletions(-) create mode 100644 spec/support/preapp_task_helpers.rb create mode 100644 spec/support/sidebar_selectors.rb diff --git a/engines/bops_preapps/spec/system/assessment_workflow_spec.rb b/engines/bops_preapps/spec/system/assessment_workflow_spec.rb index c386c3a70a..5dd617c53d 100644 --- a/engines/bops_preapps/spec/system/assessment_workflow_spec.rb +++ b/engines/bops_preapps/spec/system/assessment_workflow_spec.rb @@ -8,8 +8,8 @@ let(:reviewer) { create(:user, :reviewer, local_authority:, name: "Bob Jones") } let(:case_record) { build(:case_record, user: assessor, local_authority:) } - let!(:application_type) { create(:application_type, :prior_approval, local_authority:) } let!(:requirement) { create(:local_authority_requirement, local_authority:, category: "drawings", description: "Floor plans") } + let!(:application_type) { create(:application_type, :prior_approval, local_authority:, requirements: [requirement]) } let!(:policy_area) { create(:local_authority_policy_area, local_authority:, description: "Design") } let!(:policy_reference) { create(:local_authority_policy_reference, local_authority:, code: "LP1", description: "Local design policy") } @@ -20,66 +20,38 @@ recommended_application_type: application_type) end - before do - application_type.update!(requirements: [requirement]) - end + let(:reference) { planning_application.reference } describe "end-to-end assessment workflow" do it "completes all assessment tasks in sequence with correct status transitions and icons" do sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" - expect(page).to have_css(".bops-sidebar") + expect(page).to have_selector(:sidebar) expect(page).to have_content("Assessment") - within ".bops-sidebar" do + within :sidebar do expect(page).to have_content("Check application") expect(page).to have_content("Additional services") expect(page).to have_content("Assessment summaries") expect(page).to have_content("Complete assessment") end - check_app_details_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/check-application/check-application-details") - check_consultees_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/check-application/check-consultees-consulted") - check_site_history_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/check-application/check-site-history") - site_visit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/additional-services/site-visit") - meeting_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/additional-services/meeting") - site_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/site-description") - considerations_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/planning-considerations-and-advice") - heads_of_terms_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/suggest-heads-of-terms") - summary_of_advice_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/summary-of-advice") - choose_type_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/choose-application-type") - requirements_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/check-and-add-requirements") - review_submit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/review-and-submit-pre-application") - - expect(check_app_details_task).to be_not_started - expect(check_consultees_task).to be_not_started - expect(check_site_history_task).to be_not_started - expect(site_visit_task).to be_not_started - expect(meeting_task).to be_not_started - expect(site_description_task).to be_not_started - expect(considerations_task).to be_not_started - expect(heads_of_terms_task).to be_not_started - expect(summary_of_advice_task).to be_not_started - expect(choose_type_task).to be_not_started - expect(requirements_task).to be_not_started - expect(review_submit_task).to be_not_started - - within ".bops-sidebar" do + assessment_tasks.each do |t| + expect(t).to be_not_started + end + + within :sidebar do expect(page).to have_css("svg[aria-label='Not started']", minimum: 10) end - within ".bops-sidebar" do + within :sidebar do click_link "Check application details" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/check-application/check-application-details") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/check-application/check-application-details") expect(page).to have_selector("h1", text: "Check application details") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check application details") - expect(page).to have_css("a[aria-current='page']", text: "Check application details") - end + expect(page).to have_selector(:active_sidebar_task, "Check application details") within_fieldset("Does the description match the development or use in the plans?") { choose "Yes" } within_fieldset("Are the plans consistent with each other?") { choose "Yes" } @@ -88,186 +60,117 @@ click_button "Save and mark as complete" - expect(check_app_details_task.reload).to be_completed + expect(task("Check application details").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Check application details") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check application details") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Check consultees consulted" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/check-application/check-consultees-consulted") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/check-application/check-consultees-consulted") expect(page).to have_selector("h1", text: "Check consultees consulted") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check consultees consulted") - end + expect(page).to have_selector(:active_sidebar_task, "Check consultees consulted") click_button "Save and mark as complete" - expect(check_consultees_task.reload).to be_completed + expect(task("Check consultees consulted").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Check consultees consulted") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check consultees consulted") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Check site history" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/check-application/check-site-history") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/check-application/check-site-history") expect(page).to have_selector("h1", text: "Check site history") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check site history") - end + expect(page).to have_selector(:active_sidebar_task, "Check site history") click_button "Save and mark as complete" - expect(check_site_history_task.reload).to be_completed - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check site history") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end + expect(task("Check site history").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Check site history") - within ".bops-sidebar" do + within :sidebar do click_link "Site visit" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/additional-services/site-visit") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/additional-services/site-visit") expect(page).to have_selector("h1", text: "Site visit") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Site visit") - end + expect(page).to have_selector(:active_sidebar_task, "Site visit") expect(page).to have_content("No site visits have been recorded yet") click_button "Save and mark as complete" - expect(site_visit_task.reload).to be_completed - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Site visit") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end + expect(task("Site visit").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Site visit") - within ".bops-sidebar" do + within :sidebar do click_link "Meeting" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/additional-services/meeting") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/additional-services/meeting") expect(page).to have_selector("h1", text: "Meeting") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Meeting") - end + expect(page).to have_selector(:active_sidebar_task, "Meeting") click_button "Save and mark as complete" - expect(meeting_task.reload).to be_completed + expect(task("Meeting").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Meeting") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Meeting") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Site description" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/site-description") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/assessment-summaries/site-description") expect(page).to have_selector("h1", text: "Site description") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Site description") - end + expect(page).to have_selector(:active_sidebar_task, "Site description") fill_in "Description of the site", with: "A detached house with garden." click_button "Save changes" expect(page).to have_content("Site description was successfully updated") - expect(site_description_task.reload).to be_in_progress - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Site description") do - expect(page).to have_css("svg[aria-label='In progress']") - end - end + expect(task("Site description").reload).to be_in_progress + expect(page).to have_selector(:in_progress_sidebar_task, "Site description") click_button "Save and mark as complete" - expect(site_description_task.reload).to be_completed + expect(task("Site description").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Site description") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Site description") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Planning considerations and advice" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/planning-considerations-and-advice") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/assessment-summaries/planning-considerations-and-advice") expect(page).to have_selector("h1", text: "Planning considerations and advice") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Planning considerations and advice") - end + expect(page).to have_selector(:active_sidebar_task, "Planning considerations and advice") click_button "Save and mark as complete" - expect(considerations_task.reload).to be_completed + expect(task("Planning considerations and advice").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Planning considerations and advice") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Planning considerations and advice") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Suggest heads of terms" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/suggest-heads-of-terms") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/assessment-summaries/suggest-heads-of-terms") expect(page).to have_selector("h1", text: "Suggest heads of terms") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Suggest heads of terms") - end + expect(page).to have_selector(:active_sidebar_task, "Suggest heads of terms") click_button "Save and mark as complete" - expect(heads_of_terms_task.reload).to be_completed - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Suggest heads of terms") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end + expect(task("Suggest heads of terms").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Suggest heads of terms") - within ".bops-sidebar" do + within :sidebar do click_link "Summary of advice" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/summary-of-advice") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/assessment-summaries/summary-of-advice") expect(page).to have_selector("h1", text: "Summary of advice") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Summary of advice") - end + expect(page).to have_selector(:active_sidebar_task, "Summary of advice") choose "Likely to be supported (recommended based on considerations)" fill_in "Enter summary of planning considerations and advice. This should summarise any changes the applicant needs to make before they make an application.", with: "The proposal is acceptable." @@ -275,24 +178,16 @@ click_button "Save and mark as complete" expect(page).to have_content("Summary of advice successfully updated") - expect(summary_of_advice_task.reload).to be_completed + expect(task("Summary of advice").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Summary of advice") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Summary of advice") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Choose application type" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/complete-assessment/choose-application-type") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/complete-assessment/choose-application-type") expect(page).to have_selector("h1", text: "Choose application type") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Choose application type") - end + expect(page).to have_selector(:active_sidebar_task, "Choose application type") expect(page).to have_content("What application type would the applicant need to apply for next?") @@ -300,37 +195,24 @@ click_button "Save and mark as complete" expect(page).to have_content("Recommended application type was successfully chosen") - expect(choose_type_task.reload).to be_completed + expect(task("Choose application type").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Choose application type") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Choose application type") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Check and add requirements" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/complete-assessment/check-and-add-requirements") + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/complete-assessment/check-and-add-requirements") expect(page).to have_selector("h1", text: "Check and add requirements") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check and add requirements") - end + expect(page).to have_selector(:active_sidebar_task, "Check and add requirements") click_button "Save and mark as complete" expect(page).to have_content("Requirements were successfully saved") - expect(requirements_task.reload).to be_completed + expect(task("Check and add requirements").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Check and add requirements") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check and add requirements") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Review and submit pre-application" end @@ -339,31 +221,16 @@ click_button "Confirm and submit recommendation" expect(page).to have_content("Pre-application report submitted for review") - expect(review_submit_task.reload).to be_completed - - [ - check_app_details_task, - check_consultees_task, - check_site_history_task, - site_visit_task, - meeting_task, - site_description_task, - considerations_task, - heads_of_terms_task, - summary_of_advice_task, - choose_type_task, - requirements_task, - review_submit_task - ].each do |task| - expect(task.reload).to be_completed - end + expect(task("Review and submit pre-application").reload).to be_completed end it "shows in progress status when task is partially completed" do sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" + + expect(page).to have_selector(:sidebar) - within ".bops-sidebar" do + within :sidebar do click_link "Site description" end @@ -371,20 +238,15 @@ click_button "Save changes" expect(page).to have_content("Site description was successfully updated") - - site_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/assessment-summaries/site-description") - expect(site_description_task.reload).to be_in_progress - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Site description") do - expect(page).to have_css("svg[aria-label='In progress']") - end - end + expect(task("Site description").reload).to be_in_progress + expect(page).to have_selector(:in_progress_sidebar_task, "Site description") end it "navigates correctly between all assessment task sections" do sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" + + expect(page).to have_selector(:sidebar) tasks = [ {name: "Check application details", path: "check-application/check-application-details"}, @@ -400,17 +262,13 @@ {name: "Check and add requirements", path: "complete-assessment/check-and-add-requirements"} ] - tasks.each do |task| - within ".bops-sidebar" do - click_link task[:name] + tasks.each do |t| + within :sidebar do + click_link t[:name] end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-assess/#{task[:path]}") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: task[:name]) - expect(page).to have_css("a[aria-current='page']", text: task[:name]) - end + expect(page).to have_current_path("/preapps/#{reference}/check-and-assess/#{t[:path]}") + expect(page).to have_selector(:active_sidebar_task, t[:name]) end end @@ -418,7 +276,7 @@ planning_application.update!(status: "determined", determined_at: Time.current) sign_in(assessor) - visit "/preapps/#{planning_application.reference}/check-and-assess/assessment-summaries/site-description" + visit "/preapps/#{reference}/check-and-assess/assessment-summaries/site-description" expect(page).not_to have_button("Save and mark as complete") expect(page).not_to have_button("Save changes") @@ -426,13 +284,24 @@ it "maintains sidebar scroll position across navigation", js: true do sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" + + expect(page).to have_selector(:sidebar) - within ".bops-sidebar" do + within :sidebar do click_link "Summary of advice" end - expect(page).to have_css(".bops-sidebar[data-controller='sidebar-scroll']") + expect(page).to have_css("nav.bops-sidebar[data-controller='sidebar-scroll']") + + initial_scroll = page.evaluate_script("document.querySelector('nav.bops-sidebar').scrollTop") + + within :sidebar do + click_link "Check application details" + end + + final_scroll = page.evaluate_script("document.querySelector('nav.bops-sidebar').scrollTop") + expect(final_scroll).to eq(initial_scroll) end end @@ -447,24 +316,25 @@ it "handles the full review workflow with action_required status" do sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" + + expect(page).to have_selector(:sidebar) - within ".bops-sidebar" do + within :sidebar do click_link "Review and submit pre-application" end - review_submit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/complete-assessment/review-and-submit-pre-application") - expect(review_submit_task).to be_not_started + expect(task("Review and submit pre-application")).to be_not_started click_button "Confirm and submit recommendation" expect(page).to have_content("Pre-application report submitted for review") - expect(review_submit_task.reload).to be_completed + expect(task("Review and submit pre-application").reload).to be_completed sign_out(assessor) sign_in(reviewer) - visit "/reports/planning_applications/#{planning_application.reference}?origin=review_and_submit_pre_application" + visit "/reports/planning_applications/#{reference}?origin=review_and_submit_pre_application" within_fieldset "Do you agree with the advice?" do choose "No (return the case for assessment)" @@ -474,20 +344,16 @@ click_button "Confirm and submit pre-application report" expect(page).to have_content("Pre-application report has been sent back to the case officer for amendments") - expect(review_submit_task.reload).to be_action_required + expect(task("Review and submit pre-application").reload).to be_action_required sign_out(reviewer) sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Review and submit pre-application") do - expect(page).to have_css("svg[aria-label='Action required']") - end - end + expect(page).to have_selector(:action_required_sidebar_task, "Review and submit pre-application") - within ".bops-sidebar" do + within :sidebar do click_link "Review and submit pre-application" end @@ -495,12 +361,12 @@ click_button "Confirm and submit recommendation" expect(page).to have_content("Pre-application report submitted for review") - expect(review_submit_task.reload).to be_completed + expect(task("Review and submit pre-application").reload).to be_completed sign_out(assessor) sign_in(reviewer) - visit "/reports/planning_applications/#{planning_application.reference}?origin=review_and_submit_pre_application" + visit "/reports/planning_applications/#{reference}?origin=review_and_submit_pre_application" within_fieldset "Do you agree with the advice?" do choose "Yes" @@ -509,21 +375,22 @@ click_button "Confirm and submit pre-application report" expect(page).to have_content("Pre-application report has been sent to the applicant") - expect(review_submit_task.reload).to be_completed + expect(task("Review and submit pre-application").reload).to be_completed end end describe "site visit recording" do it "allows adding a site visit with date and comments" do sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" - within ".bops-sidebar" do + expect(page).to have_selector(:sidebar) + + within :sidebar do click_link "Site visit" end - site_visit_task = planning_application.case_record.find_task_by_slug_path!("check-and-assess/additional-services/site-visit") - expect(site_visit_task).to be_not_started + expect(task("Site visit")).to be_not_started expect(page).to have_content("No site visits have been recorded yet") @@ -542,13 +409,8 @@ click_button "Save changes" - expect(site_visit_task.reload).to be_in_progress - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Site visit") do - expect(page).to have_css("svg[aria-label='In progress']") - end - end + expect(task("Site visit").reload).to be_in_progress + expect(page).to have_selector(:in_progress_sidebar_task, "Site visit") expect(page).not_to have_content("No site visits have been recorded yet") @@ -561,9 +423,11 @@ describe "check application details with issues" do it "shows request links when selecting No for checks" do sign_in(assessor) - visit "/planning_applications/#{planning_application.reference}/assessment/tasks" + visit "/planning_applications/#{reference}/assessment/tasks" + + expect(page).to have_selector(:sidebar) - within ".bops-sidebar" do + within :sidebar do click_link "Check application details" end diff --git a/engines/bops_preapps/spec/system/consultation_workflow_spec.rb b/engines/bops_preapps/spec/system/consultation_workflow_spec.rb index 22854913e4..ad2033b2b0 100644 --- a/engines/bops_preapps/spec/system/consultation_workflow_spec.rb +++ b/engines/bops_preapps/spec/system/consultation_workflow_spec.rb @@ -10,47 +10,34 @@ create(:planning_application, :pre_application, :not_started, local_authority:) end + let(:reference) { planning_application.reference } + before do sign_in(user) end describe "end-to-end consultation workflow" do it "completes all consultation tasks in sequence with correct status transitions and icons" do - visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + visit "/preapps/#{reference}/consultees/determine-consultation-requirement" - expect(page).to have_css(".bops-sidebar") + expect(page).to have_selector(:sidebar) expect(page).to have_content("Consultation") - determine_task = planning_application.case_record.find_task_by_slug_path!("consultees/determine-consultation-requirement") - consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") - add_consultees_task = consultees_section.tasks.find_by(slug: "add-and-assign-consultees") - send_emails_task = consultees_section.tasks.find_by(slug: "send-emails-to-consultees") - view_responses_task = consultees_section.tasks.find_by(slug: "view-consultee-responses") - - expect(determine_task).to be_not_started - expect(add_consultees_task).to be_hidden - expect(send_emails_task).to be_hidden - expect(view_responses_task).to be_hidden + expect(task("Determine consultation requirement")).to be_not_started + expect(task("Add and assign consultees")).to be_hidden + expect(task("Send emails to consultees")).to be_hidden + expect(task("View consultee responses")).to be_hidden - within ".bops-sidebar" do + within :sidebar do expect(page).to have_link("Determine consultation requirement") expect(page).not_to have_link("Add and assign consultees") expect(page).not_to have_link("Send emails to consultees") expect(page).not_to have_link("View consultee responses") end - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Determine consultation requirement") do - expect(page).to have_css("svg[aria-label='Not started']") - end - end - + expect(page).to have_selector(:not_started_sidebar_task, "Determine consultation requirement") expect(page).to have_selector("h1", text: "Determine consultation requirement") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Determine consultation requirement") - expect(page).to have_css("a[aria-current='page']", text: "Determine consultation requirement") - end + expect(page).to have_selector(:active_sidebar_task, "Determine consultation requirement") expect(page).to have_content("Is consultation required?") expect(page).to have_field("Yes") @@ -60,47 +47,31 @@ click_button "Save and mark as complete" expect(page).to have_content("Consultation requirement was successfully updated") - expect(determine_task.reload).to be_completed + expect(task("Determine consultation requirement").reload).to be_completed expect(planning_application.reload.consultation_required).to be true + expect(page).to have_selector(:completed_sidebar_task, "Determine consultation requirement") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Determine consultation requirement") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - expect(add_consultees_task.reload).not_to be_hidden - expect(send_emails_task.reload).not_to be_hidden - expect(view_responses_task.reload).not_to be_hidden + expect(task("Add and assign consultees").reload).not_to be_hidden + expect(task("Send emails to consultees").reload).not_to be_hidden + expect(task("View consultee responses").reload).not_to be_hidden - within ".bops-sidebar" do + within :sidebar do expect(page).to have_link("Add and assign consultees") expect(page).to have_link("Send emails to consultees") expect(page).to have_link("View consultee responses") end - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Add and assign consultees") do - expect(page).to have_css("svg[aria-label='Not started']") - end - within(".bops-sidebar__task", text: "Send emails to consultees") do - expect(page).to have_css("svg[aria-label='Not started']") - end - within(".bops-sidebar__task", text: "View consultee responses") do - expect(page).to have_css("svg[aria-label='Not started']") - end - end + expect(page).to have_selector(:not_started_sidebar_task, "Add and assign consultees") + expect(page).to have_selector(:not_started_sidebar_task, "Send emails to consultees") + expect(page).to have_selector(:not_started_sidebar_task, "View consultee responses") - within ".bops-sidebar" do + within :sidebar do click_link "Add and assign consultees" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/add-and-assign-consultees") + expect(page).to have_current_path("/preapps/#{reference}/consultees/add-and-assign-consultees") expect(page).to have_selector("h1", text: "Add and assign consultees") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Add and assign consultees") - end + expect(page).to have_selector(:active_sidebar_task, "Add and assign consultees") expect(page).to have_content("Select constraints that require consultation") expect(page).to have_content("Assign consultees to each constraint") @@ -108,69 +79,53 @@ click_button "Save changes" expect(page).to have_content("Consultee assignments were successfully saved") - expect(add_consultees_task.reload).to be_in_progress - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Add and assign consultees") do - expect(page).to have_css("svg[aria-label='In progress']") - end - end + expect(task("Add and assign consultees").reload).to be_in_progress + expect(page).to have_selector(:in_progress_sidebar_task, "Add and assign consultees") click_button "Save and mark as complete" expect(page).to have_content("Consultee assignments were successfully saved") - expect(add_consultees_task.reload).to be_completed + expect(task("Add and assign consultees").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Add and assign consultees") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Add and assign consultees") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Send emails to consultees" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/send-emails-to-consultees") + expect(page).to have_current_path("/preapps/#{reference}/consultees/send-emails-to-consultees") expect(page).to have_selector("h1", text: "Send emails to consultees") + expect(page).to have_selector(:active_sidebar_task, "Send emails to consultees") - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Send emails to consultees") - end - - send_emails_task.complete! + task("Send emails to consultees").complete! - within ".bops-sidebar" do + within :sidebar do click_link "View consultee responses" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/view-consultee-responses") + expect(page).to have_current_path("/preapps/#{reference}/consultees/view-consultee-responses") expect(page).to have_selector("h1", text: "View consultee responses") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "View consultee responses") - end + expect(page).to have_selector(:active_sidebar_task, "View consultee responses") expect(page).to have_content("No consultees have been added yet") click_button "Save and mark as complete" expect(page).to have_content("Consultee responses were successfully reviewed") - expect(view_responses_task.reload).to be_completed - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "View consultee responses") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - [determine_task, add_consultees_task, send_emails_task, view_responses_task].each do |task| - expect(task.reload).to be_completed + expect(task("View consultee responses").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "View consultee responses") + + [ + task("Determine consultation requirement"), + task("Add and assign consultees"), + task("Send emails to consultees"), + task("View consultee responses") + ].each do |t| + expect(t.reload).to be_completed end end it "hides consultation tasks when consultation is not required" do - visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + visit "/preapps/#{reference}/consultees/determine-consultation-requirement" choose "No" click_button "Save and mark as complete" @@ -178,16 +133,11 @@ expect(page).to have_content("Consultation requirement was successfully updated") expect(planning_application.reload.consultation_required).to be false - consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") - add_consultees_task = consultees_section.tasks.find_by(slug: "add-and-assign-consultees") - send_emails_task = consultees_section.tasks.find_by(slug: "send-emails-to-consultees") - view_responses_task = consultees_section.tasks.find_by(slug: "view-consultee-responses") - - expect(add_consultees_task.reload).to be_hidden - expect(send_emails_task.reload).to be_hidden - expect(view_responses_task.reload).to be_hidden + expect(task("Add and assign consultees").reload).to be_hidden + expect(task("Send emails to consultees").reload).to be_hidden + expect(task("View consultee responses").reload).to be_hidden - within ".bops-sidebar" do + within :sidebar do expect(page).not_to have_link("Add and assign consultees") expect(page).not_to have_link("Send emails to consultees") expect(page).not_to have_link("View consultee responses") @@ -196,7 +146,6 @@ it "navigates correctly between all consultation tasks" do planning_application.update!(consultation_required: true) - consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") consultees_section.tasks.update_all(hidden: false) tasks = [ @@ -206,33 +155,28 @@ {name: "View consultee responses", path: "view-consultee-responses"} ] - visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + visit "/preapps/#{reference}/consultees/determine-consultation-requirement" - tasks.each do |task| - within ".bops-sidebar" do - click_link task[:name] + tasks.each do |t| + within :sidebar do + click_link t[:name] end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/consultees/#{task[:path]}") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: task[:name]) - expect(page).to have_css("a[aria-current='page']", text: task[:name]) - end + expect(page).to have_current_path("/preapps/#{reference}/consultees/#{t[:path]}") + expect(page).to have_selector(:active_sidebar_task, t[:name]) end end it "hides buttons when application is determined" do planning_application.update!(status: "determined", determined_at: Time.current, consultation_required: true) - consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") consultees_section.tasks.update_all(hidden: false) - visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + visit "/preapps/#{reference}/consultees/determine-consultation-requirement" expect(page).not_to have_button("Save and mark as complete") expect(page).not_to have_button("Save changes") - visit "/preapps/#{planning_application.reference}/consultees/add-and-assign-consultees" + visit "/preapps/#{reference}/consultees/add-and-assign-consultees" expect(page).not_to have_button("Save and mark as complete") expect(page).not_to have_button("Save changes") @@ -243,23 +187,31 @@ consultation = planning_application.consultation || planning_application.create_consultation! create(:consultee, consultation:, name: "Test Consultee") - visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + visit "/preapps/#{reference}/consultees/determine-consultation-requirement" expect(page).to have_selector(".govuk-warning-text", text: "Changing this answer to \"No\" will remove all consultees") end it "maintains sidebar scroll position across navigation", js: true do planning_application.update!(consultation_required: true) - consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") consultees_section.tasks.update_all(hidden: false) - visit "/preapps/#{planning_application.reference}/consultees/determine-consultation-requirement" + visit "/preapps/#{reference}/consultees/determine-consultation-requirement" - within ".bops-sidebar" do + within :sidebar do click_link "View consultee responses" end - expect(page).to have_css(".bops-sidebar[data-controller='sidebar-scroll']") + expect(page).to have_css("nav.bops-sidebar[data-controller='sidebar-scroll']") + + initial_scroll = page.evaluate_script("document.querySelector('nav.bops-sidebar').scrollTop") + + within :sidebar do + click_link "Determine consultation requirement" + end + + final_scroll = page.evaluate_script("document.querySelector('nav.bops-sidebar').scrollTop") + expect(final_scroll).to eq(initial_scroll) end end @@ -278,12 +230,11 @@ before do planning_application.update!(consultation_required: true) - consultees_section = planning_application.case_record.find_task_by_slug_path!("consultees") consultees_section.tasks.update_all(hidden: false) end it "displays consultee responses with correct status tags" do - visit "/preapps/#{planning_application.reference}/consultees/view-consultee-responses" + visit "/preapps/#{reference}/consultees/view-consultee-responses" expect(page).to have_content("Response summary") expect(page).to have_content("Total consultees") @@ -303,7 +254,7 @@ end it "filters consultees by response type when clicking tabs" do - visit "/preapps/#{planning_application.reference}/consultees/view-consultee-responses" + visit "/preapps/#{reference}/consultees/view-consultee-responses" click_link "No objection (1)" diff --git a/engines/bops_preapps/spec/system/validation_workflow_spec.rb b/engines/bops_preapps/spec/system/validation_workflow_spec.rb index d9d6150c3c..cc0f4b5087 100644 --- a/engines/bops_preapps/spec/system/validation_workflow_spec.rb +++ b/engines/bops_preapps/spec/system/validation_workflow_spec.rb @@ -30,83 +30,57 @@ proposal_details:) end + let(:reference) { planning_application.reference } + before do sign_in(user) end describe "end-to-end validation workflow" do it "completes all validation tasks in sequence with correct status transitions and icons" do - visit "/planning_applications/#{planning_application.reference}/validation/tasks" + visit "/planning_applications/#{reference}/validation/tasks" - expect(page).to have_css(".bops-sidebar") + expect(page).to have_selector(:sidebar) expect(page).to have_content("Validation") - within ".bops-sidebar" do + within :sidebar do expect(page).to have_content("Check, tag, and confirm documents") expect(page).to have_content("Check application details") expect(page).to have_content("Other validation issues") expect(page).to have_content("Review") end - review_documents_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-tag-and-confirm-documents/review-documents") - check_red_line_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-red-line-boundary") - check_constraints_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-constraints") - check_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-description") - add_reporting_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/add-reporting-details") - check_fee_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-fee") - other_requests_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/other-validation-issues/other-validation-requests") - review_requests_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/review/review-validation-requests") - send_decision_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/review/send-validation-decision") - - expect(review_documents_task).to be_not_started - expect(check_red_line_task).to be_not_started - expect(check_constraints_task).to be_not_started - expect(check_description_task).to be_not_started - expect(add_reporting_task).to be_not_started - expect(check_fee_task).to be_not_started - expect(other_requests_task).to be_not_started - expect(review_requests_task).to be_not_started - expect(send_decision_task).to be_not_started - - within ".bops-sidebar" do + validation_tasks.each do |t| + expect(t).to be_not_started + end + + within :sidebar do expect(page).to have_css("svg[aria-label='Not started']", minimum: 7) end - within ".bops-sidebar" do + within :sidebar do click_link "Review documents" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-tag-and-confirm-documents/review-documents") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/check-tag-and-confirm-documents/review-documents") expect(page).to have_selector("h1", text: "Review documents") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Review documents") - expect(page).to have_css("a[aria-current='page']", text: "Review documents") - end + expect(page).to have_selector(:active_sidebar_task, "Review documents") expect(page).to have_content("There are no active documents") click_button "Save and mark as complete" expect(page).to have_content("Successfully updated document review") - expect(review_documents_task.reload).to be_completed - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Review documents") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end + expect(task("Review documents").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Review documents") - within ".bops-sidebar" do + within :sidebar do click_link "Check red line boundary" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-red-line-boundary") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/check-application-details/check-red-line-boundary") expect(page).to have_content("Check the digital red line boundary") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check red line boundary") - end + expect(page).to have_selector(:active_sidebar_task, "Check red line boundary") expect(page).to have_field("Yes") expect(page).to have_field("No") @@ -115,25 +89,17 @@ click_button "Save and mark as complete" expect(page).to have_content("Red line boundary check was successfully saved") - expect(check_red_line_task.reload).to be_completed + expect(task("Check red line boundary").reload).to be_completed expect(planning_application.reload.valid_red_line_boundary).to be true + expect(page).to have_selector(:completed_sidebar_task, "Check red line boundary") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check red line boundary") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Check constraints" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-constraints") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/check-application-details/check-constraints") expect(page).to have_content("Check constraints") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check constraints") - end + expect(page).to have_selector(:active_sidebar_task, "Check constraints") within(".identified-constraints-table") do expect(page).to have_text("Conservation area") @@ -143,24 +109,16 @@ click_button "Save and mark as complete" expect(page).to have_content("Constraints were successfully marked as reviewed") - expect(check_constraints_task.reload).to be_completed + expect(task("Check constraints").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Check constraints") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check constraints") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Check description" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-description") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/check-application-details/check-description") expect(page).to have_selector("h1", text: "Check description") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check description") - end + expect(page).to have_selector(:active_sidebar_task, "Check description") expect(page).to have_content("Does the description match the development or use in the plans?") @@ -168,25 +126,17 @@ click_button "Save and mark as complete" expect(page).to have_content("Description check was successfully saved") - expect(check_description_task.reload).to be_completed + expect(task("Check description").reload).to be_completed expect(planning_application.reload.valid_description).to be true + expect(page).to have_selector(:completed_sidebar_task, "Check description") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check description") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Add reporting details" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/add-reporting-details") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/check-application-details/add-reporting-details") expect(page).to have_selector("h1", text: "Add reporting details") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Add reporting details") - end + expect(page).to have_selector(:active_sidebar_task, "Add reporting details") expect(page).to have_content("Is the local planning authority the owner of this land?") @@ -195,24 +145,16 @@ click_button "Save and mark as complete" expect(page).to have_content("Reporting details were successfully saved") - expect(add_reporting_task.reload).to be_completed + expect(task("Add reporting details").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Add reporting details") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Add reporting details") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Check fee" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-fee") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/check-application-details/check-fee") expect(page).to have_content("Check the application fee") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Check fee") - end + expect(page).to have_selector(:active_sidebar_task, "Check fee") expect(page).to have_content("Payment information") expect(page).to have_content("Fee calculation") @@ -223,62 +165,43 @@ click_button "Save and mark as complete" expect(page).to have_content("Fee check was successfully saved") - expect(check_fee_task.reload).to be_completed + expect(task("Check fee").reload).to be_completed expect(planning_application.reload.valid_fee).to be true + expect(page).to have_selector(:completed_sidebar_task, "Check fee") - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check fee") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - within ".bops-sidebar" do + within :sidebar do click_link "Other validation requests" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/other-validation-issues/other-validation-requests") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/other-validation-issues/other-validation-requests") expect(page).to have_selector("h1", text: "Other validation requests") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Other validation requests") - end + expect(page).to have_selector(:active_sidebar_task, "Other validation requests") expect(page).to have_content("No other validation requests have been added") click_button "Save and mark as complete" expect(page).to have_content("Other validation requests was successfully saved") - expect(other_requests_task.reload).to be_completed - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Other validation requests") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end + expect(task("Other validation requests").reload).to be_completed + expect(page).to have_selector(:completed_sidebar_task, "Other validation requests") - within ".bops-sidebar" do + within :sidebar do click_link "Review validation requests" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/review/review-validation-requests") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/review/review-validation-requests") expect(page).to have_selector("h1", text: "Review validation requests") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Review validation requests") - end + expect(page).to have_selector(:active_sidebar_task, "Review validation requests") expect(page).to have_content("There are no active validation requests") - within ".bops-sidebar" do + within :sidebar do click_link "Send validation decision" end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/review/send-validation-decision") + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/review/send-validation-decision") expect(page).to have_selector("h1", text: "Send validation decision") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: "Send validation decision") - end + expect(page).to have_selector(:active_sidebar_task, "Send validation decision") expect(page).to have_content("The application has not been marked as valid or invalid yet") expect(page).to have_button("Mark the application as valid") @@ -286,77 +209,47 @@ click_button "Mark the application as valid" expect(page).to have_content("The application is marked as valid") - expect(send_decision_task.reload).to be_completed + expect(task("Send validation decision").reload).to be_completed expect(planning_application.reload).to be_valid - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Send validation decision") do - expect(page).to have_css("svg[aria-label='Completed']") - end - end - - [ - review_documents_task, - check_red_line_task, - check_constraints_task, - check_description_task, - add_reporting_task, - check_fee_task, - other_requests_task, - send_decision_task - ].each do |task| - expect(task.reload).to be_completed - end + expect(page).to have_selector(:completed_sidebar_task, "Send validation decision") end it "shows in progress status when task is partially completed" do - visit "/planning_applications/#{planning_application.reference}/validation/tasks" + visit "/planning_applications/#{reference}/validation/tasks" - within ".bops-sidebar" do + within :sidebar do click_link "Check constraints" end click_button "Save changes" expect(page).to have_content("Constraints were successfully marked as reviewed") - - check_constraints_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-constraints") - expect(check_constraints_task.reload).to be_in_progress - - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check constraints") do - expect(page).to have_css("svg[aria-label='In progress']") - end - end + expect(task("Check constraints").reload).to be_in_progress + expect(page).to have_selector(:in_progress_sidebar_task, "Check constraints") end it "handles validation request flow with status transitions" do - visit "/planning_applications/#{planning_application.reference}/validation/tasks" + visit "/planning_applications/#{reference}/validation/tasks" - within ".bops-sidebar" do + within :sidebar do click_link "Check description" end choose "No" click_button "Save and mark as complete" - expect(page).to have_current_path("/planning_applications/#{planning_application.reference}/validation/validation_requests/new?type=description_change") + expect(page).to have_current_path("/planning_applications/#{reference}/validation/validation_requests/new?type=description_change") - check_description_task = planning_application.case_record.find_task_by_slug_path!("check-and-validate/check-application-details/check-description") - expect(check_description_task.reload).to be_in_progress + expect(task("Check description").reload).to be_in_progress expect(planning_application.reload.valid_description).to be false - visit "/planning_applications/#{planning_application.reference}/validation/tasks" + visit "/planning_applications/#{reference}/validation/tasks" - within ".bops-sidebar" do - within(".bops-sidebar__task", text: "Check description") do - expect(page).to have_css("svg[aria-label='In progress']") - end - end + expect(page).to have_selector(:in_progress_sidebar_task, "Check description") end it "navigates correctly between all validation task sections" do - visit "/planning_applications/#{planning_application.reference}/validation/tasks" + visit "/planning_applications/#{reference}/validation/tasks" sections = [ {name: "Review documents", path: "check-tag-and-confirm-documents/review-documents"}, @@ -371,36 +264,41 @@ ] sections.each do |section| - within ".bops-sidebar" do + within :sidebar do click_link section[:name] end - expect(page).to have_current_path("/preapps/#{planning_application.reference}/check-and-validate/#{section[:path]}") - - within ".bops-sidebar" do - expect(page).to have_css(".bops-sidebar__task--active", text: section[:name]) - expect(page).to have_css("a[aria-current='page']", text: section[:name]) - end + expect(page).to have_current_path("/preapps/#{reference}/check-and-validate/#{section[:path]}") + expect(page).to have_selector(:active_sidebar_task, section[:name]) end end it "hides buttons when application is determined" do planning_application.update!(status: "determined", determined_at: Time.current) - visit "/preapps/#{planning_application.reference}/check-and-validate/check-application-details/check-description" + visit "/preapps/#{reference}/check-and-validate/check-application-details/check-description" expect(page).not_to have_button("Save and mark as complete") expect(page).not_to have_button("Save changes") end it "maintains sidebar scroll position across navigation", js: true do - visit "/planning_applications/#{planning_application.reference}/validation/tasks" + visit "/planning_applications/#{reference}/validation/tasks" - within ".bops-sidebar" do + within :sidebar do click_link "Send validation decision" end - expect(page).to have_css(".bops-sidebar[data-controller='sidebar-scroll']") + expect(page).to have_css("nav.bops-sidebar[data-controller='sidebar-scroll']") + + initial_scroll = page.evaluate_script("document.querySelector('nav.bops-sidebar').scrollTop") + + within :sidebar do + click_link "Review documents" + end + + final_scroll = page.evaluate_script("document.querySelector('nav.bops-sidebar').scrollTop") + expect(final_scroll).to eq(initial_scroll) end end end diff --git a/spec/support/preapp_task_helpers.rb b/spec/support/preapp_task_helpers.rb new file mode 100644 index 0000000000..bd3e517841 --- /dev/null +++ b/spec/support/preapp_task_helpers.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +module PreappTaskHelpers + extend ActiveSupport::Concern + + class TaskDefinitions + WORKFLOW_FILE = Rails.root.join("config/task_workflows/pre_application.yml") + + Task = Struct.new(:name, :slug_path, :section, :hidden, keyword_init: true) do + def visible? + !hidden + end + end + + class << self + def all_tasks + @all_tasks ||= flatten_workflow + end + + def find_by_name(name) + all_tasks.find { |t| t.name == name } + end + + def visible_tasks_for_section(section_name) + all_tasks.select { |t| t.section == section_name && t.visible? } + end + + private + + def workflow + @workflow ||= YAML.load_file(WORKFLOW_FILE) + end + + def flatten_workflow + workflow.flat_map do |section| + collect_tasks(section["tasks"], section["name"].parameterize, section["section"]) + end + end + + def collect_tasks(nodes, parent_slug, section_name) + return [] unless nodes + + nodes.flat_map do |node| + slug = node["name"].parameterize + full_slug = [parent_slug, slug].compact.join("/") + + if node["tasks"] + collect_tasks(node["tasks"], full_slug, section_name) + else + Task.new( + name: node["name"], + slug_path: full_slug, + section: section_name, + hidden: node["hidden"] || node["status_hidden"] + ) + end + end + end + end + end + + # Usage: task("Site description"), task("Add and assign consultees"), etc. + def task(name) + task_cache[name] + end + + def task_cache + @task_cache ||= Hash.new(&method(:find_task)) + end + + def find_task(tasks, name) + if (definition = TaskDefinitions.find_by_name(name)) + tasks[name] = planning_application.case_record.find_task_by_slug_path!(definition.slug_path) + else + raise "Unknown task: #{name}. Available: #{available_tasks}" + end + end + + def available_tasks + TaskDefinitions.all_tasks.map(&:name).join(", ") + end + + def assessment_tasks + TaskDefinitions.visible_tasks_for_section("Assessment").map { |t| task(t.name) } + end + + def validation_tasks + TaskDefinitions.visible_tasks_for_section("Validation").map { |t| task(t.name) } + end + + def consultees_section + @consultees_section ||= planning_application.case_record.find_task_by_slug_path!("consultees") + end +end + +RSpec.configure do |config| + config.include PreappTaskHelpers, type: :system +end diff --git a/spec/support/sidebar_selectors.rb b/spec/support/sidebar_selectors.rb new file mode 100644 index 0000000000..3e02ddd5e1 --- /dev/null +++ b/spec/support/sidebar_selectors.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Custom Capybara selectors for sidebar navigation in workflow specs +# These provide cleaner, more semantic ways to interact with the sidebar + +Capybara.add_selector(:sidebar) do + css { "nav.bops-sidebar" } +end + +Capybara.add_selector(:active_sidebar_task) do + xpath { |name| ".//li[contains(@class, 'bops-sidebar__task--active')][.//a[normalize-space()='#{name}']]" } +end + +Capybara.add_selector(:completed_sidebar_task) do + xpath { |name| ".//li[contains(@class, 'bops-sidebar__task')][.//svg[@aria-label='Completed']][.//a[normalize-space()='#{name}']]" } +end + +Capybara.add_selector(:in_progress_sidebar_task) do + xpath { |name| ".//li[contains(@class, 'bops-sidebar__task')][.//svg[@aria-label='In progress']][.//a[normalize-space()='#{name}']]" } +end + +Capybara.add_selector(:not_started_sidebar_task) do + xpath { |name| ".//li[contains(@class, 'bops-sidebar__task')][.//svg[@aria-label='Not started']][.//a[normalize-space()='#{name}']]" } +end + +Capybara.add_selector(:action_required_sidebar_task) do + xpath { |name| ".//li[contains(@class, 'bops-sidebar__task')][.//svg[@aria-label='Action required']][.//a[normalize-space()='#{name}']]" } +end