Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define steps in ConsentForm #482

Merged
merged 4 commits into from
Sep 6, 2023
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
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ group :test do
gem "capybara"
gem "cuprite"
gem "rspec"
gem "shoulda-matchers"
gem "webmock"
end
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,8 @@ GEM
sentry-ruby (~> 5.10.0)
sentry-ruby (5.10.0)
concurrent-ruby (~> 1.0, >= 1.0.2)
shoulda-matchers (5.3.0)
activesupport (>= 5.2.0)
silencer (2.0.0)
solargraph (0.49.0)
backport (~> 1.2)
Expand Down Expand Up @@ -586,6 +588,7 @@ DEPENDENCIES
rubocop-govuk
sentry-rails
sentry-ruby
shoulda-matchers
silencer
solargraph
solargraph-rails
Expand Down
39 changes: 16 additions & 23 deletions app/controllers/consent_forms/edit_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class ConsentForms::EditController < ConsentForms::BaseController

layout "two_thirds"

steps :name, :date_of_birth, :school
steps(*ConsentForm.form_steps)

before_action :set_session
before_action :set_consent_form
Expand All @@ -15,14 +15,10 @@ def show
end

def update
@consent_form.assign_attributes(update_params)

case current_step
when :name
@consent_form.assign_attributes(name_params)
when :date_of_birth
@consent_form.assign_attributes(date_of_birth_params)
when :school
@consent_form.assign_attributes(school_params)

if @consent_form.is_this_their_school == "no"
return(
redirect_to session_consent_form_cannot_consent_path(
Expand All @@ -33,7 +29,7 @@ def update
end
end

render_wizard @consent_form, context: current_step
render_wizard @consent_form
end

private
Expand All @@ -46,20 +42,17 @@ def finish_wizard_path
session_consent_form_confirm_path(@session, @consent_form)
end

def name_params
params.fetch(:consent_form, {}).permit(
%i[first_name last_name use_common_name common_name]
)
end

def date_of_birth_params
params.fetch(:consent_form, {}).permit(
%i[date_of_birth(3i) date_of_birth(2i) date_of_birth(1i)]
)
end

def school_params
params.fetch(:consent_form, {}).permit(%i[is_this_their_school])
def update_params
permitted_attributes = {
name: %i[first_name last_name use_common_name common_name],
date_of_birth: %i[date_of_birth(3i) date_of_birth(2i) date_of_birth(1i)],
school: %i[is_this_their_school]
}.fetch(current_step)

params
.fetch(:consent_form, {})
.permit(permitted_attributes)
.merge(form_step: current_step)
end

def set_session
Expand All @@ -77,7 +70,7 @@ def validate_params
DateParamsValidator.new(
field_name: :date_of_birth,
object: @consent_form,
params: date_of_birth_params
params: update_params
)

unless validator.date_params_valid?
Expand Down
67 changes: 46 additions & 21 deletions app/models/consent_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,59 @@
#

class ConsentForm < ApplicationRecord
attr_accessor :is_this_their_school
cattr_accessor :form_steps do
%i[name date_of_birth school]
end
tvararu marked this conversation as resolved.
Show resolved Hide resolved

attr_accessor :form_step, :is_this_their_school

audited

belongs_to :session

validates :first_name, presence: true, on: :name
validates :last_name, presence: true, on: :name
validates :use_common_name, inclusion: { in: [true, false] }, on: :name
validates :common_name, presence: true, on: :name, if: :use_common_name?

validates :date_of_birth,
presence: true,
comparison: {
less_than: Time.zone.today,
greater_than_or_equal_to: 22.years.ago.to_date,
less_than_or_equal_to: 3.years.ago.to_date
},
on: :date_of_birth

validates :is_this_their_school,
presence: true,
inclusion: {
in: %w[yes no]
},
on: :school
with_options on: :update do
with_options if: -> { required_for_step?(:name) } do
validates :first_name, presence: true
validates :last_name, presence: true
validates :use_common_name, inclusion: { in: [true, false] }
validates :common_name, presence: true, if: :use_common_name?
end

with_options if: -> { required_for_step?(:date_of_birth) } do
validates :date_of_birth,
presence: true,
comparison: {
less_than: Time.zone.today,
greater_than_or_equal_to: 22.years.ago.to_date,
less_than_or_equal_to: 3.years.ago.to_date
}
end

with_options if: -> { required_for_step?(:school, exact: true) } do
validates :is_this_their_school,
presence: true,
inclusion: {
in: %w[yes no]
}
end
end

def full_name
[first_name, last_name].join(" ")
end

private

def required_for_step?(step, exact: false)
# Exact means that the form_step must match the step
return false if exact && form_step != step

# All fields are required if no form_step is set
return true if form_step.nil?

# Otherwise, all fields from previous and current steps are required
return true if form_steps.index(step) <= form_steps.index(form_step)

false
end
tvararu marked this conversation as resolved.
Show resolved Hide resolved
end
4 changes: 4 additions & 0 deletions spec/factories/consent_forms.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FactoryBot.define do
factory :consent_form do
end
end
66 changes: 66 additions & 0 deletions spec/models/consent_form_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require "rails_helper"

RSpec.describe ConsentForm, type: :model do
describe "Validations" do
let(:form_step) { nil }
let(:use_common_name) { false }
subject { build(:consent_form, form_step:, use_common_name:) }

it "validates all fields when no form_step is set" do
expect(subject).to validate_presence_of(:first_name).on(:update)
expect(subject).to validate_presence_of(:last_name).on(:update)
expect(subject).to validate_presence_of(:date_of_birth).on(:update)
end

context "when form_step is :name" do
let(:form_step) { :name }

it { should validate_presence_of(:first_name).on(:update) }
it { should validate_presence_of(:last_name).on(:update) }

context "when use_common_name is true" do
let(:use_common_name) { true }

it { should validate_presence_of(:common_name).on(:update) }
end
end

context "when form_step is :date_of_birth" do
let(:form_step) { :date_of_birth }

context "runs validations from previous steps" do
it { should validate_presence_of(:first_name).on(:update) }
end

it { should validate_presence_of(:date_of_birth).on(:update) }
# it { should validate_comparison_of(:date_of_birth)
# .is_less_than(Time.zone.today)
# .is_greater_than_or_equal_to(22.years.ago.to_date)
# .is_less_than_or_equal_to(3.years.ago.to_date)
# .on(:update) }
end

context "when form_step is :school" do
let(:form_step) { :school }

context "runs validations from previous steps" do
it { should validate_presence_of(:first_name).on(:update) }
it { should validate_presence_of(:date_of_birth).on(:update) }
end

it { should validate_presence_of(:is_this_their_school).on(:update) }
it do
should validate_inclusion_of(:is_this_their_school).in_array(
%w[yes no]
).on(:update)
end
Comment on lines +52 to +56
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the linter's idea, not mine

end
end

describe "#full_name" do
it "returns the full name as a string" do
consent_form = build(:consent_form, first_name: "John", last_name: "Doe")
expect(consent_form.full_name).to eq("John Doe")
end
end
end
7 changes: 7 additions & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
end
Capybara.javascript_driver = :cuprite_custom

Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
Expand Down