Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/controllers/forms/exit_pages_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Forms
class ExitPagesController < PageController
def show
return redirect_to form_page_path(@step.form_id, @step.form_slug, current_context.next_page_slug) unless current_context.can_visit?(@step.page_slug)

@back_link = form_page_path(@step.form_id, @step.form_slug, @step.page_slug)
@condition = @step.routing_conditions.first
end
end
end
1 change: 1 addition & 0 deletions app/controllers/forms/page_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def back_link(page_slug)

def redirect_post_save
return redirect_to review_file_page, success: t("banner.success.file_uploaded") if answered_file_question?
return redirect_to exit_page_path(form_id: @step.form_id, form_slug: @step.form_slug, page_slug: @step.page_slug) if @step.exit_page_condition_matches?

redirect_to next_page
end
Expand Down
14 changes: 14 additions & 0 deletions app/models/step.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ def end_page?
end

def next_page_slug_after_routing
if exit_page_condition_matches?
return nil
end

if first_condition_default?
return goto_condition_page_slug(routing_conditions.first)
end
Expand Down Expand Up @@ -106,6 +110,16 @@ def conditions_with_goto_errors
end
end

def has_exit_page_condition?
return false unless routing_conditions&.first.respond_to?(:exit_page_markdown)

routing_conditions.first.exit_page_markdown.is_a?(String)
end

def exit_page_condition_matches?
first_condition_matches? && has_exit_page_condition?
end

private

def goto_condition_page_slug(condition)
Expand Down
13 changes: 13 additions & 0 deletions app/views/forms/exit_pages/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<% set_page_title(form_title(form_name: @current_context.form.name, page_name: @condition.exit_page_heading, mode: @mode)) %>

<% content_for :back_link do %>
<%= link_to "Back", @back_link, class: "govuk-back-link" %>
<% end %>

<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<h1 class="govuk-heading-l"> <%= @condition.exit_page_heading %></h1>
<%= HtmlMarkdownSanitizer.new.render_scrubbed_markdown(@condition.exit_page_markdown) %>
<%= render SupportDetailsComponent::View.new(@support_details) %>
</div>
</div>
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
answer_constraints = { answer_index: /\d+/ }
page_answer_defaults = { answer_index: 1 }

get "/:page_slug/exit" => "forms/exit_pages#show",
as: :exit_page,
constraints: page_constraints

get "/:page_slug/add-another-answer/change" => "forms/add_another_answer#show",
as: :change_add_another_answer,
constraints: page_constraints,
Expand Down
105 changes: 105 additions & 0 deletions spec/features/fill_in_form_with_exit_page_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
require "rails_helper"

feature "Fill in and submit a form with an exit page", type: :feature do
let(:routing_conditions) { [DataStruct.new(routing_page_id: 1, check_page_id: 1, answer_value: "Option 1", goto_page_id: nil, exit_page_heading: "This is an exit_page", exit_page_markdown: "This is the contents", validation_errors: [])] }
let(:steps) { [(build :v2_question_page_step, :with_selections_settings, id: 1, routing_conditions:, question_text:)] }
let(:form) { build :v2_form_document, :live?, id: 1, name: "Fill in this form", steps:, start_page: 1 }
let(:question_text) { Faker::Lorem.question }
let(:reference) { Faker::Alphanumeric.alphanumeric(number: 8).upcase }

let(:req_headers) do
{
"X-API-Token" => Settings.forms_api.auth_key,
"Accept" => "application/json",
}
end

let(:post_headers) do
{
"X-API-Token" => Settings.forms_api.auth_key,
"Content-Type" => "application/json",
}
end

before do
ActiveResource::HttpMock.respond_to do |mock|
mock.get "/api/v2/forms/1/live", req_headers, form.to_json, 200
end

allow(ReferenceNumberService).to receive(:generate).and_return(reference)
end

scenario "As a form filler" do
when_i_visit_the_form_start_page
then_i_should_see_the_first_question

when_i_choose_the_exit_option
and_i_click_on_continue
then_i_should_see_the_exit_page

when_i_click_back
when_i_dont_choose_the_exit_option
and_i_click_on_continue
then_i_should_see_the_check_your_answers_page

when_i_opt_out_of_email_confirmation
and_i_submit_my_form
then_my_form_should_be_submitted
and_i_should_receive_a_reference_number
end

def when_i_visit_the_form_start_page
visit form_path(mode: "form", form_id: 1, form_slug: "fill-in-this-form")
expect_page_to_have_no_axe_errors(page)
end

def then_i_should_see_the_first_question
expect(page.find("h1")).to have_text question_text
end

def when_i_choose_the_exit_option
choose "Option 1"
end

def when_i_dont_choose_the_exit_option
choose "Option 2"
end

def and_i_click_on_continue
click_button "Continue"
end

def then_i_should_see_the_check_your_answers_page
expect(page.find("h1")).to have_text "Check your answers before submitting your form"
expect(page).to have_text question_text
expect(page).to have_text "Option 2"
expect_page_to_have_no_axe_errors(page)
end

def when_i_click_back
click_on "Back"
end

def then_i_should_see_the_exit_page
expect(page.find("h1")).to have_text "This is an exit_page"
expect(page).to have_text "This is the contents"
expect_page_to_have_no_axe_errors(page)
end

def when_i_opt_out_of_email_confirmation
choose "No"
end

def and_i_submit_my_form
click_on "Submit"
end

def then_my_form_should_be_submitted
expect(page.find("h1")).to have_text "Your form has been submitted"
expect_page_to_have_no_axe_errors(page)
end

def and_i_should_receive_a_reference_number
expect(page).to have_text reference
end
end
45 changes: 45 additions & 0 deletions spec/models/step_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,49 @@
end
end
end

describe "#has_exit_page_condition?" do
it "returns false when no routing conditions" do
expect(step.has_exit_page_condition?).to be false
end

it "returns false when first routing condition is not exit page" do
page.routing_conditions = [OpenStruct.new(answer_value: "Yes", goto_page_id: "5")]
expect(step.has_exit_page_condition?).to be false
end

it "returns false when first routing condition contains markdown exit_page_markdown" do
page.routing_conditions = [OpenStruct.new(exit_page_markdown: 12)]
expect(step.has_exit_page_condition?).to be false
end

it "returns true when first routing condition contains string markdown exit_page_markdown" do
page.routing_conditions = [OpenStruct.new(exit_page_markdown: "")]
expect(step.has_exit_page_condition?).to be true
end
end

describe "#exit_page_condition_matches?" do
let(:selection) { "Yes" }
let(:question) { instance_double(Question::Selection, selection:) }
let(:routing_conditions) { [OpenStruct.new(answer_value: "Yes", exit_page_markdown: "string")] }
let(:page) { build(:page, id: 2, position: 1, routing_conditions:) }

it "returns true when condition matches and condition is an exit page" do
expect(step.exit_page_condition_matches?).to be true
end

it "when condition matches but not an exit page it returns false" do
routing_conditions.first.exit_page_markdown = nil
expect(step.exit_page_condition_matches?).to be false
end

context "when condition doesn't match" do
let(:selection) { "No" }

it "returns false" do
expect(step.exit_page_condition_matches?).to be false
end
end
end
end
20 changes: 20 additions & 0 deletions spec/requests/forms/page_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,26 @@
end
end
end

context "when the page is a an exit question" do
let(:first_step_in_form) do
build :v2_question_page_step, :with_selections_settings,
id: 1,
next_step_id: 2,
routing_conditions: [DataStruct.new(id: 1, routing_page_id: 1, check_page_id: 1, goto_page_id: nil, answer_value: "Option 1", validation_errors: [], exit_page_markdown: "Exit page markdown", exit_page_heading: "exit page heading")],
is_optional: false
end

it "redirects to the exit page when exit page answer given" do
post save_form_page_path(mode:, form_id: 2, form_slug: form_data.form_slug, page_slug: 1, params: { question: { selection: "Option 1" }, changing_existing_answer: false })
expect(response).to redirect_to exit_page_path(mode:, form_id: 2, form_slug: form_data.form_slug, page_slug: 1)
end

it "redirects to the next step in the form when any other answer given" do
post save_form_page_path(mode:, form_id: 2, form_slug: form_data.form_slug, page_slug: 1, params: { question: { selection: "Option 2" }, changing_existing_answer: false })
expect(response).to redirect_to form_page_path(mode:, form_id: 2, form_slug: form_data.form_slug, page_slug: 2)
end
end
end

def log_lines
Expand Down
38 changes: 38 additions & 0 deletions spec/views/forms/exit_pages/show.html.erb_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require "rails_helper"

describe "forms/exit_pages/show.html.erb" do
let(:form) { build :form, :with_support, id: 1, name: "exit page form" }
let(:mode) { OpenStruct.new(preview_draft?: false, preview_archived?: false, preview_live?: false) }
let(:condition) { OpenStruct.new({ exit_page_heading: "heading", exit_page_markdown: " * first line\n * second line\n" }) }
let(:support_details) { OpenStruct.new(email: form.support_email) }

before do
assign(:current_context, OpenStruct.new(form:))
assign(:mode, mode)
assign(:condition, condition)
assign(:back_link, "/back")
assign(:support_details, support_details)

render
end

it "has the correct title" do
expect(view.content_for(:title)).to eq "heading - exit page form"
end

it "has a back link" do
expect(view.content_for(:back_link)).to have_link("Back", href: "/back")
end

it "has the correct heading" do
expect(rendered).to have_css("h1", text: condition.exit_page_heading)
end

it "displays the markdown" do
expect(rendered).to have_css("li", text: "second line")
end

it "displays the help link" do
expect(rendered).to have_text(I18n.t("support_details.get_help_with_this_form"))
end
end