I am trying to do some rspec unit tests on a method in my model. The method returns a promise, and when resolved, the name of the person. The method is not the problem as I know that it works correctly. Here is my test code:
it 'should return correct name' do
report = Report.new(first_name: 'Testy', last_name: 'Testerson')
report.save!
expect(report.name).to eql('Testy Testerson')
end
When I test it, I get the following error:
Failure/Error: expect(report.name).to eql('Testy Testerson')
TypeError:
can't convert Promise to Array (Promise#to_ary gives Promise)
While debugging, I used the following line to inspect the returned value of the method:
puts report.name.inspect
And I got the following response:
#<Promise(70319926955580): "Testy Testerson">
The error seems to be happening because it tests the promise against the expected value. Why am I getting this error?
Using report.name.value fixes this issue
When running code on the server, calls to store return a promise that is already resolved. But on the client the promise won't be resolved yet. Someone (forget the name atm) is working on adding support to promise directly into opal-rspec, but at the moment a returned promise won't wait for opal-rspec. The plan is once thats ready we'll add more tools to volt to make it easier for developers to test in both MRI and opal (like we do with Volt itself).
You can call .value on a promise to get back its value, but only if the promise has resolved. The safer way to do it is to use a .then block:
report.name.then do |name|
expect(name).to eq('Bob')
end
Hopefully that helps.
Related
Upon submitting a form in Sinatra, I'm coming up with the following error:
App 40327 output: 2018-06-28 02:59:17 - NoMethodError - undefined method `[]' for nil:NilClass:
App 40327 output: /Library/WebServer/Documents/blammo/routes/publish.rb:87:in `block in <class:MyApp>'
The form is a file upload form, and a single text field. Simple. The file goes through, as does the text field. They are both captured just fine.
I submit the params to a method, which is ultimately responsible for generating the error on the following line down the page:
fname = params[:s_single_file_upload][:filename]
The method in question returns fine with a boolean. I've rewritten it a couple of ways and flushed out anything that might trip something I'm
unfamiliar with.
So the params is messed up if this method mentioned above is being called. So fname can't be assigned. I expect the params to be intact
at this point in the code. Is there any destruction if the params are perused before this point? In another language, I've seen params destroyed
in one way or another for some reason, but I'm not sure about Ruby.
I'm not finding any nil:NilClass, but that's exactly what it's reporting. Here's the trigger of this method:
result = Alpha::rf_alpha_sniff(params)
And the module::method:
module Alpha
def self.rf_alpha_sniff(incoming)
qualifiers = %w(alpha bravo charlie delta echo foxtrot)
incoming.delete('captures')
incoming.delete('splat') # take out Mustermann's 'captures' and 'splat'
incoming.delete('s_single_file_upload') # non-perusal 'single_file_upload'
incoming.values.each do |item|
item = item.gsub(" ","_")
Dev::hq_log("item: #{ qualifiers.include?(item.downcase) }")
return true if qualifiers.include?(item.downcase)
end
return false
end
end
So the page progresses fine without this method. When the method is induced any way, the params seem to get screwed up, so the file is pretty much
gone.
How is this method interfering with the params so that it's unavailable later on down the script? I'm expecting it to be fully available everywhere.
Turns out, using incoming.delete was deleting items from the params hash, as it was a reference to the original, instead of using a copy.
So, I have to copy the params by using params.dup (duplicate) so they are not the same object.
Having a view of the params hash post-testing-method, showed me that objects were indeed deleted. Another one solved.
I have this Ruby code in a script:
$dev_input=gets.chomp.downcase!
if $dev_input.include? "/"
check_developer_commands()
else
puts ">>Invalid Command<<"
continuing_dev_mode()
end
The problem is, whenever I try and run the script containing this, I get an error spat back at me that says :
dev_continue_main.rb:3:in 'continuing_dev_mode': undefined method 'include?' for nil:NilClass (NoMethodError)
Any idea what this error might be? I'm pretty sure that this is the proper way to use the .include? method. I've done some research, looked at tutorialspoint.com and some other sites, but they agree that this is the proper way to use this method.
I checked the error message and it confirmed that the third line in this script/my example is the source of the problem, so it's not some other instance of this method throwing an error.
Any thoughts? Please Help!
The problem is that $dev_input is nil. That stems from applying downcase! in defining $dev_input. I don't know why you want to possibly assign nil to $dev_input, and at the same time claim that calling include? on it is the right way. I don't get your intention for doing that, but if you instead had $dev_input = gets.chomp.downcase, then it wouldn't cause such error.
I tried to wait on a text before perform any action by follows SitePrism URL https://github.com/natritmeyer/site_prism in this section>> "Methods Supporting Capybara Options".
#page.wait_until_<Element>_visible :text => "Some Text!!!"
But i am getting below error:
undefined method `zero?' for {:text=>"Some Text!!!"}:Hash (NoMethodError)
Why i am getting this error? Am i doing something wrong?
Looking at the site_prism code - https://github.com/natritmeyer/site_prism/blob/master/lib/site_prism/element_container.rb#L134 the generated method takes a timeout, and the options. It seems like you need to pass the timeout value if you want to pass other options
wait_until_<Element>_visible <timeout value in seconds>, text: "Some Text!!!"
Seems like an error in the documentation, or some old defaulting behavior was removed or something
Old question
For those still hitting this SO answer, this has been remedied in v3 of the API and is no longer an issue. See: https://github.com/natritmeyer/site_prism/blob/master/UPGRADING.md#wait_until-methods
wait_for_ methods now no longer exist, and you should just implicitly wait by calling element i.e. my_button
If you want it to wait, you can modify the Capybara.default_wait_time or pass in a wait key i.e. my_button(wait: 3)
I'm going a little nuts working with Volt at the moment. The moment I try to do something a bit more complicated I end up getting the exception "ArgumentError: a promise has already been chained" in the browser console.
The stack trace doesn't point to anything I can interpret as useful.
That does this error actually mean, and how do I go about trying to track down the cause?
I'd post some code, but some of these errors appear on page load with no indication of where the problem is, so I'd need to post the entire app :/
Volt uses Opal's promise implementation, which I believe is based on the A+ spec in JS land. The error your seeing is because a promise can only have a single .then or .fail block on it. Each .then or .fail will return a new promise that you can then chain off of.
So you can do this:
promise = Promise.new
promise2 = promise.then do
..
end
promise2.then do
..
end
(notice I'm assigning promise2 instead of chaining off of the first one again)
But you can not do something like this:
promise = Promise.new
promise.then do
...
end
promise.then do
..
end
(Notice how I called .then on promise more than once)
A more compact way to write the first is to chain off of the end's
promise = Promise.new
promise.then do
..
end.then do
..
end.fail do
..
end
Volt bindings expect a promise that hasn't been chained on. Also, I think I can make it work where you can chain multiple times, though I haven't thought through all of the implications of this, so I could be wrong. If I get some time I might write a new promise implementation that can handle this. If your still seeing that error and the above doesn't explain why its there, let me know. Thanks!
I'm using Devise (v2.1.2) with Omniauth for user verification. I'm working on a functional test for a controller that takes a JSON object as the POST body and thus using the technique from this question to set the raw POST body. This works fine for development, but when I run tests I get an exception on a method that's completely unauthenticated:
NoMethodError: undefined method `user' for nil:NilClass
Example test:
test "should be able to create an item" do
m = FactoryGirl.attributes_for(:item)
raw_post :create, {}, m.to_json
assert_response :success
end
None of my models have a user method, and nothing in this controller uses authentication, so I was pretty confused. A full stack trace shows that the error comes from the first line of this function in Devise:
def sign_out_all_scopes(lock=true)
users = Devise.mappings.keys.map { |s| warden.user(:scope => s, :run_callbacks => false) }
warden.raw_session.inspect
warden.logout
expire_devise_cached_variables!
warden.clear_strategies_cache!
warden.lock! if lock
users.any?
end
So it looks like in my functional tests (and only in my functional tests) the warden object is nil.
Why is this function being called on an unauthenticated request?
Why doesn't the warden object exist here?
What can I do to fix it?
No idea, Devise is doing its own thing.
See 1.
Include Devise::TestHelpers.
The Devise documentation says that you need to include the helpers in order to use them. It does not say that if you don't include the helpers your functional tests will fail, including those that don't use any authentication, but that's what happens.
(Note the JSON handling here, which I originally thought was the problem, ended up being just a red herring. Even with standard post or get you will have this problem.)