-
-
Notifications
You must be signed in to change notification settings - Fork 910
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
WIP: Add converting_values
to validation matchers
#820
Conversation
it 'accepts (and not raise an error)' do | ||
model = define_model_validating_uniqueness( | ||
attribute_name: :name, | ||
validation_options: { case_sensitive: false } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put a comma after the last parameter of a multiline method call.
We now always run the absence tests since we don't support anything before Rails 4, so there's no need for a conditional.
* For some reason, ActiveRecord was printing a warning saying that "active_record/base" was already being loaded and there was a possible circular dependency. We fix this by explicitly requiring "active_record/base" before `$VERBOSE` is set to true. * We were getting warnings when re-defining Kernel.capture, Kernel.silence_stream and Kernel.silence_stderr, so undefine them first.
More commit message here...
7fa233a
to
830b38c
Compare
converting_values( | ||
'xxx' => 'XXX', | ||
'xxxx' => 'XXXX', | ||
'xxxxx' => 'XXXXX' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put a comma after the last parameter of a multiline method call.
expect(record). | ||
to validate_length_of(:name). | ||
is_at_least(0). | ||
converting_values("x" => "X") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer single-quoted strings when you don't need string interpolation or special symbols.
After thinking about it, I'm not sure I like this approach -- if you have a test that uses a factory to build a record, and a value for the attribute being tested is provided within the factory itself, and the matcher fails because that value is getting changed somehow, it doesn't really make sense to use In other words, if you have this factory: factory :user do
username "some_username"
end and this model: class User < ActiveRecord::Base
def username=(username)
super(username.downcase)
end
end and you have this test: describe User do
context "validations" do
it do
create(:user)
should validate_uniqueness_of(:username)
end
end
end it wouldn't make sense to say: describe User do
it do
should validate_uniqueness_of(:username).
converting_values("SOME_USERNAME" => "some_username")
end
end because a reader of this test wouldn't even know where this comes from. In fact, if you saw: describe User do
it do
should validate_uniqueness_of(:username).
converting_values("A" => "a")
end
end would you be confused where So, perhaps we do this instead:
|
Closing this in favor of #866. |
This is WIP as I add tests for every matcher to which this applies.
I don't like the idea of blindly ignoring any CouldNotSetAttributeError that may arise from using a particular matcher. It may very well be that the exception could be raised for a good reason. So instead of doing this, I'm proposing a new matcher:
converting_values
(or its companion,converting_value_to
, forallow_value
). The idea here is that you give the matcher a whitelist of acceptable values and their converted forms. So if the matcher detects a CouldNotSetAttributeError, but the value it sent to the attribute and the value it got out are both in this whitelist, then it'll ignore the exception and move on.I think this is preferable over supplying some kind of lambda (which I proposed in #799) because at that point you'd probably be copying or recreating the same logic you have in the model. I think that by explicitly listing the acceptable values it's far easier to control and it's more clear to someone reading the test what's going on.
exclusion(producing a test case here is difficult)inclusion(producing a test case here is difficult)presence(the only thing that's set on the record is nil, and we are handling value conversions here so as long as the final value is blank)uniqueness(this actually creates a lot of problems so we should probably raise a specific error?)