Skip to content

Commit

Permalink
navigator redirects user if they veer off journey
Browse files Browse the repository at this point in the history
  • Loading branch information
asmega committed Jan 23, 2025
1 parent 61823ed commit 47fd15c
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 0 deletions.
9 changes: 9 additions & 0 deletions app/controllers/claims_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class ClaimsController < BasePublicController
skip_before_action :send_unstarted_claimants_to_the_start, only: [:new, :create]
before_action :initialize_session_slug_history
before_action :check_page_is_in_sequence, only: [:show, :update]
before_action :check_page_is_permissible, only: [:show]
before_action :set_backlink_path, only: [:show, :update]
before_action :check_claim_not_in_progress, only: [:new]
before_action :clear_claim_session, only: [:new], unless: -> { journey.start_with_magic_link? }
Expand Down Expand Up @@ -120,6 +121,14 @@ def check_page_is_in_sequence
redirect_to claim_path(current_journey_routing_name, next_required_slug) unless page_sequence.has_completed_journey_until?(params[:slug])
end

def check_page_is_permissible
return unless journey.use_navigator?

unless navigator.permissible_slug?
redirect_to claim_path(current_journey_routing_name, navigator.furthest_permissible_slug)
end
end

def initialize_session_slug_history
session[:slugs] ||= []
end
Expand Down
14 changes: 14 additions & 0 deletions app/models/journeys/further_education_payments/slug_sequence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,22 @@ def slugs
if answers.skip_postcode_search == true
sequence.delete("select-home-address")
end

if !eligibility_checker.ineligible?
sequence.delete("ineligible")
end
end
end

private

def eligibility_checker
@eligibility_checker ||= journey::EligibilityChecker.new(journey_session:)
end

def journey
Journeys.for_routing_name(journey_session.journey)
end
end
end
end
71 changes: 71 additions & 0 deletions app/models/journeys/navigator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ def initialize(current_slug:, slug_sequence:, params:, session:)
@session = session
end

# when showing a form
# work out where the backlink should take the user
def previous_slug
last_valid_slug = nil

Expand All @@ -35,6 +37,9 @@ def previous_slug
end
end

# given the current slug
# returns the next slug in the sequence
# used when a user hits continue on a form
def next_slug
return "ineligible" if eligibility_checker.ineligible?

Expand Down Expand Up @@ -78,8 +83,74 @@ def next_slug
end
end

# is a user allowed to visit the current_slug?
# use this to guard against a user jumping ahead in a journey
def permissible_slug?
if current_slug == "ineligible" && eligibility_checker.ineligible?
return true
end

forms.each do |form|
slug = journey.slug_for_form(form:)

if current_slug == slug
return true
end

if form.respond_to?(:completed?)
if !form.completed?
return false
end
elsif form.invalid?
return false
end
end
end

# ignoring the current_slug
# return the last slug the user is allowed to visit
# this is the furthest slug available in the journey given their state
# use this when user requests a non permissible slug
def furthest_permissible_slug
last_slug = nil

forms.each_with_index do |form, index|
slug = journey.slug_for_form(form:)

if form.respond_to?(:completed?)
if form.completed?
last_slug = slug
else
return slug
end
elsif form.valid?
last_slug = slug
else
return slug
end
end

last_slug
end

private

def forms
@forms ||= slug_sequence.slugs.map do |slug|
form_class = journey.form_class_for_slug(slug:)

raise "Form not found for journey: #{journey} slug: #{slug}" if form_class.nil?

form = form_class.new(
journey:,
journey_session:,
params:,
session:
)
form
end
end

def journey
Journeys.for_routing_name(slug_sequence.journey_session.journey)
end
Expand Down
17 changes: 17 additions & 0 deletions spec/features/further_education_payments/jump_around_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require "rails_helper"

RSpec.feature "Further education payments" do
scenario "visiting impermissible slug redirects back to last permissible slug" do
when_further_education_payments_journey_configuration_exists

visit landing_page_path(Journeys::FurtherEducationPayments::ROUTING_NAME)
expect(page).to have_link("Start now")
click_link "Start now"

expect(page).to have_content("Are you a member of staff with teaching responsibilities?")

visit claim_path(Journeys::FurtherEducationPayments::ROUTING_NAME, slug: "address")

expect(page).to have_content("Are you a member of staff with teaching responsibilities?")
end
end
79 changes: 79 additions & 0 deletions spec/models/journeys/navigator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,83 @@
end
end
end

describe "#permissible_slug?" do
context "when permissible" do
let(:answers) do
build(
:further_education_payments_answers
)
end

it "returns truthy" do
expect(subject.permissible_slug?).to be_truthy
end
end

context "when not permissible" do
let(:current_slug) { "address" }
let(:answers) do
build(
:further_education_payments_answers
)
end

it "returns falsey" do
expect(subject.permissible_slug?).to be_falsey
end
end
end

describe "#furthest_permissible_slug" do
context "when new journey" do
let(:answers) do
build(
:further_education_payments_answers
)
end

it "returns first slug" do
expect(subject.furthest_permissible_slug).to eql("teaching-responsibilities")
end
end

context "when mid-journey" do
let(:current_slug) { "foo" }

let(:answers) do
build(
:further_education_payments_answers,
teaching_responsibilities: true,
provision_search: "ply"
)
end

before do
create(:school, name: "Plymouth")
end

it "returns relevant slug" do
expect(subject.furthest_permissible_slug).to eql("select-provision")
end
end

context "when about to submit" do
let(:current_slug) { "foo" }
let(:school) { create(:school) }

let(:answers) do
build(
:further_education_payments_answers,
:submittable,
provision_search: school.name,
skip_postcode_search: true
)
end

it "returns check-answers slug" do
expect(subject.furthest_permissible_slug).to eql("check-your-answers")
end
end
end
end

0 comments on commit 47fd15c

Please sign in to comment.