From 70771edc697a46a66dbf33f8d73ba4773aae3048 Mon Sep 17 00:00:00 2001 From: Jerome Pratt Date: Tue, 17 Sep 2024 16:19:24 +0100 Subject: [PATCH 1/2] [RUBY-3220] Add project name validation logic to submit proposal - Updated `project_name_complete?` method to check for blank names, valid characters, and uniqueness. - Introduced `PROJECT_NAME_REGEX` constant in `ProjectNameStep` for name format validation. - Added comprehensive RSpec tests for various project name validation scenarios. --- .../pafs_core/validation_presenter.rb | 11 +++- app/steps/pafs_core/project_name_step.rb | 3 +- .../pafs_core/validation_presenter_spec.rb | 54 ++++++++++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/app/presenters/pafs_core/validation_presenter.rb b/app/presenters/pafs_core/validation_presenter.rb index 6b9043c6..9454bab0 100644 --- a/app/presenters/pafs_core/validation_presenter.rb +++ b/app/presenters/pafs_core/validation_presenter.rb @@ -19,7 +19,16 @@ def complete? end def project_name_complete? - # NOTE: currently has to be present before creation + return add_error(:project_name, "Tell us the project name") if name.blank? + + unless name =~ PafsCore::ProjectNameStep::PROJECT_NAME_REGEX + return add_error(:project_name, "The project name must only contain letters, underscores, hyphens and numbers") + end + + if PafsCore::Project.where.not(id: project.id).exists?(name: name) + return add_error(:project_name, "The project name already exists. Your project must have a unique name.") + end + true end diff --git a/app/steps/pafs_core/project_name_step.rb b/app/steps/pafs_core/project_name_step.rb index 402d6b6e..8ac76a6b 100644 --- a/app/steps/pafs_core/project_name_step.rb +++ b/app/steps/pafs_core/project_name_step.rb @@ -2,12 +2,13 @@ module PafsCore class ProjectNameStep < BasicStep + PROJECT_NAME_REGEX = /\A[A-Za-z0-9 _-]+\z/ delegate :name, :name=, to: :project validates :name, presence: { message: "Tell us the project name" } validates :name, format: { - with: /\A[A-Za-z0-9 _-]+\z/, + with: PROJECT_NAME_REGEX, message: "The project name must only contain letters, underscores, hyphens and numbers" }, if: -> { name.present? } diff --git a/spec/presenters/pafs_core/validation_presenter_spec.rb b/spec/presenters/pafs_core/validation_presenter_spec.rb index 37c7749c..41d73505 100644 --- a/spec/presenters/pafs_core/validation_presenter_spec.rb +++ b/spec/presenters/pafs_core/validation_presenter_spec.rb @@ -46,8 +46,58 @@ end describe "#project_name_complete?" do - it "always returns true" do - expect(subject.project_name_complete?).to be true + context "when the project name is blank" do + before { subject.name = "" } + + it_behaves_like "failed validation example", :project_name_complete?, :project_name, "Tell us the project name" + end + + context "when the project name contains invalid characters" do + invalid_names = ["Project/123", "Project@Name", "Project#ABC"] + + invalid_names.each do |invalid_name| + context "with name '#{invalid_name}'" do + before { subject.name = invalid_name } + + it_behaves_like "failed validation example", :project_name_complete?, :project_name, "The project name must only contain letters, underscores, hyphens and numbers" + end + end + end + + context "when the project name is not unique" do + before do + existing_project = create(:project, name: "Existing Project") + subject.name = existing_project.name + end + + it_behaves_like "failed validation example", :project_name_complete?, :project_name, "The project name already exists. Your project must have a unique name." + end + + context "when the project name is valid and unique" do + valid_names = ["Project 123", "PROJECT_ABC", "project-xyz", "Simple Project Name"] + + valid_names.each do |valid_name| + context "with name '#{valid_name}'" do + before { subject.name = valid_name } + + it_behaves_like "successful validation example", :project_name_complete? + end + end + end + + context "when updating an existing project" do + subject { described_class.new(existing_project) } + + let(:existing_project) { create(:project, name: "Existing Project") } + + it "allows the project to keep its current name" do + expect(subject.project_name_complete?).to be true + end + + it "allows the project to change its name" do + subject.name = "Updated Project Name" + expect(subject.project_name_complete?).to be true + end end end From bb31ed2623525c9d1f27670e308dcefb3de796c0 Mon Sep 17 00:00:00 2001 From: Jerome Pratt Date: Tue, 17 Sep 2024 17:01:39 +0100 Subject: [PATCH 2/2] [RUBY-3220] Refactor project name validation logic for clarity --- app/presenters/pafs_core/validation_presenter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/presenters/pafs_core/validation_presenter.rb b/app/presenters/pafs_core/validation_presenter.rb index 9454bab0..68436cc4 100644 --- a/app/presenters/pafs_core/validation_presenter.rb +++ b/app/presenters/pafs_core/validation_presenter.rb @@ -25,7 +25,9 @@ def project_name_complete? return add_error(:project_name, "The project name must only contain letters, underscores, hyphens and numbers") end - if PafsCore::Project.where.not(id: project.id).exists?(name: name) + other_projects_with_same_name = PafsCore::Project.where.not(id: project.id).where(name: name) + + if other_projects_with_same_name.present? return add_error(:project_name, "The project name already exists. Your project must have a unique name.") end