Create feature specs for Devise OAuth with different providers - ruby-on-rails

I'm writing a Rails app with 100% test coverage. I have feature specs with Capybara for logging in with a username and password, but I don't have specs for logging in through Facebook or LinkedIn.
I didn't find an answer on the devise OmniAuth pages. Is this testable? Should I not be testing this?

I would take a look at https://github.com/plataformatec/devise/wiki/OmniAuth%3A-Overview
So what I’ve ended up creating 2 helpers in my support/omniauth.rb file:
def set_omniauth(opts = {})
default = {:provider => :facebook,
:uuid => "1234",
:facebook => {
:email => "foobar#example.com",
:gender => "Male",
:first_name => "foo",
:last_name => "bar"
}
}
credentials = default.merge(opts)
provider = credentials[:provider]
user_hash = credentials[provider]
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[provider] = {
'uid' => credentials[:uuid],
"extra" => {
"user_hash" => {
"email" => user_hash[:email],
"first_name" => user_hash[:first_name],
"last_name" => user_hash[:last_name],
"gender" => user_hash[:gender]
}
}
}
end
def set_invalid_omniauth(opts = {})
credentials = { :provider => :facebook,
:invalid => :invalid_crendentials
}.merge(opts)
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[credentials[:provider]] = credentials[:invalid]
end
With this sweet setup, I can now have multiple defaults in my tests, which makes changes very clean:
background do
set_omniauth()
click_link_or_button 'Sign up with Facebook'
end
Happy Hacking

Related

How to use aws_account_utils to create an AWS account ? Getting error : cannot load such file -- aws_account_utils

I want to use AWSAccountUtils in my project to create AWS account. I have installed gem aws_account_utils too. What more do I need to do or what is that I am missing ? In my controller I have defined following function and code is :
def create_aws_account
require 'aws_account_utils'
#account_details = []
#account_values = {}
aws_utils = AwsAccountUtils::AwsAccountUtils.new()
details = { 'fullName' => 'Devanshu Kumar',
'company' => 'ABC',
'addressLine1' => 'CP, Bund Garden Road',
'city' => 'Pune',
'state' => 'Maharastra',
'postalCode' => '411007',
'phoneNumber' => '1234567890',
'guess' => 'Test Account Dev' }
resp = aws_utils.create_account(account_name: 'My Test Account Devanshu Kumar',
account_email: 'devanshu.kumar#abc.com',
account_password: 'password',
account_details: details)
#account_values = {:account_number => data_disk.resp}
#account_details.push #account_values
render :json => { created_aws_account: account_details }
end
AWS Account Details Error Image

ruby on rails braintree fail on duplicate payment method

i am trying to implement braintree payments into a ruby app, and everything seems to be working fine, but when i pass fail_on_duplicate_payment_method_card as an option i am getting invalid keys: options[fail_on_duplicate_payment_method_card]
result = Braintree::PaymentMethod.create(
:customer_id => current_user.customer_cim_id,
:payment_method_nonce => 'fake-valid-amex-nonce',
:cardholder_name => "#{current_user.first_name} #{current_user.last_name}",
:options => {
:make_default => true,
:fail_on_duplicate_payment_method_card => true
}
)
if result.success?
customer = Braintree::Customer.find(current_user.customer_cim_id)
puts customer.id
puts customer.payment_methods[0].token
else
p result.errors
end
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact our support team.
fail_on_duplicate_payment_method_card should be fail_on_duplicate_payment_method.
result = Braintree::PaymentMethod.create(
:customer_id => current_user.customer_cim_id,
:payment_method_nonce => 'fake-valid-amex-nonce',
:cardholder_name => "#{current_user.first_name} #{current_user.last_name}",
:options => {
:make_default => true,
:fail_on_duplicate_payment_method => true
}
)

Mandrill / Mailchip Devise email works with mandrill_send but fails with Sidekiq

I am new to Mandrill so this may be the root cause of my issue :) - I have it working from this example:
https://nvisium.com/blog/2014/10/08/mandrill-devise-and-mailchimp-templates/
I don't think it's a Devise issue but I figured I would mention it. Here is my DeviseMailer code:
def invitation_instructions(record, token, opts={})
options = {
:subject => "Subject",
:from_name=> "From",
:email => record.email,
:global_merge_vars => [
{ name: 'invite_name', content: "Invited By" },
{ name: 'invite_email', content: "Invited By Email" },
{ name: 'invite_company', content: "Company Name" },
{ name: 'invitation_url', content: root_url(:invitation_token => token) } #accept_invitation_url(record, :invitation_token => token)
],
:template => "Invitation",
:template_name => "Invitation"
}
mandrill_send options
#MandrillEmail.perform_async(options)
end
def mandrill_send(opts={})
message = {
:subject=> "#{opts[:subject]}",
:from_name=> "#{opts[:from_name]}",
:from_email=>"do-not-reply#xxxxx.com",
:to=>
[{"email"=>"#{opts[:email]}",
"type"=>"to"}],
:global_merge_vars => opts[:global_merge_vars]
}
sending = MANDRILL.messages.send_template opts[:template], [], message
rescue Mandrill::Error => e
Rails.logger.debug("#{e.class}: #{e.message}")
raise
end
This works - I get my email and the templates work etc.
Now if I move the logic to a SideKiq worker (MandrillEmail.perform_async(options)) it fails with:
Mandrill::ValidationError: Validation error: {"template_name":"Sorry, this field can't be left blank.","message":{"to":[{"email":"Sorry, this field can't be left blank."}]}}
I added :template_name => "Invitation" but that doesn't work. My sidekiq monitor clearly shows both the template_name and message>to>email: params being passed into the worker.
Not sure what I am missing here.
Likely you are running into a string/symbol conflict. Symbols cannot be passed to Sidekiq jobs.
https://github.com/mperham/sidekiq/wiki/Best-Practices#1-make-your-job-parameters-small-and-simple

Testing OAuth with Capybara/Rspec for Facebook

I'm writing a test for Facebook integration. When I run rspec, I get the following error
Failure/Error: before { click_link "Sign in with Facebook" }
NoMethodError:
undefined method `provider' for #<Hash:0x007fbe98511798>
# ./app/models/user.rb:55:in `from_omniauth'
My OAuth mock contains
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:facebook] = {
'uid' => "999999",
'provider' => "facebook",
'extra' => {
'user_hash' => {
'email' => 'test#gmail.com',
'first_name' => 'First',
'last_name' => 'Last',
'gender' => 'Male'
}
},
'credentials' => {
'token' => "token1234qwert"
}
}
The exact place it apparently breaks is
def self.from_omniauth(auth)
where("fb_provider = ? and fb_uid = ?", auth.provider, auth.uid.to_s).first_or_initialize.tap do |user|
But when I do a puts auth.to_yaml as the first line in from_omniauth(auth) it shows provider: facebook along with everything else I included in my mock auth. I'm lost at this point. Any suggestions or help would be appreciated. Thanks.
Your code should be this:
where("fb_provider = ? and fb_uid = ?", auth['provider'], auth['uid'].to_s ...
This is because auth in this instance is a Hash object and Hash objects do not respond to methods by the same name as their keys. Instead, you should just use the Hash#[] method -- as I've demonstrated -- to access the value for those keys.

How to get gateway response from model into controller - Ruby on Rails

My application uses activemerchant to process payments. I'm using Eway as my payment gateway. I'm storing credit card details with Eway to keep them out of my application database.
I'm using a method store which returns a response with a customer billing id that I can use at a later time to process the order.
http://rdoc.info/github/Shopify/active_merchant/master/ActiveMerchant/Billing/EwayManagedGateway
My main issue is how do I get the response value into my controller so I can save it to the member model.
I've created a simple ruby file to test this all works and it does. I just need to convert this code to work inside my rails app.
require "rubygems"
gem 'activemerchant', '1.15.0'
require 'activemerchant'
ActiveMerchant::Billing::Base.mode = :production
gateway = ActiveMerchant::Billing::EwayManagedGateway.new(
:login => '12345678',
:username => 'mylogin#example.com',
:password => 'mypassword'
)
credit_card = ActiveMerchant::Billing::CreditCard.new(
:type => "visa",
:number => "4444333322221111",
:verification_value => "123",
:month => "11",
:year => "2011",
:first_name => "John",
:last_name => "Citizen"
)
options = {
:order_id => '1230123',
:ip => "127.0.0.1",
:email => 'john.citizen#example.com',
:billing_address => { :title => "Mr.",
:address1 => '123 Sample Street',
:city => 'Sampleville',
:state => 'NSW',
:country => 'AU',
:zip => '2000'
},
:description => 'purchased items'
}
if credit_card.valid?
response = gateway.store(credit_card, options)
if response.success?
puts "Credit Card Stored. #{response.message}"
customer = response.params['CreateCustomerResult']
puts "Customer Id: #{customer}"
else
puts "Error: #{response.message}"
end
else
puts "Error, credit card is not valid. #{credit_card.errors.full_messages.join('. ')}"
end
Here is the relevant code in my order model.
serialize :params
cattr_accessor :gateway
def response=(response)
self.success = response.success?
self.message = response.message
self.params = response.params
self.billing_id = response.params['CreateCustomerResult']
rescue ActiveMerchant::ActiveMerchantError => e
self.success = false
self.message = e.message
self.params = {}
self.billing_id = nil
end
def store
response = Order.gateway.store(credit_card, options)
end
Here is my order controller create code.
def create
#member = current_member
#order_deal = Deal.find(params[:deal_id])
#order = #order_deal.orders.build(params[:order])
#order.member_id = current_member.id
#order.ip_address = request.remote_ip
#deal = #order_deal
if #order.save
if #order.store
render :action => "success"
flash[:notice] = "Successfully processed your order."
else
render :action => "new"
end
else
render :action => 'new'
end
end
So essentially I want to get the
response.params['CreateCustomerResult']
and add it to my member model under
member.billing_id = response.params['CreateCustomerResult]
How can I do this?

Resources