DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • Efficiently Migrating From Jest to Vitest in a Next.js Project
  • Advanced Error Handling in JavaScript
  • Building a Tic-Tac-Toe Game Using React

Trending

  • Detection and Mitigation of Lateral Movement in Cloud Networks
  • Orchestrating Microservices with Dapr: A Unified Approach
  • Docker Base Images Demystified: A Practical Guide
  • How Kubernetes Cluster Sizing Affects Performance and Cost Efficiency in Cloud Deployments
  1. DZone
  2. Coding
  3. JavaScript
  4. Bring Ruby VCR to Javascript testing with Capybara and puffing-billy

Bring Ruby VCR to Javascript testing with Capybara and puffing-billy

By 
Swizec Teller user avatar
Swizec Teller
·
Mar. 15, 13 · Interview
Likes (0)
Comment
Save
Tweet
Share
7.7K Views

Join the DZone community and get the full member experience.

Join For Free

Let’s say you are writing an application in Ruby. You are probably talking to every API under the sun and are happily writing tests to make sure your code isn’t failing.

Because you don’t want to rely on 3rd parties or an internet connection to make your tests pass or fail you mock everything with let’s say, Webmock. This also makes your tests much much faster. After all even the fastest internet is much slower than the processor talking to its memory.

If you’re too lazy to mock out every API under the sun, you might use VCR to record requests and play them back later. The main advantage being, you don’t have to worry about meticulously reimplementing everything, and you can nuke the recordings at any time to make sure your code still works against the real API.

Life is good.

Enter Javascript, stage left

Then Javascript becomes more and more prominent. Suddenly your application’s logic is shifting from backend to browser and before you know it, most of your tests are pretty irrelevant.

You’re fine for a while with Capybara or Cucumber.

Launch a headless browser, click around the site from the comfort of RSpec, make sure users see what they’re supposed to. Balance restored.

Then you add a payment form. Or something. Suddenly your frontend is talking to an API. In case of Stripe or Balanced it’s even a feature. A great benefit for the user.

jQuery(function($) {
  $('#payment-form').submit(function(event) {
    var $form = $(this);
 
    // Disable the submit button to prevent repeated clicks
    $form.find('button').prop('disabled', true);
 
    Stripe.createToken($form, stripeResponseHandler);
 
    // Prevent the form from submitting with the default action
    return false;
  });
});

Well that sucks, you’re suddenly back to square one.

Your tests take minutes to execute. Your tests fail without an internet connection. Your tests rely on some 3rd party service being up. Your tests suck.

Who wants to code when running ~5 tests takes 3 minutes? Nobody.

Enter puffing-billy, stage right

The problem is that neither Webmock nor VCR can handle requests originating in a browser because they happen in a different thread and they can’t mess around with those.

Luckily, a year ago Olly Smith, created puffing-billy.

The idea was great – spin up a web proxy, tell your headless browser to use it, when your code makes a request it will go through the proxy, which will try to use a Webmock to handle it, otherwise pass it on to the vast internet.

But who wants to mock everything out manually?

Over the past few weeks I set upon the task of fixing this problem and restoring sanity to my life. Good tests are transparent to the application and I’ll be damned if I use any of the suggested solutions on the internet like “Well you just put a switch in your code that knows if you’re in a test and then doesn’t talk to Stripe”

Screw that.

This morning I submitted a pull request to puffing-billy.

I added the ability for puffing-billy to behave like it was VCR, but for your browser. When a request is made, it gets cached. The cache is then persisted between sessions, and requests are played back to the browser as needed.

It’s not as sophisticated as VCR just yet, but it gets the job done and my test runtime has gone from 3 minutes to just under a minute. That’s a big deal in my book!

The caching even understands that some URL’s are needlessly different on every request (social buttons, analytics etc.) so you can configure it to normalize those requests to a single recording that is played back every time. Your tests don’t really rely on gAnalytics working right?

And the best thing is, you don’t even have to change your tests.

You add something like this in your spec_helper.rb:

Billy.configure do |c|
  c.cache = true
  c.ignore_params = ["http://www.google-analytics.com/__utm.gif",
                     "http://b.siftscience.com/i.gif",
                     "https://r.twimg.com/jot",
                     "http://p.twitter.com/t.gif",
                     "http://p.twitter.com/f.gif",
                     "http://www.facebook.com/plugins/like.php",
                     "https://www.facebook.com/dialog/oauth",
                     "http://cdn.api.twitter.com/1/urls/count.json"]
  c.persist_cache = true
  c.cache_path = 'spec/req_cache/'
end
 
# need to call this because of a race condition between persist_cache
# being set and the proxy being loaded for the first time
Billy.proxy.restore_cache
 
Capybara.javascript_driver = :poltergeist_billy

A test for the payment form looks the same as usual:

    scenario "physical product" do
      product = start_buying build(:product, :physical, user: @seller, active: true)
 
      VCR.use_cassette('Balanced/purchase_with_cc') do
        within '#new_order' do
          fill_in 'order_email', with: Faker::Internet.safe_email
          fill_in_address
          fill_in_card
 
          click_on 'Buy Now'
        end
 
        page.should have_css('#receipt', :visible => true)
      end
 
      validate_receipt product, @seller
    end

Puffing-billy will transparently cache every requests the browser makes and VCR records any requests made by your backend logic. It’s pretty sweet.

What do you guys think? I only have 20 days of Ruby experience and the internet has told me it really wants something like this, but I couldn’t find anyone who’s already made it.



Testing JavaScript Requests Capybara (software)

Published at DZone with permission of Swizec Teller, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • Efficiently Migrating From Jest to Vitest in a Next.js Project
  • Advanced Error Handling in JavaScript
  • Building a Tic-Tac-Toe Game Using React

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!