Created
September 9, 2019 06:55
-
-
Save mikker/f7fc5efa3245190343187896ad99d58a to your computer and use it in GitHub Desktop.
Receive and expect Stripe webhook events in your Rails system tests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'system_helper' | |
RSpec.describe 'Something', type: :system do | |
it 'receives an event', :with_stripe_events do | |
make_request_at_stripe | |
wait_for_stripe_event { |e| e.type == 'charge.succeeded' } | |
expect(...) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'stripe' | |
require 'stripe_event' # https://github.com/integrallis/stripe_event | |
require 'json' | |
require 'open3' | |
# Expects bin/stripe-{platform} to be relevant version of stripe-cli | |
# https://github.com/stripe/stripe-cli | |
class StripeCli | |
class << self | |
def debug? | |
@debug ||= false | |
end | |
attr_writer :debug | |
end | |
def initialize(callback = nil, &block) | |
@callback = callback || block | |
end | |
def self.boot!(&block) | |
return if @instance | |
@instance = new(&block).boot! | |
end | |
def self.kill! | |
return unless @instance | |
@instance.kill! | |
@instance = nil | |
end | |
def boot! | |
@cli_thread = Thread.new do | |
puts "Booting Stripe CLI with #{cmd}" if debug? | |
meth = debug? ? :popen2 : :popen2e | |
Open3.send(meth, cmd) do |_in, out, _status| | |
out.each do |line| | |
case line | |
when /^{/ | |
start_buffering(line) | |
when /^}/ | |
json = flush_buffer(line) | |
puts json if debug? | |
begin | |
event = Stripe::Event.construct_from(json, symbolize_names: true) | |
@callback.call(event) | |
rescue => e | |
puts e.inspect | |
puts e.backtrace if debug? | |
end | |
else | |
write_to_buffer(line) if buffering? | |
end | |
end | |
rescue => e | |
puts e.inspect | |
puts e.backtrace if debug? | |
end | |
end | |
sleep 1 # wait for the cli to be mostly ready | |
self | |
end | |
def kill! | |
puts 'Killing Stripe CLI' if debug? | |
@cli_thread.kill | |
end | |
private | |
def debug? | |
self.class.debug? | |
end | |
def cmd | |
@cmd ||= | |
begin | |
cli = "bin/stripe-#{Gem::Platform.local.os}" | |
"#{cli} listen -p --config spec/stripe.toml" | |
end | |
end | |
def start_buffering(line) | |
@object_buffer = '' + line | |
end | |
def write_to_buffer(line) | |
@object_buffer += line | |
end | |
def flush_buffer(line) | |
@object_buffer += line | |
json = JSON.parse(@object_buffer) | |
@object_buffer = nil | |
json | |
end | |
def buffering? | |
!!@object_buffer | |
end | |
end | |
module WithStripeEventsHelpers | |
def register_stripe_event(event) | |
stripe_events.push(event) | |
end | |
def stripe_events | |
@stripe_events ||= [] | |
end | |
def wait_for_stripe_event | |
Timeout.timeout(15) do | |
loop do | |
break if stripe_events.find { |event| yield(event) } | |
sleep 0.1 | |
end | |
rescue Timeout::Error | |
puts 'Died waiting for Stripe event' | |
raise | |
end | |
end | |
end | |
RSpec.configure do |config| | |
config.include WithStripeEventsHelpers, with_stripe_events: true | |
config.before(:each, with_stripe_events: true) do | |
StripeCli.boot! do |event| | |
register_stripe_event event | |
StripeEvent.instrument(event) | |
end | |
end | |
config.after(:each, with_stripe_events: true) do | |
StripeCli.kill! | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment