Convert old Rspec syntax into new syntax - ruby-on-rails

I am using the APIonRails tutorial and they have this:
require 'spec_helper'
describe ApiConstraints do
let(:api_constraints_v1) { ApiConstraints.new(version: 1) }
let(:api_constraints_v2) { ApiConstraints.new(version: 2, default: true) }
describe "matches?" do
it "returns true when the version matches the 'Accept' header" do
request = double(host: 'api.marketplace.dev',
headers: {"Accept" => "application/vnd.marketplace.v1"})
api_constraints_v1.matches?(request).should be_true
end
it "returns the default version when 'default' option is specified" do
request = double(host: 'api.marketplace.dev')
api_constraints_v2.matches?(request).should be_true
end
end
end
In an example, but I have come to understand that this is using the old syntax.
To convert this into the new syntax, I am trying this:
require 'rails_helper'
describe ApiConstraints do
let(:api_constraints_v1) { ApiConstraints.new(version: 1) }
let(:api_constraints_v2) { ApiConstraints.new(version: 2, default: true) }
describe "matches?" do
it "returns true when the version matches the 'Accept' header" do
request = double(host: 'api.localhost:3000',
headers: {"Accept" => "application/vnd.marketplace.v1"})
expect(request).to match(api_constraints_v1)
end
it "returns the default version when 'default' option is specified" do
request = double(host: 'api.localhost:3000')
expect api_constraints_v2.matches?(request).to_be true
end
end
end
This is the error I am getting:
Failures:
1) ApiConstraints matches? returns true when the version matches the 'Accept' header
Failure/Error: expect(request).to match(api_constraints_v1)
expected #<RSpec::Mocks::Double:0x3feeedaf60c4 #name=nil> to match #<ApiConstraints:0x007fddde50f9b0 #version=1, #default=nil>
Diff:
## -1,2 +1,2 ##
-#<ApiConstraints:0x007fddde50f9b0 #default=nil, #version=1>
+#<RSpec::Mocks::Double:0x3feeedaf60c4 #name=nil>
# ./lib/spec/api_constraints_spec.rb:11:in `block (3 levels) in <top (required)>'
2) ApiConstraints matches? returns the default version when 'default' option is specified
Failure/Error: expect api_constraints_v2.matches?(request).to_be true
NoMethodError:
undefined method `to_be' for true:TrueClass
Did you mean? to_enum
to_s
# ./lib/spec/api_constraints_spec.rb:16:in `block (3 levels) in <top (required)>'
Finished in 0.0045 seconds (files took 6.52 seconds to load)
2 examples, 2 failures
Failed examples:
rspec ./lib/spec/api_constraints_spec.rb:8 # ApiConstraints matches? returns true when the version matches the 'Accept' header
rspec ./lib/spec/api_constraints_spec.rb:14 # ApiConstraints matches? returns the default version when 'default' option is specified
What could be causing this?
Edit 1
Per My Gemfile.lock, these are the versions of my relevant gems:
rspec (3.1.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-core (3.1.7)
rspec-support (~> 3.1.0)
rspec-expectations (3.1.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.1.0)
rspec-mocks (3.1.3)
rspec-support (~> 3.1.0)
rspec-rails (3.1.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-support (~> 3.1.0)
rspec-support (3.1.2)
rubyzip (1.2.0)
selenium-webdriver (2.53.0)
childprocess (~> 0.5)
rubyzip (~> 1.0)
websocket (~> 1.0)
shellany (0.0.1)
shoulda (3.5.0)
shoulda-context (~> 1.0, >= 1.0.1)
shoulda-matchers (>= 1.4.1, < 3.0)
shoulda-context (1.2.1)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
What is the correct new syntax I should use to be able to achieve the same thing that the original code achieves?

In the original test change
api_constraints_v1.matches?(request).should be_true
to
expect(api_constraints_v1.matches?(request)).to be_truthy
or
expect(api_constraints_v1.matches?(request)).to be(true)
if you expect only a boolean value to be returned.

change
expect request.to eq(api_constraints_v1)
to
expect(request).to eq(api_constraints_v1)
and the same problem in the other spec...
expect is a method to which you give the thing that the expectation is going on (ie request)...
after you get the result from the request method - you then call to on it...
The way you had it before... you are first calling to on request and then passing the result of that to expect... ie, grouping matters ;)

I've used the same ApiConstraints in my rails-api-base project and it crashes when you try matches? with a non-default version without specifying the Accept header.
I added the following test (which crashes):
it 'returns false when not default and no Accept header' do
request = double(host: 'api.marketplace.dev')
expect(api_constraints_v1.matches?(request)).to be false
end
And I fixed ApiConstraints:
def matches?(req)
#default ||
(req.respond_to?('headers') &&
req.headers.key?('Accept') &&
req.headers['Accept'].include?("application/vnd.marketplace.v#{#version}"))
end
Hope it helps!

Related

benchmark-rspec is stuck without any notifications

Im trying to test memory allocation. And choose for it rspec-benchmark gem. But found some strange behaviour I don't understand. To reproduce it we can write spec like this:
require 'rails_helper'
describe ApplicationsManagement::Export do
let(:applications_collection) { create_list(:application, 1 ) }
describe '#call' do
it 'comsumpts not more 1 MB' do
i = 0
expect { applications_collection.each { |app| puts i += 1 } }.to perform_allocation(1_048_576).bytes
end
end
end
When we run spec we have to wait few minutes!!
ApplicationsManagement::Export
#call
1
comsumpts not more 1 MB (FAILED - 1)
Failures:
1) ApplicationsManagement::Export#call comsumpts not more 1 MB
Failure/Error: expect { applications_collection.each { |app| puts i += 1 } }.to perform_allocation(1_048_576).bytes
expected block to perform allocation of 1048576 bytes, but allocated 10694166 bytes
# ./spec/services/applications_management/export_spec.rb:16:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:55:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:54:in `block (2 levels) in <top (required)>'
Finished in 4 minutes 8.5 seconds (files took 21.99 seconds to load)
1 example, 1 failure
To be honest, it was the first time I see the output, because I didn't wait never. Anyway its too long time for only one application creating and allocating 1 Mb memory. What am I doing wrong, why this spec is running so long?
spec/rails_helper.rb
require 'rspec-benchmark'
RSpec.configure do |config|
config.include RSpec::Benchmark::Matchers
...
P.S:
rails 4.2.9
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-benchmark (0.5.1)
benchmark-malloc (~> 0.1.0)
benchmark-perf (~> 0.5.0)
benchmark-trend (~> 0.3.0)
rspec (>= 3.0.0, < 4.0.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
Thank you so much!
I've found that if I pass FactoryBot.create(...) to the expect block, then I got the stuck behaviour. But if one row before I have initialized the objects. Then example working as expected.
require 'rails_helper'
describe ApplicationsManagement::Export do
let(:applications_collection) { create_list(:application, 1) }
describe '#call' do
it 'comsumpts not more 1 MB' do
applications_collection
i = 0
expect { applications_collection.each { |app| puts i += 1 } }.to perform_allocation(1_048_576).bytes
end
end
end
ApplicationsManagement::Export
#call
1
comsumpts not more 1 MB
Finished in 1.17 seconds (files took 21.71 seconds to load)
1 example, 0 failures

Rake task NoMethodError: undefined method `task' for main:Object

I have this code which works fine (!!! without the first line "task..."!!!) in console. It creates events in DB. However no luck when running the rake (rake fetch_ttt):
task :fetch_ttt => :environment do
require 'nokogiri'
require 'open-uri'
url = "http://www.example.com"
doc = Nokogiri::HTML(open(url))
doc.css("#eventrow").each do |item|
unless Event.find_by_name(item.at_css("a").text).present?
Event.create(
:start_time => item.at_css("#eventdate").text,
:name => item.at_css("a").text,
:url => item.at_css("a")[:href]
)
end
end
end
This is the trace (not much in dry run neither):
** Invoke fetch_ttt (first_time)
** Invoke environment (first_time)
** Execute (dry run) environment
** Execute (dry run) fetch_ttt
It has been fine couple hours ago. Since then I did a "bundle update", made some DB migrations, edited associations. I tried rolling back migrations and removed model association changes with no luck. I suspect the gems.
Below the 3 gems I rolled back to the previous versions to see if they are responsible but not. And the full diff.
old ones:
gem 'rake', '10.5.0'
gem 'http', '0.9.8'
gem 'ipaddress', '0.8.2'
full diff:
- bcrypt (3.1.10)
+ bcrypt (3.1.11)
- carrierwave (0.10.0)
+ carrierwave (0.11.2)
+ mimemagic (>= 0.3.0)
- concurrent-ruby (1.0.0)
+ concurrent-ruby (1.0.2)
- devise (3.5.6)
+ devise (4.1.1)
- railties (>= 3.2.6, < 5)
+ railties (>= 4.1.0, < 5.1)
- thread_safe (~> 0.1)
- domain_name (0.5.20160128)
+ domain_name (0.5.20160310)
- excon (0.45.4)
+ excon (0.49.0)
- excon (~> 0.45)
+ excon (~> 0.49)
****lots of stuff related to "fog" gem
- http (0.9.8)
+ http (0.9.9)
- ipaddress (0.8.2)
+ ipaddress (0.8.3)
- mime-types (2.99)
- mini_magick (4.4.0)
+ mime-types (2.99.1)
+ mimemagic (0.3.1)
+ mini_magick (4.5.1)
mini_portile2 (2.0.0)
- minitest (5.8.4)
- multi_json (1.11.2)
+ minitest (5.9.0)
+ multi_json (1.12.0)
- rails_stdout_logging (0.0.4)
+ rails_stdout_logging (0.0.5)
- responders (2.1.1)
+ responders (2.2.0)
- sprockets (3.5.2)
+ sprockets (3.6.0)
- sprockets-rails (3.0.1)
+ sprockets-rails (3.0.4)
- tilt (2.0.2)
+ tilt (2.0.4)
Rails 4.2.5, Ruby 2.1.4, I am on C9 IDE. But doesn't work on heroku neither.
UPDATE
reverted back to rake 10.5.0 (and did grep rake Gemfile.lock) now in the console I only get:
<Rake::Task fetch_ttt => [environment]>
scraping doesn't run at all :(
I don't think there's enough info here to give a definitive answer, but I would start by investigating the root cause for why it isn't working on heroku.
For example, does the rake task run at all? How do you know?
If so, do heroku run rails c and try doing the sequence of code yourself. Inspect the database records before and after you expect a chance. What happened?
If it didn't run, what type of output did you get? heroku logs can also be helpful.
One other little tip, it's possible to use byebug with heroku logs -t. Although I only recommend this in your staging environment and only if you're willing to clean up the git history afterwards.
In short, my answer is I would solve it by debugging more directly. Hope this helps.
outcommented
#require 'nokogiri'
#require 'open-uri'
and now it works. Even with rake 11.1.2

Rspec issue with method

I'm trying to make a simple validation, the main issue I thing is the Rails version (I have been using RSpec with Rails 4) because I'm using it with Rails 3.2 and Ruby 1.9.3.
This is the code in my Model
expect(section).to have(1).errors_on(:name)
and it return this error
1) Admin::Section is invalid without name
Failure/Error: expect(section).to have(1).errors_on(:name)
NoMethodError:
undefined method `have' for #<RSpec::ExampleGroups::AdminSection:0x007f81cf6e72d0>
My gem list is this
* rspec-core (3.0.1)
* rspec-expectations (3.0.1)
* rspec-mocks (3.0.1)
* rspec-rails (3.0.1)
* rspec-support (3.0.0)
I can make it pass with should be_valid but it is deprecated.
If I use have_at_least the error is on errors_on
See this pull request. have(n) was extracted rspec-collection_matchers gem
You can include it or just use one of the following:
expect(section.error_on(:name)size).to eq(1)
expect(section.error_on(:name)).to be_present
expect(section).to have_validation_error("your error message").on(:name)

Handling OmniAuth::Strategies::OAuth2::CallbackError in OmniAuth

How can I handle the error:
OmniAuth::Strategies::OAuth2::CallbackError
...generated by OmniAuth when a user goes through to the Facebook login, but decides to cancel?
I have seen a few threads about this, but none of the solutions worked for me.
I tried placing this:
OmniAuth.config.on_failure = UsersController.action(:oauth_failure)
...into the omniauth.rb initializer file with no success.
I am using the omniauth-facebook gem with Rails 4.0.2.
Any help greatly appreciated.
Many thanks!
Michael.
My gemfile.lock file reveals the following gems related to the omniauth-facebook gem:
oauth2 (0.8.1)
faraday (~> 0.8)
httpauth (~> 0.1)
jwt (~> 0.1.4)
multi_json (~> 1.0)
rack (~> 1.2)
omniauth (1.1.4)
hashie (>= 1.2, < 3)
rack
omniauth-facebook (1.5.1)
omniauth-oauth2 (~> 1.1.0)
omniauth-oauth2 (1.1.1)
oauth2 (~> 0.8.0)
omniauth (~> 1.0)
I upgraded the omniauth-facebook gem to version 1.0.6 and now it is working as expected.
For anyone else coming across this issue and would like to capture this error, here's what you need:
/config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'xxx', 'xxx', scope: "email,publish_stream,user_location,user_birthday"
end
/config/initializers/omniauth_failure_callback.rb
OmniAuth.config.on_failure = Proc.new do |env|
UsersController.action(:omniauth_failure).call(env)
end
/app/controllers/users_controller.rb
def omniauth_failure
flash[:danger] = "Unable to connect with Facebook at this time."
redirect_to root_url
end

Transferring users from Devise 1.1.7 to 2.2.3, for new application

I develop a new application and I want to transfer users from old one. I'd like to let them to use their own old password in new app.
OLD_APP:
config.encryptor = :authlogic_sha512
config.pepper = "xxx"
devise (1.1.7)
bcrypt-ruby (~> 2.1.2)
warden (~> 1.0.2)
NEW_APP:
devise (2.2.3)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
BCrypt
without pepper (config.pepper line left commented)
I used some solutions such as:
Converting existing password hash to Devise
but unfortunately it doesn't works.
My questions is how I could transform SHA512 hash (with salt) to BCrypt (without salt) ?
Whether anybody came across on this issue ?
Thanks.

Resources