Goal: Trying to submit empty register form fails due to validation errors. Expects are present in scenario as single line (method). Errors are being checked very precisely in terms of their placement. I don't want to use classical counting until that's the only way left.
def cant_be_blank_error_is_displayed(number_of_times = 1)
expect(page).to have_content t('errors.messages.blank'), count: number_of_times
end
require 'rails_helper'
require 'email_helper'
feature 'register organisation', type: :feature, js: true do
let!(:register_page) { RegisterPage.new }
let!(:login_page) { LoginPage.new }
let!(:organisation) { create :organisation, name: 'organisation_name' }
let!(:owner) { create :user, email: 'user@example.com', role: :owner }
let(:form) { register_page.register_form }
before { register_page.load }
context 'creation fails because' do
scenario 'mandatory fields were left empty' do
register_page.submit_empty_form
all_mandatory_fields_cant_be_blank_error_displayed
# expect(form).to have_content mail_blank_or_taken_error
end
scenario (...)
end
end
Method:
1. Define specific errors as elements in the page
class RegisterPage < SitePrism::Page
set_url "/sign_up"
section :register_form, :xpath, "//*[@id='new_user']" do
element :email, :xpath, "//*[@id='user_email']"
(...) # other input fields
# binding.pry confirms they appear on the page
element :mail_blank_or_taken_error, :xpath, "//*[@id='new_user']/div[2]/span"
element :blank_password_error, :xpath, "//*[@id='new_user']/div[4]/span"
element :password_too_short_error, :xpath, "//*[@id='new_user']/div[2]/div[3]/p"
element :mismatch_error, :xpath, "//*[@id='new_user']/div[2]/div[4]/span"
element :blank_name_error, :xpath, "//*[@id='new_user']/div[2]/div[5]/span"
element :name_taken_error, :xpath, "//*[@id='new_user']/div[2]/div[5]"
element :wrong_format_error, :xpath, "//*[@id='new_user']/div[7]/span
(...)
end
end
2. Create error_alerts.rb
helper to store expects in one method
def all_mandatory_fields_cant_be_blank_error_displayed
[
mail_blank_or_taken_error,
blank_password_error,
signs_limit_error,
blank_name_error,
blank_adress_line_error,
blank_city_error,
blank_country_error,
blank_zipcode_error,
blank_phone_number_error,
blank_website_error,
].each do |validation_errors|
expect(form).to have_content validation_errors
end
end
Obstacle: Errors are default rails ones, so they are not defined as translations, which I used in another spec in the same convention and everything worked flawlessly.
example:
def invalid_email_or_password_error_displayed
expect(login_page).to have_content t("devise.failure.invalid", authentication_keys: "Email")
end
Failures: I get following errors.
1# my way - same issue occurs for each object from the |validation_errors|
1) register organisation creation fails because mandatory fields were left empty
Failure/Error: mail_blank_or_taken_error,
NameError:
undefined local variable or method `mail_blank_or_taken_error' for #<RSpec::ExampleGroups::RegisterOrganisation::CreationFailsBecause:0x007fe56b336370>
# ./spec/support/error_alerts.rb:63:in `all_mandatory_fields_cant_be_blank_error_displayed'
# ./spec/features/organisation_registration_spec.rb:16:in `block (3 levels) in <top (required)>'
2# classical expect
1) register organisation creation fails because mandatory fields were left empty
Failure/Error: expect(form).to have_content
mail_blank_or_taken_error
NameError:
undefined local variable or method `mail_blank_or_taken_error' for # <RSpec::ExampleGroups::RegisterOrganisation: :CreationFailsBecause:0x007ff02e7b9348>#./spec/features/organisation_registration_spec.rb:17:in `block (3 levels) in <top (required)>'
Question: Is my way technically achievable after some modifications or the only solution is to use classical counting method? Can loop iterate through page's elements? Here's an example of its similiar use, though expects are strings and the loop itself is included in spec's scenario, instead of being exported to external method in a helper.
scenario "is successful" do
all_ministry_memberships_page.create_new(ministry, cabinet, minister)
[
t("flash.actions.create.notice", resource_name: "Ministry membership"),
"Ministry " + ministry.name,
"Cabinet " + cabinet.name,
"Minister " + minister.name,
"Start Date " + (cabinet.appointment_date + 2.days).strftime("%Y-%m-%d"),
"Created At " + ministry_membership.created_at.strftime("%B %0e, %Y %H:%M"),
"Updated At " + ministry_membership.updated_at.strftime("%B %0e, %Y %H:%M"),
].each do |form_input|
expect(form).to have_content form_input
end
end