Tests failing because a gems method is undefined - ruby-on-rails

I'm writing tests for a rails application and keep getting the following error, which is related to this UK postcode validator gem:
Error:
OrganisationsControllerTest#test_0001_should get index:
NoMethodError: undefined method `full_valid?' for # <UKPostcode::GeographicPostcode:0x007fe405e6caf8>
app/validators/postcode_validator.rb:4:in `validate_each'
test/controllers/organisations_controller_test.rb:7:in `block in <class:OrganisationsControllerTest>'
The error is refering to the line where FactoryGirl instantiates and object for use in the tests. This is the factory used:
FactoryGirl.define do
factory :organisation do
name 'Acme Corp'
address_1 'Acme House'
address_2 '40 - 44 Harvard Road'
address_3 'Archingdon'
town 'Exeter'
postcode 'EX4 6PX'
phone_number '03309 890890'
email 'hello#acme.com'
linkedin_url 'https://linkedin.com/acmecorp'
twitter_handle 'acmecorp'
facebook_url 'https://facebook.com/acmecorp'
website 'https://www.acmecopr.com'
end
end
I assume the error is because I need to require the library somewhere, but I can't seem to find the right place. So far I have added require 'uk_postcode' to the file the factory is defined in, the failing controller test class and test_helper.rb.
How can I stop this error?
Any help much appreciated :)

Doesn't look like require error. It is unable to find full_valid? method on the instance of UKPostcode::GeographicPostcode object. It can be because of the version of gem you have doesn't have this method.
Look here to see how you can verify it. Open console and create a new
UKPostcode::GeographicPostcode object and verify if the method exists.

Related

How to mock a GraphQL type in Rails engine rspec?

I'm working inside a Rails engine where I have a GraphQL type.
module RailsEngine
module Graph
module RailsEngine
module Types
MyClass = GraphQL::ObjectType.define do
# some working code here
field :user, RailsEngine.graph_user_type.constantize, 'The description of user'
end
end
end
end
end
graph_user_type is a method that I define in the mattr_accessor and am getting a specific class of User from the main Rails app through the initializer.
When I'm running my Rspec tests for this type, I'm getting an error NameError: uninitialized constant Graph
So I was thinking of mocking the whole line field :user, RailsEngine.graph_user_type.constantize, 'The description of user' like this:
before do
user_type = double('Graph::User::Types::User')
allow(described_class.fields['user']).to receive(:constantize).and_return(user_type)
end
I've also tried allow(described_class.fields['user']).to receive(:type).and_return(user_type) also to no avail!
But I'm still getting the same error! Any ideas?
Failure/Error: field :user, RailsEngine.graph_user_type.constantize, 'The description of user'
NameError:
uninitialized constant Graph```
before do
user_type = double('Graph::User::Types::User')
allow(described_class.fields['user']).to receive(:constantize).and_return(user_type)
end
You need to understand what allow method does. It takes an object, on which later expectation is set with .to receive(...).
What seems to have more sense, would be:
allow(RailsEngine).to receive(:graph_user_type).and_return('Graph::User::Types::User')
or, if you need it to return a double, you'd do sth like
allow(RailsEngine).to receive_message_chain('graph_user_type.constantize').and_return(user_type)
https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/message-chains
This way you're controlling what RailsEngine.graph_user_type is returning, and being passed on field as a second argument.
So the issue was hidden here
graph_user_type is a method that I define in the mattr_accessor and am getting a specific class of User from the main Rails app through the initializer.
Since I was getting the method graph_user_type through the initializer to the engine from the main app, before the spec was loaded, the error was already thrown - so it was useless to mock it inside the spec.
The solution was to add the very same thing that the main app initializer had to the dummy initializer inside the engine (with an indication that the data is mocked)
This was my initializer:
RailsEngine.graph_user_type = 'Graph::User::Types::User'
This was my dummy initializer inside Engine:
RailsEngine.graph_user_type = 'MockUserType'

Why can't I have a mailer method named message?

I've created a new mail on rails 5 using the mailer generator:
$ rails g mailer mymailer message
Rails created the application_mailer, mymailer_mailer, views and tests. Ok.
This is the mailer generated by rails:
class MymailerMailer < ApplicationMailer
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.mymailer_mailer.message.subject
#
def message
#greeting = "Hi"
mail to: "to#example.org"
end
end
But whenever I've tried to send the mail I've got the following error:
NoMethodError: undefined method `reject!' for nil:NilClass
After spent about two hours double-checking every config file I've decided to change method to bla...
VoilĂ : It worked, Ok! But why?
BTW: The message method I've found is from ActionMailer::MessageDelivery but there's no mention on Rails Guides of that.
If you look at the docs for MessageDelivery, there appears to be a method already provided named message which
Returns the resulting Mail::Message
My assumption is that your definition is overriding this provided method, but you are not returning the expected Mail::Message type object.
As another answer stated, there's already a method in the class named message. This shouldn't be a problem if you use the class as intended, since the mailer shouldn't have a single message named "message", it should have a more descriptive name.
The intent of a Mailer object is to define a context for messages that may be sent.
So for example, a UserMailer would be used to build messages to a user. Then each different type of message has a method, such as forgotten_password or welcome.
The documentation includes a more thorough example that follows this.

rspec undefined method `sequence' for 1:Fixnum

I am writing a spec test in rails using rspec. One of the models I am testing has an attribute of sequence on it, and it is conflicting with rspec (from what I have found), but I have not been able to find a work around.
Here is my code
lessons.rb (factory)
FactoryGirl.define do
factory :lesson do
version_id 1
add_attribute :sequence, 1 # this is the field
name "Lesson Name"
description "An Example Lesson Description"
group_id 1
content "here is some example context"
passing_quiz_difficulty 2
survey_id 1
status 1
staff_content "example staff content"
lesson_type_id 1
end
end
method I'm testing
def second_response?(lesson)
self.lessons.where('sequence < ?', lesson.sequence).first
end
controller
def show
...
#part_two = true if #reveal_step.second_response?(#lesson)
...
end
rspec stack trace
Failure/Error: expect(#reveal_step.second_response?(lesson_1.id)).to eql true
NoMethodError: undefined method `sequence' for 1:Fixnum
This method works fine in the application, but I need to write a test for it, and I cannot find a work around with the sequence attribute, and I cannot leave it out because this whole method and flow of this part of the app is dependent on the sequence attr. Does anyone know of a workaround to use? or another way I could approach this? Any help would be appreciated.
Your expectation is passing a number, lesson_1.id, into a method that expects a lesson. That ID does not have a sequence method, while lessons do.

FactoryGirl with Rspec in Rails Unknown Method Error

So I am dealing with Rspec testing and FactoryGirl. I'm still a bit confused as to the inner workings of FactoryGirl when an object is created or built.
I have a few test results that look similar to this:
Failure/Error: #ticket = FactoryGirl.create(:ticket)
NoMethodError:
undefined method `user=' for #<Ticket:0x007f1455e72fc8>
# ./spec/models/ticket_spec.rb:38:in `block (3 levels) in <top (required)>'
It seems as if it is trying to assign an instance of ticket to user but why? And where would I start to try to fix it?
Update
I am just getting familiar with this code base and so I just realized there is no ticket factory or user factory. Is this way of creating a ticket for testing incorrect? Sorry for ignorance, I'm still very green with FactoryGirl and test frameworks in general.
You need to define your factories, most likely in spec/factories.rb or in a spec/factories folder. More info: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md
# spec/factories.rb
factory :user do
# assuming this passes model validations
end
factory :ticket do
# assuming this passes model validations
user
end

Help with a Given step that goes to a page and as a logged in user

My scenerio looks like:
Given I am on the homepage
As a member
When I follow "new post"
..
..
In my web_steps.rb I added:
When /^As a (.+)$/ do |type|
#user = Factory(:user, type)
end
My factories are in:
/spec/factories.rb
/spec/factories/user.rb
How do I reference my factories.rb into my web_steps.rb page?
Am I doing this correctly? Now this instance variable #user is the variable that my controller checks to see if it is authenticated correct?
I'm getting this error currently:
features/create_post.feature: Lexing error on line 8: ' As a member'.
What is wrong with my 'As a member' line?
Update
I noticed I had:
When /^As a
I changed it to:
As /^a
now I get:
undefined method `As' for main:Object (NoMethodError)
'As' is not valid in a cucumber scenario as far as I know.
Your lines should start with 'Given', 'When', 'Then', or 'And'.
Your scenario should probably look more like
Given I am logged in as 'User'
When I go to the homepage
And I follow "New post"
Then ...
Rather than write web steps that instantiate factories, i use Pickle for this. Pickle is nice, because you don't have to futz with your factories at all in cucumber. It defines generic steps for creating any given factory object (model), as well as steps for finding model objects and other things.
Ryan Bates has a created a screenscast on pickle as well. Rails screencasts are a nice post-lunch office tradition around our place!
Ok, good luck,
ian.

Resources