Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Gzip support #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/tcr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def save_session

def use_cassette(name, options = {}, &block)
raise ArgumentError, "`TCR.use_cassette` requires a block." unless block
TCR.cassette = Cassette.new(name)
TCR.cassette = TCR::Cassette.build(name, configuration.serialize_with)
yield
TCR.cassette.save
ensure
Expand Down
48 changes: 10 additions & 38 deletions lib/tcr/cassette.rb
Original file line number Diff line number Diff line change
@@ -1,44 +1,16 @@
module TCR
class Cassette
attr_reader :name

def initialize(name)
@name = name

if File.exists?(filename)
@recording = false
@contents = File.open(filename) { |f| f.read }
@sessions = JSON.parse(@contents)
else
@recording = true
@sessions = []
end
end

def recording?
@recording
end

def next_session
if recording?
@sessions << []
@sessions.last
module Cassette
def self.build(name, type)
case type
when :gzip
TCR::Cassette::Gzip.new(name)
else
raise NoMoreSessionsError if @sessions.empty?
@sessions.shift
TCR::Cassette::JSON.new(name)
end
end

def save
if recording?
File.open(filename, "w") { |f| f.write(JSON.pretty_generate(@sessions)) }
end
end

protected

def filename
"#{TCR.configuration.cassette_library_dir}/#{name}.json"
end
end
end

require "tcr/cassette/base"
require "tcr/cassette/json"
require "tcr/cassette/gzip"
41 changes: 41 additions & 0 deletions lib/tcr/cassette/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module TCR
module Cassette
class Base
attr_reader :name

def initialize(name)
@name = name

if File.exist?(filename)
@recording = false
@sessions = deserialize
else
@recording = true
@sessions = []
end
end

def recording?
@recording
end

def next_session
if recording?
@sessions << []
@sessions.last
else
raise NoMoreSessionsError if @sessions.empty?
@sessions.shift
end
end

def save
serialize(@sessions) if recording?
end

def filename
File.join(TCR.configuration.cassette_library_dir, "#{name}.#{extension}")
end
end
end
end
25 changes: 25 additions & 0 deletions lib/tcr/cassette/gzip.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module TCR
module Cassette
class Gzip < Base
def initialize(_name)
super
end

def extension
:gz
end

def serialize(data)
Zlib::GzipWriter.open(filename) do |gz|
gz.write(Marshal.dump(data))
end
end

def deserialize
Zlib::GzipReader.open(filename) do |gz|
return Marshal.load(gz.read)
end
end
end
end
end
21 changes: 21 additions & 0 deletions lib/tcr/cassette/json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module TCR
module Cassette
class JSON < Base
def initialize(_name)
super
end

def extension
:json
end

def serialize(data)
File.binwrite(filename, ::JSON.pretty_generate(data))
end

def deserialize
::JSON.parse(File.binread(filename))
end
end
end
end
3 changes: 2 additions & 1 deletion lib/tcr/configuration.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module TCR
class Configuration
attr_accessor :cassette_library_dir, :hook_tcp_ports, :block_for_reads
attr_accessor :cassette_library_dir, :hook_tcp_ports, :block_for_reads, :serialize_with

def initialize
reset_defaults!
Expand All @@ -10,6 +10,7 @@ def reset_defaults!
@cassette_library_dir = "fixtures/tcr_cassettes"
@hook_tcp_ports = []
@block_for_reads = false
@serialize_with = :json
end
end
end
12 changes: 12 additions & 0 deletions lib/tcr/recordable_tcp_socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@

module TCR
class RecordableTCPSocket
module MockedIO
def self.wait_readable(_timeout)
true
end

def self.wait_writable(_timeout)
true
end
end

attr_reader :live, :socket
attr_accessor :recording

Expand Down Expand Up @@ -46,6 +56,8 @@ def write(str)
def to_io
if live
@socket.to_io
else
MockedIO
end
end

Expand Down
Binary file added spec/fixtures/google_http.gz
Binary file not shown.
26 changes: 25 additions & 1 deletion spec/tcr_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@
it "defaults to erroring on read/write mismatch access" do
TCR.configuration.block_for_reads.should be_falsey
end
end

it "has a default cassette type" do
TCR.configuration.serialize_with.should == :json
end
end

describe ".configure" do
it "configures cassette location" do
Expand All @@ -51,6 +55,12 @@
TCR.configure { |c| c.block_for_reads = true }
}.to change{ TCR.configuration.block_for_reads }.from(false).to(true)
end

it "configures cassette type" do
expect {
TCR.configure { |c| c.serialize_with = :gzip }
}.to change{ TCR.configuration.serialize_with }.from(:json).to(:gzip)
end
end

it "raises an error if you connect to a hooked port without using a cassette" do
Expand Down Expand Up @@ -225,6 +235,20 @@
}.not_to raise_error
end

it "supports gzip cassettes" do
TCR.configure { |c|
c.hook_tcp_ports = [80]
c.serialize_with = :gzip
}

expect {
TCR.use_cassette("spec/fixtures/google_http") do
body = Net::HTTP.get(URI('http://google.com/'))
expect(body).to_not be_empty
end
}.not_to raise_error
end

it "can stub the full session of a real server accepting a real email over SMTPS with STARTTLS" do
TCR.configure { |c|
c.hook_tcp_ports = [587]
Expand Down