I am trying to test my app and remote control. I use Rails 3.2 and lastest version of vcr and fakeweb. Actually I have watched RailsCast and now i want to do anti testing but I cannot.
My request test file;
require "spec_helper"
describe "ZipCodeLookup" do
it "show Beverly Hills given 90210", :vcr do
visit root_path
fill_in "zip_code", with: "90210"
click_on "Lookup"
page.should have_content("Beverly Hills")
end
it "any errors" do
visit root_path
fill_in "zip_code", with: "9"
click_on "Lookup"
page.should have_content("Nomethods")
end
end
do not get stuck in page.should line. I just tried how I can make an anti test.
and my model;
class ZipCode
attr_reader :state, :city, :area_code, :time_zone
def initialize(zip)
client = Savon::Client.new("http://www.webservicex.net/uszip.asmx?WSDL")
response = client.request :web, :get_info_by_zip, body: { "USZip" => zip }
data = response.to_hash[:get_info_by_zip_response][:get_info_by_zip_result][:new_data_set][:table]
#state = data[:state]
#city = data[:city]
#area_code = data[:area_code]
#time_zone = data[:time_zone]
end
end
And the error when I run bundle exec rspec spec/requests/zip_code_lookup_spec.rb
Ender-iMac:zip_coder-after ender$ bundle exec rspec spec/requests/zip_code_lookup_spec.rb
HTTPI executes HTTP GET using the net_http adapter
SOAP request: http://www.webservicex.net/uszip.asmx
SOAPAction: "http://www.webserviceX.NET/GetInfoByZIP", Content-Type: text/xml;charset=UTF-8, Content-Length: 389
<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://www.webserviceX.NET" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ins0="http://www.webserviceX.NET"><env:Body><ins0:GetInfoByZIP><ins0:USZip>90210</ins0:USZip></ins0:GetInfoByZIP></env:Body></env:Envelope>
HTTPI executes HTTP POST using the net_http adapter
SOAP response (status 200):
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><GetInfoByZIPResponse xmlns="http://www.webserviceX.NET"><GetInfoByZIPResult><NewDataSet xmlns=""><Table><CITY>Beverly Hills</CITY><STATE>CA</STATE><ZIP>90210</ZIP><AREA_CODE>310</AREA_CODE><TIME_ZONE>P</TIME_ZONE></Table></NewDataSet></GetInfoByZIPResult></GetInfoByZIPResponse></soap:Body></soap:Envelope>
.HTTPI executes HTTP GET using the net_http adapter
F
Failures:
1) ZipCodeLookup any errors
Failure/Error: click_on "Lookup"
FakeWeb::NetConnectNotAllowedError:
Real HTTP connections are disabled. Unregistered request: GET http://www.webservicex.net/uszip.asmx?WSDL. You can use VCR to automatically record this request and replay it later. For more details, visit the VCR documentation at: http://relishapp.com/myronmarston/vcr/v/1-11-3
# ./app/models/zip_code.rb:6:in `initialize'
# ./app/controllers/zip_code_lookup_controller.rb:3:in `new'
# ./app/controllers/zip_code_lookup_controller.rb:3:in `index'
# (eval):2:in `click_on'
# ./spec/requests/zip_code_lookup_spec.rb:15:in `block (2 levels) in <top (required)>'
Finished in 0.17138 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/requests/zip_code_lookup_spec.rb:12 # ZipCodeLookup any errors
I do not understand why VCR cannot run same HTTP request in different states.
How can I test in anti test way?
SOLUTION
Sorry it was my mistake :( I forgot to write :vcr in "it" description line. it should be like this
it "any errors", :vcr do
visit root_path
fill_in "zip_code", with: "9"
click_on "Lookup"
page.should have_content("Nomethods")
end
Related
I'm using Capybara to test my project. But i have a problem.
I have some remote forms on my project. They add records via ajax. When i'm testing with capybara it works well on development environment. It visits the page, fills in the form and submits. Booom, record has been added and test didnt fail.
But when i run rspec with test environments i'm getting unknown format exception.
1) add new address user adds new address
Failure/Error: find("input[value='Adres Ekle']").click
ActionController::UnknownFormat:
Account::AddressesController#create is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []
# ./spec/features/user_add_new_address_spec.rb:28:in `block (2 levels) in <top (required)>'
I've also tried to respond via js from controller like;
def create
request.format = :js
end
Then it returns;
1) add new address user adds new address
Failure/Error: find("input[value='Adres Ekle']").click
ActionController::UnknownFormat:
Account::AddressesController#create is missing a template for this request format and variant.
request.formats: ["text/javascript"]
request.variant: []
# ./spec/features/user_add_new_address_spec.rb:28:in `block (2 levels) in <top (required)>'
And my scenario if u want more info;
scenario 'user adds new address' do
expect(page).to have_content 'Kayıtlı Adreslerim'
find("a[title='Adres Ekle']").click
expect(page).to have_content 'Yeni Adres Ekle'
expect(page).to have_content 'Adres Başlığı'
fill_in 'address[name]', with:'Izmir Ofisi'
select('Izmir', :from => 'address[city_id]')
fill_in 'address[address]', with: 'Lorem ipsum dolor sit amet.'
find("input[value='Adres Ekle']").click # It submits remote: true form.
expect(page).to have_content 'Success!'
end
PS: my create action doesnt render something like that.
its like;
def create
#new_address = Address.new
#address = #current_account.addresses.new(address_params)
if #address.save
#check = true
else
#check = false
end
end
it renders: create.js.erb
<% if #check %>
if($('.addresses').length) {
$('.addresses').append('<%= j(render('account/addresses/address', address: #address)) %>');
}
if($('#did-addresses').length){
$('#did-addresses').append("<%= "<option selected='true' value='#{#address.id}'>#{#address.name}</option>".html_safe %>").selectpicker('refresh');
}
$('#new-address').html('<%= j(render('account/addresses/form', new_address: #new_address)) %>');
swal({
type: 'success',
title: "<%= t('response.success') %>",
text: "<%= t('flash.actions.create.notice', resource_name: Address.model_name.human) %>",
timer: 2000
});
quickview.close('#new-address');
<% else %>
<% #address.errors.each do |error| %>
<% end %>
<% end %>
$('.preloader').fadeOut();
I was facing the same case in rails 6 but I fixed it be adding js: true to the scenario and it automatically worked well.
scenario 'Should delete the feature', js: true do
# Your logic
# Your expectations
end
Since copying your development config over your test config fixed your issue, it sounds like you probably an error in one of your JS files. Normally in the test and production environment all of your JS assets get concatenated into one file which means an error in any one of them can prevent the code in the others from being executed. In the development environment each JS file is loaded separately which means an error in any file can only affect the rest of the code in that file. Check your the console in your browser for any JS errors when going to the page in question and fix them.
I'm trying to access Braintree's hosted fields with the following code:
within_frame('braintree-hosted-field-number') do
fill_in 'Credit card number', with: '4111-1111-1111-1111'
end
The frame's name is correct, I copied it from the inspect panel on Chrome.
But I get this error
Capybara::Webkit::InvalidResponseError:
Unable to locate frame.
What am I doing wrong? Or, more importantly, how do I debug this/see what's going on?
Edit
Here is my code, as requested. Note that the whole system works fine if I go through and manually fill out the fields and submit the form.
Slim
= f.fields_for :user do |u|
.control-group.col-24.payment-details
label.half
.field-title First Name
= u.text_field :first_name
label.half
.field-title Last Name
= u.text_field :last_name
label.full
.field-title Email for receipt
= u.email_field :email
label.full
.field-title Credit card number
.bt-field#credit-card
label.half
.field-title Expiry date
.bt-field#exp-card
label.half
.field-title CVC
.bt-field#cvv-card
script src="https://js.braintreegateway.com/js/braintree-2.24.0.min.js"
CoffeeScript
braintree.setup(clientToken, "custom", {
id: "donate-form",
onPaymentMethodReceived: (obj)->
formdata = donationForm.getFormData()
formdata.set "payment_method_nonce", obj.nonce
donationForm.send(formdata)
onError: (obj)->
errors = []
switch obj.type
when "VALIDATION"
errors.push "Invalid payment details. Please correct your payment details."
else
errors.push "Something went wrong. Please check your payment details and try again."
donationForm.printErrors("donation-errors", errors)
hostedFields: {
styles: {
"input": {
"font-size": "14px",
"font-weight": "bold",
"font-family": "Lato, Helvetica, Arial, Geneva, sans-serif",
"color": "#464646;",
"transition": colorTransition,
"-webkit-transition": colorTransition
},
".invalid": { color: "#DD0000"} },
number: {selector: "#credit-card"},
cvv: {selector: "#cvv-card"},
expirationDate: {selector: "#exp-card", "placeholder": "dd/mm"}
}
})
Edit 2
donation_module_spec.rb
require "rails_helper"
RSpec.feature "Donation Module", type: :feature do
scenario "Wrong public token" do
visit "/donate?t=BAD_URL&frame=1"
expect(page).to have_content("Are you sure you're installing this on the correct website?")
end
scenario "Public visitor creates a new donation", driver: :webkit do
#load page
website = create(:website)
page.driver.header 'Referer', website.website
visit "/donate?t=#{website.public_token}&frame=1"
#verify page 1 loaded
expect(page).not_to have_content("Are you sure you're installing this on the correct website?")
#fill page 1
find("input[value='20'] ~ div").click
#go to page 2
find("#credit-details").click
#verify page 2 content is loaded
expect(find(".total-cost-text")).to be_visible
#fill page 2
fill_in 'First Name', with: 'Leeroy'
fill_in 'Last Name', with: 'Jenkins'
fill_in 'Email for receipt', with: 'new_donor#email.com'
sleep 5
within_frame('braintree-hosted-field-number') do
fill_in 'Credit card number', with: '4111-1111-1111-1111'
end
within_frame('#braintree-hosted-field-expirationDate') do
fill_in '#expiration', with: '09/19'
end
within_frame('#braintree-hosted-field-cvv') do
fill_in '#cvv', with: '123'
end
find('Make payment').click
# expect to make a new user, new donation, new receipt, emailed receipt
end
end
rails_helper.rb
Modified to show only the related parts:
require 'capybara/rails'
require 'capybara/rspec'
Capybara::Webkit.configure do |config|
config.allow_url("js.braintreegateway.com")
config.allow_url("fonts.googleapis.com")
config.allow_unknown_urls
config.debug = true
end
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = false
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
I don't have an answer for you as to why this might be happening, copying your setup I'm able to get it to work. I do have a couple of additional thoughts that may help.
1) Take a look at the debug output (looks like you already have this enabled with config.debug = true) and make sure there are no errors. Here are the relevant parts of my output -
"Visit(http:/localhost:3000/hostedfields_payment)" started page load
Started request to "http://localhost:3000/hostedfields_payment"
Finished "Visit(http:/localhost:3000/hostedfields_payment)" with response "Success()"
Started request to "https://js.braintreegateway.com/js/braintree-2.17.5.js"
Started request to "https://api.sandbox.braintreegateway.com/merchants/-/client_api/v1/configuration?-
Received 200 from "https://api.sandbox.braintreegateway.com/merchants/-/client_api/v1/configuration?-
Received "FrameFocus(braintree-hosted-field-number)"
Load started
Started request to "https://assets.braintreegateway.com/hosted-fields/2.17.5/hosted-fields-frame.html#91586a91-c55f-4e51-80e6-7cd750f9c750"
Started request to "https://assets.braintreegateway.com/hosted-fields/2.17.5/hosted-fields-frame.html#91586a91-c55f-4e51-80e6-7cd750f9c750"
Started request to "https://assets.braintreegateway.com/hosted-fields/2.17.5/hosted-fields-frame.html#91586a91-c55f-4e51-80e6-7cd750f9c750"
"TimeoutCommand" waiting for load to finish
Started request to "https://assets.braintreegateway.com/hosted-fields/2.17.5/braintree-hosted-fields-internal.min.js"
Received 200 from "https://assets.braintreegateway.com/hosted-fields/2.17.5/hosted-fields-frame.html#91586a91-c55f-4e51-80e6-7cd750f9c750"
Received 200 from "https://assets.braintreegateway.com/hosted-fields/2.17.5/hosted-fields-frame.html#91586a91-c55f-4e51-80e6-7cd750f9c750"
Received 200 from "https://assets.braintreegateway.com/hosted-fields/2.17.5/hosted-fields-frame.html#91586a91-c55f-4e51-80e6-7cd750f9c750"
Received 200 from "https://assets.braintreegateway.com/hosted-fields/2.17.5/braintree-hosted-fields-internal.min.js"
Page finished with true
Load finished
Started "FrameFocus(braintree-hosted-field-number)"
Finished "FrameFocus(braintree-hosted-field-number)" with response "Success()"
Wrote response true ""
Received "FindCss(input#credit-card-number)"
Started "FindCss(input#credit-card-number)"
Finished "FindCss(input#credit-card-number)" with response "Success()"
2) A gnarly way you could check is at the end your sleep 5, print the body to a file and open it up. You can check that the iframes exist.
File.open("looking_for_iframes.html", "w") do |file|
file.print(page.body)
end
Otherwise feel free to reach out to Braintree Support.
TL;DR—How do I access fields within Braintree's Hosted Fields' iframes?
I want to test a UX flow of paying a donation through Braintree. This is my code so far:
require "rails_helper"
RSpec.feature "Donation Module", type: :feature do
scenario "Public visitor creates a new donation" do
#load page
website = create(:website)
Capybara.current_session.driver.header 'Referer', website.website
visit "/donate?t=#{website.public_token}&frame=1"
#verify page loaded
expect(page).not_to have_content("Are you sure you're installing this on the correct website?")
#fill page 1
find("input[value='20']").click
#go to page 2
find("#credit-details").click
#verify page 2 content is loaded
expect(find(".total-cost-text")).to be_visible
#fill page 2
fill_in 'First Name', with: 'Leeroy'
fill_in 'Last Name', with: 'Jenkins'
fill_in 'Email for receipt', with: 'new_donor#email.com'
within_frame('#braintree-hosted-field-number') do
fill_in '#credit-card-number', with: '4111-1111-1111-1111'
end
within_frame('#braintree-hosted-field-expirationDate') do
fill_in '#expiration', with: '09/19'
end
within_frame('#braintree-hosted-field-cvv') do
fill_in '#cvv', with: '123'
end
find('Make payment').click
# expect to make a new user, new donation, new receipt, email receipt
end
end
Currently, it's breaking at the first within_frame saying Capybara::NotSupportedByDriverError:
Capybara::Driver::Base#within_frame
How do I access fields inside BT's iframes?
Well, I am writing here not exactly an answer to this question, but rather corrections to the question, as I was in the similar situation and was facing similar errors such as Selenium::WebDriver::Error::NoSuchFrameError: Unable to locate frame: #braintree-hosted-field-number and Test::Unit::Capybara::ElementNotFound: Unable to find field "#credit-card-number".
The within_frame should have the following format (the #-sign for ID should be removed from both):
within_frame('braintree-hosted-field-number') do
fill_in 'credit-card-number', :with => number
end
And in order to use the selenium driver in Test::Unit, I used the following helper:
def js
Capybara.current_driver = Capybara.javascript_driver
yield
Capybara.current_driver = Capybara.use_default_driver
end
And then wrapped my tests in it:
class SomeTest < ActionDispatch::IntegrationTest
test "should ..." do
js do
within_frame('braintree-hosted-field-number') do
fill_in 'credit-card-number', :with => number
end
# ...
end
end
Hopefully, someone will find it useful while using Unit Tests.
Seems like you're using the rack_test driver? That doesn't support JS or frames so braintree isn't going to work with that. You need to switch to one of the real browser drivers like selenium, capybara-webkit, or poltergeist.
I have a problem, I can run a test that uses vcr on its own and it works, it creates the cassette and it uses that on the next test. Great.
The problem is when I run all my tests together this particular test fails, because webmock disables http connections, I have seen this example on the Github repo page that explains how to expect real and not stubbed requests
My question is how Do I say: Allow Http connections for requests UNLESS there is a cassette. It should also CREATE the cassette when HTTP connections are allowed.
The VCR Settings
require 'vcr'
VCR.configure do | c |
if !ARGV.first.nil?
c.default_cassette_options = { :record => :new_episodes, :erb => true }
c.filter_sensitive_data('<BLACKBIRD_API_KEY>') {YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_KEY'].to_s}
c.filter_sensitive_data('<BLACKBIRD_API_URL>') {YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_URL'].to_s}
c.debug_logger = File.open(ARGV.first, 'w')
c.cassette_library_dir = 'spec/vcr'
c.hook_into :webmock
end
end
the above if statement exists because not EVERY test creates a cassette. So we want them to run when a cassette isn't needed.
The Test
require 'spec_helper'
describe Xaaron::Publishers::Users do
context "publish created users" do
before(:each) do
Xaaron.configuration.reset
no_user_member_roles_relation
Xaaron.configuration.publish_to_black_bird = true
Xaaron.configuration.black_bird_api_url = YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_URL']
Xaaron.configuration.black_bird_api_key =YAML.load(File.read('config/application.yml'))['BLACKBIRD_API_KEY']
end
it "should publish to blackbird" do
VCR.use_cassette 'publisher/create_user_response' do
expect(
Xaaron::Publishers::Users.publish_new_user({user: {
first_name: 'adsadsad', user_name: 'sasdasdasdsa' ,
email: 'asdassad#sample.com', auth_token: 'asdsadasdasdsa'
}}).code
).to eql 200
end
end
end
end
Runs fine on its own, creates the cassette, fails when run with all other tests due to webmock.
The Failure
Failure/Error: Xaaron::Publishers::Users.publish_new_user({user: {
WebMock::NetConnectNotAllowedError:
Real HTTP connections are disabled. Unregistered request: GET some_site_url_here with headers {'Http-Authorization'=>'api_key_here', 'User-Agent'=>'Typhoeus - https://github.com/typhoeus/typhoeus'}
You can stub this request with the following snippet:
stub_request(:get, "some site url here").
with(:headers => {'Http-Authorization'=>'some api key here', 'User-Agent'=>'Typhoeus - https://github.com/typhoeus/typhoeus'}).
to_return(:status => 200, :body => "", :headers => {})
When I run rspec to run all tests, they all pass, but when I give a specific filename, it fails.
$ rspec spec/controllers/refinery/books/admin/books_controller_spec.rb
2) Refinery::Books::Admin::BooksController GET :new responds 200 success
Failure/Error: login_admin_user #Gives 404
WebMock::NetConnectNotAllowedError:
Real HTTP connections are disabled. Unregistered request: POST http://localhost:8981/solr/default/update?wt=ruby with body '<?xml ...' with headers {'Content-Type'=>'text/xml'}
You can stub this request with the following snippet:
stub_request(:post, "http://localhost:8981/solr/default/update?wt=ruby").
with(:body => "<?xml ...",
:headers => {'Content-Type'=>'text/xml'}).
to_return(:status => 200, :body => "", :headers => {})
registered request stubs:
stub_request(:post, "http://localhost:8983/solr/test/update?wt=ruby").
with(:headers => {'Content-Type'=>'text/xml'})
============================================================
# ./lib/rsolr/connection.rb:15:in `execute'
# (eval):2:in `post'
# ./spec/support/controller_macros.rb:21:in `login_admin_user'
I have it mocked & stubbed already, so why is it failing? The only thing I can see is the existing stub is '/test/' and the request is '/default/'. How did that change?
Ok I ran into this problem again on another spec. Here is the spec:
https://gist.github.com/starrychloe/1d79d9925f9b79ae5c01
I did find this solr/solr.xml
<?xml version="1.0" encoding="UTF-8" ?>
<solr persistent="false">
<cores adminPath="/admin/cores" host="${host:}" hostPort="${jetty.port:}">
<core name="default" instanceDir="." dataDir="default/data"/>
<core name="development" instanceDir="." dataDir="development/data"/>
<core name="test" instanceDir="." dataDir="test/data"/>
</cores>
</solr>
It's like rspec is running in production environment, even if I explicitely give the environment
$ RAILS_ENV=test rspec spec/controllers/refinery/books/books_controller_spec.rb
I think it is an rspec problem. rspec -v: version 2.14.7.
I added stub_request(:post, "http://localhost:8981/solr/default/update?wt=ruby").to_return(:status => 200, :body => "", :headers => {}) before login_admin_user but I don't think that's the root solution.
It is probably interacting with another test.
Try running the suite in random order
rspec spec --order rand
and/or try running all the tests for that controller or or controllers.
You are using webmock, which disables all HTTP connections by default.
You can modify you Gemfile to disable auto require as followed:
gem "webmock", :require => false
And require webmock where you need it (e.g., require 'webmock/rspec'). After disabling HTTP connections for certain tests, remember to WebMock.allow_net_connect! to allow real http connections for other tests.
Another alternative is to WebMock.disable_net_connect!(:allow_localhost => true) to disable external requests while allowing localhost.