shopify-tcr 0.0.5.pre.shopify

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5765907faf7f2ab832ec3c3d3b5477cd88dedda1
4
+ data.tar.gz: 3ab7b0a348ed8ec457f26cc910eba7c33aa602b7
5
+ SHA512:
6
+ metadata.gz: 7b6358e5fca32fba779383cb6f0b12f39a00d03f443bc9940eb12e37442058c1c4c055e82914fe42684fe5268f77518605dfb263b368dd6136116c9b4a8ec4b8
7
+ data.tar.gz: f9c552dc0527e9f190393a85b7fa66997915e111db60293390d77b4c1e8424ca0a19d480c4535f198ad7ae9dd83048b774fd061c46f947bb92583bbb6aac983a
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3@tcr --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tcr.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Rob Forman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # TCR (TCP + VCR)
2
+
3
+ TCR is a *very* lightweight version of [VCR](https://github.com/vcr/vcr) for TCP sockets.
4
+
5
+ Currently used for recording 'net/smtp' interactions so only a few of the TCPSocket methods are recorded out.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'tcr'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install tcr
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ require 'test/unit'
25
+ require 'tcr'
26
+
27
+ TCR.configure do |c|
28
+ c.cassette_library_dir = 'fixtures/tcr_cassettes'
29
+ c.hook_tcp_ports = [25]
30
+ end
31
+
32
+ class TCRTest < Test::Unit::TestCase
33
+ def test_example_dot_com
34
+ TCR.use_cassette('google_smtp') do
35
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
36
+ io = Net::InternetMessageIO.new(tcp_socket)
37
+ assert_match /220 mx.google.com ESMTP/, io.readline
38
+ end
39
+ end
40
+ end
41
+ ```
42
+
43
+ Run this test once, and TCR will record the tcp interactions to fixtures/tcr_cassettes/google_smtp.json.
44
+
45
+ ```json
46
+ [
47
+ [
48
+ [
49
+ "read",
50
+ "220 mx.google.com ESMTP x3si2474860qas.18 - gsmtp\r\n"
51
+ ]
52
+ ]
53
+ ]
54
+ ```
55
+
56
+ Run it again, and TCR will replay the interactions from json when the tcp request is made. This test is now fast (no real TCP requests are made anymore), deterministic and accurate.
57
+
58
+ You can disable TCR hooking TCPSocket ports for a given block via `turned_off`:
59
+
60
+ ```ruby
61
+ TCR.turned_off do
62
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
63
+ end
64
+ ```
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ RSpec::Core::RakeTask.new('spec')
4
+ task :default => :spec
data/lib/tcr.rb ADDED
@@ -0,0 +1,67 @@
1
+ require "tcr/cassette"
2
+ require "tcr/configuration"
3
+ require "tcr/errors"
4
+ require "tcr/recordable"
5
+ require "tcr/socket_extension"
6
+ require "tcr/ssl_socket_extension"
7
+ require "tcr/version"
8
+ require "socket"
9
+ require "json"
10
+
11
+ module TCR
12
+ ALL_PORTS = '*'
13
+
14
+ extend self
15
+
16
+ def configure
17
+ yield configuration
18
+ end
19
+
20
+ def configuration
21
+ @configuration ||= Configuration.new
22
+ end
23
+
24
+ def cassette
25
+ @cassette
26
+ end
27
+
28
+ def cassette=(v)
29
+ @cassette = v
30
+ end
31
+
32
+ def disabled
33
+ @disabled || false
34
+ end
35
+
36
+ def disabled=(v)
37
+ @disabled = v
38
+ end
39
+
40
+ def record_port?(port)
41
+ !disabled && configuration.hook_tcp_ports == ALL_PORTS || configuration.hook_tcp_ports.include?(port)
42
+ end
43
+
44
+ def use_cassette(name, options = {}, &block)
45
+ raise ArgumentError, "`TCR.use_cassette` requires a block." unless block
46
+ begin
47
+ TCR.cassette = Cassette.build(name)
48
+ yield TCR.cassette
49
+ ensure
50
+ TCR.cassette.finish
51
+ TCR.cassette = nil
52
+ end
53
+ end
54
+
55
+ def turned_off(&block)
56
+ raise ArgumentError, "`TCR.turned_off` requires a block." unless block
57
+ begin
58
+ disabled = true
59
+ yield
60
+ ensure
61
+ disabled = false
62
+ end
63
+ end
64
+ end
65
+
66
+ TCPSocket.prepend(TCR::SocketExtension)
67
+ OpenSSL::SSL::SSLSocket.send(:include, TCR::SSLSocketExtension)
@@ -0,0 +1,176 @@
1
+ module TCR
2
+ class Cassette
3
+ attr_reader :name
4
+
5
+ def self.build(name)
6
+ if cassette_exists?(name)
7
+ RecordedCassette.new(name)
8
+ else
9
+ RecordingCassette.new(name)
10
+ end
11
+ end
12
+
13
+ def self.filename(name)
14
+ "#{TCR.configuration.cassette_library_dir}/#{name}.json"
15
+ end
16
+
17
+ def self.cassette_exists?(name)
18
+ File.exists?(filename(name))
19
+ end
20
+
21
+ def initialize(name)
22
+ @name = name
23
+ end
24
+
25
+ protected
26
+
27
+ def filename
28
+ self.class.filename(name)
29
+ end
30
+
31
+ class RecordingCassette < Cassette
32
+ attr_reader :originally_recorded_at
33
+
34
+ def initialize(*args)
35
+ super
36
+ @originally_recorded_at = Time.now
37
+ end
38
+
39
+ def sessions
40
+ @sessions ||= []
41
+ end
42
+
43
+ def next_session
44
+ Session.new.tap do |session|
45
+ sessions << session
46
+ end
47
+ end
48
+
49
+ def finish
50
+ FileUtils.mkdir_p(File.dirname(filename))
51
+ File.open(filename, "w") { |f| f.write(serialized_form) }
52
+ end
53
+
54
+ private
55
+
56
+ def serialized_form
57
+ raw = {
58
+ "originally_recorded_at" => originally_recorded_at,
59
+ 'sessions' => sessions.map(&:as_json)
60
+ }
61
+ JSON.pretty_generate(raw)
62
+ end
63
+
64
+ def empty?
65
+ true
66
+ end
67
+
68
+ class Session
69
+ def initialize
70
+ @recording = []
71
+ end
72
+
73
+ def connect(&block)
74
+ next_command('connect', ret: nil, &block)
75
+ end
76
+
77
+ def close(&block)
78
+ next_command('close', &block)
79
+ end
80
+
81
+ def read(*args, &block)
82
+ next_command('read', data: args, &block)
83
+ end
84
+
85
+ def write(str, &block)
86
+ next_command('write', data: str, &block)
87
+ end
88
+
89
+ def as_json
90
+ {"recording" => @recording}
91
+ end
92
+
93
+ private
94
+
95
+ def next_command(command, options={}, &block)
96
+ yield.tap do |return_value|
97
+ return_value = options[:ret] if options.has_key?(:ret)
98
+ @recording << [command, return_value] + Array(options[:data])
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ class RecordedCassette < Cassette
105
+ def sessions
106
+ @sessions ||= serialized_form['sessions'].map{|raw| Session.new(raw)}
107
+ end
108
+
109
+ def originally_recorded_at
110
+ serialized_form['originally_recorded_at']
111
+ end
112
+
113
+ def next_session
114
+ session = sessions.shift
115
+ raise NoMoreSessionsError unless session
116
+ session
117
+ end
118
+
119
+ def finish
120
+ # no-op
121
+ end
122
+
123
+ def empty?
124
+ sessions.all?(&:empty?)
125
+ end
126
+
127
+ private
128
+
129
+ def serialized_form
130
+ @serialized_form ||= begin
131
+ raw = File.open(filename) { |f| f.read }
132
+ JSON.parse(raw)
133
+ end
134
+ end
135
+
136
+ class Session
137
+ def initialize(raw)
138
+ @recording = raw["recording"]
139
+ end
140
+
141
+ def connect
142
+ next_command('connect')
143
+ end
144
+
145
+ def close
146
+ next_command('close')
147
+ end
148
+
149
+ def read(*args)
150
+ next_command('read') do |str, *data|
151
+ raise TCR::DataMismatchError.new("Expected to read to be called with args '#{args.inspect}' but was called with '#{data.inspect}'") unless args == data
152
+ end
153
+ end
154
+
155
+ def write(str)
156
+ next_command('write') do |len, data|
157
+ raise TCR::DataMismatchError.new("Expected to write '#{str}' but next data in recording was '#{data}'") unless str == data
158
+ end
159
+ end
160
+
161
+ def empty?
162
+ @recording.empty?
163
+ end
164
+
165
+ private
166
+
167
+ def next_command(expected)
168
+ command, return_value, data = @recording.shift
169
+ raise TCR::CommandMismatchError.new("Expected to '#{expected}' but next in recording was '#{command}'") unless expected == command
170
+ yield return_value, *data if block_given?
171
+ return_value
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,14 @@
1
+ module TCR
2
+ class Configuration
3
+ attr_accessor :cassette_library_dir, :hook_tcp_ports
4
+
5
+ def initialize
6
+ reset_defaults!
7
+ end
8
+
9
+ def reset_defaults!
10
+ @cassette_library_dir = "fixtures/tcr_cassettes"
11
+ @hook_tcp_ports = []
12
+ end
13
+ end
14
+ end
data/lib/tcr/errors.rb ADDED
@@ -0,0 +1,6 @@
1
+ module TCR
2
+ class TCRError < StandardError; end
3
+ class NoMoreSessionsError < TCRError; end
4
+ class CommandMismatchError < TCRError; end
5
+ class DataMismatchError < TCRError; end
6
+ end
@@ -0,0 +1,45 @@
1
+ module TCR
2
+ module Recordable
3
+ attr_accessor :cassette
4
+
5
+ def recording
6
+ @recording ||= cassette.next_session
7
+ end
8
+
9
+ def connect
10
+ recording.connect do
11
+ super
12
+ end
13
+ end
14
+
15
+ def read_nonblock(bytes)
16
+ recording.read do
17
+ super
18
+ end
19
+ end
20
+
21
+ def gets(*args)
22
+ recording.read do
23
+ super
24
+ end
25
+ end
26
+
27
+ def write(str)
28
+ recording.write(str) do
29
+ super
30
+ end
31
+ end
32
+
33
+ def read(*args)
34
+ recording.read do
35
+ super
36
+ end
37
+ end
38
+
39
+ def close
40
+ recording.close do
41
+ super
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ module TCR
2
+ module SocketExtension
3
+ def initialize(address, port, *args)
4
+ super
5
+ if TCR.record_port?(port) && TCR.cassette
6
+ extend(Recordable)
7
+ self.cassette = TCR.cassette
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module TCR
2
+ module SSLSocketExtension
3
+ def self.included(klass)
4
+ klass.send(:alias_method, :initialize_without_tcr, :initialize)
5
+ klass.send(:alias_method, :initialize, :initialize_with_tcr)
6
+ end
7
+
8
+ def initialize_with_tcr(s, context)
9
+ initialize_without_tcr(s, context)
10
+ if TCR.record_port?(s.remote_address.ip_port) && TCR.cassette
11
+ extend(TCR::Recordable)
12
+ self.cassette = TCR.cassette
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module TCR
2
+ VERSION = "0.0.5-shopify"
3
+ end
@@ -0,0 +1,12 @@
1
+ {
2
+ "sessions": [
3
+ {
4
+ "recording": [
5
+ [
6
+ "read",
7
+ "220 mx.google.com ESMTP x3si2474860qas.18 - gsmtp\r\n"
8
+ ]
9
+ ]
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,56 @@
1
+ {
2
+ "sessions": [
3
+ {
4
+ "recording": [
5
+ [
6
+ "read",
7
+ "220 mx.google.com ESMTP d8si2472149qai.124 - gsmtp\r\n"
8
+ ],
9
+ [
10
+ "write",
11
+ 16,
12
+ "EHLO localhost\r\n"
13
+ ],
14
+ [
15
+ "read",
16
+ "250-mx.google.com at your service, [54.227.243.167]\r\n250-SIZE 35882577\r\n250-8BITMIME\r\n250-STARTTLS\r\n250 ENHANCEDSTATUSCODES\r\n"
17
+ ],
18
+ [
19
+ "write",
20
+ 6,
21
+ "QUIT\r\n"
22
+ ],
23
+ [
24
+ "read",
25
+ "221 2.0.0 closing connection d8si2472149qai.124 - gsmtp\r\n"
26
+ ]
27
+ ]
28
+ },
29
+ {
30
+ "recording": [
31
+ [
32
+ "read",
33
+ "220 mta1579.mail.gq1.yahoo.com ESMTP YSmtpProxy service ready\r\n"
34
+ ],
35
+ [
36
+ "write",
37
+ 16,
38
+ "EHLO localhost\r\n"
39
+ ],
40
+ [
41
+ "read",
42
+ "250-mta1579.mail.gq1.yahoo.com\r\n250-8BITMIME\r\n250-SIZE 41943040\r\n250 PIPELINING\r\n"
43
+ ],
44
+ [
45
+ "write",
46
+ 6,
47
+ "QUIT\r\n"
48
+ ],
49
+ [
50
+ "read",
51
+ "221 mta1579.mail.gq1.yahoo.com\r\n"
52
+ ]
53
+ ]
54
+ }
55
+ ]
56
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "sessions": [
3
+ {
4
+ "recording": [
5
+ [
6
+ "read",
7
+ "220 mx.google.com ESMTP h5si2286277qec.54 - gsmtp\r\n"
8
+ ]
9
+ ]
10
+ },
11
+ {
12
+ "recording": [
13
+ [
14
+ "read",
15
+ "220 mta1009.mail.gq1.yahoo.com ESMTP YSmtpProxy service ready\r\n"
16
+ ]
17
+ ]
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,17 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
data/spec/tcr_spec.rb ADDED
@@ -0,0 +1,151 @@
1
+ require "spec_helper"
2
+ require "tcr"
3
+ require "net/protocol"
4
+ require "net/smtp"
5
+
6
+ describe TCR do
7
+ before(:each) do
8
+ TCR.configuration.reset_defaults!
9
+ end
10
+
11
+ describe ".configuration" do
12
+ it "has a default cassette location configured" do
13
+ TCR.configuration.cassette_library_dir.should == "fixtures/tcr_cassettes"
14
+ end
15
+
16
+ it "has an empty list of hook ports by default" do
17
+ TCR.configuration.hook_tcp_ports.should == []
18
+ end
19
+ end
20
+
21
+ describe ".configure" do
22
+ it "configures cassette location" do
23
+ expect {
24
+ TCR.configure { |c| c.cassette_library_dir = "some/dir" }
25
+ }.to change{ TCR.configuration.cassette_library_dir }.from("fixtures/tcr_cassettes").to("some/dir")
26
+ end
27
+
28
+ it "configures tcp ports to hook" do
29
+ expect {
30
+ TCR.configure { |c| c.hook_tcp_ports = [25] }
31
+ }.to change{ TCR.configuration.hook_tcp_ports }.from([]).to([25])
32
+ end
33
+ end
34
+
35
+ describe ".turned_off" do
36
+ it "requires a block to call" do
37
+ expect {
38
+ TCR.turned_off
39
+ }.to raise_error(ArgumentError)
40
+ end
41
+
42
+ it "makes real TCPSocket.open calls even when hooks are setup" do
43
+ TCR.configure { |c| c.hook_tcp_ports = [25] }
44
+ TCR.turned_off do
45
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
46
+ expect(tcp_socket).not_to respond_to(:cassette)
47
+ end
48
+ end
49
+ end
50
+
51
+ describe ".use_cassette" do
52
+ before(:each) {
53
+ TCR.configure { |c|
54
+ c.hook_tcp_ports = [25]
55
+ c.cassette_library_dir = "."
56
+ }
57
+ File.unlink("test.json") if File.exists?("test.json")
58
+ }
59
+ after(:each) {
60
+ File.unlink("test.json") if File.exists?("test.json")
61
+ }
62
+
63
+ it "requires a block to call" do
64
+ expect {
65
+ TCR.use_cassette("test")
66
+ }.to raise_error(ArgumentError)
67
+ end
68
+
69
+ it "resets the cassette after use" do
70
+ expect(TCR.cassette).to be_nil
71
+ TCR.use_cassette("test") { }
72
+ expect(TCR.cassette).to be_nil
73
+ end
74
+
75
+ it "creates a cassette file on use" do
76
+ expect {
77
+ TCR.use_cassette("test") do
78
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
79
+ tcp_socket.close
80
+ end
81
+ }.to change{ File.exists?("./test.json") }.from(false).to(true)
82
+ end
83
+
84
+ it "records the tcp session data into the file" do
85
+ TCR.use_cassette("test") do
86
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
87
+ io = Net::InternetMessageIO.new(tcp_socket)
88
+ line = io.readline
89
+ tcp_socket.close
90
+ end
91
+ cassette_contents = File.open("test.json") { |f| f.read }
92
+ cassette_contents.include?("220 mx.google.com ESMTP").should == true
93
+ end
94
+
95
+ it "plays back tcp sessions without opening a real connection" do
96
+ TCR.use_cassette("spec/fixtures/google_smtp") do
97
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
98
+ expect(tcp_socket).to respond_to(:cassette)
99
+ io = Net::InternetMessageIO.new(tcp_socket)
100
+ line = io.readline.should include("220 mx.google.com ESMTP")
101
+ end
102
+ end
103
+
104
+ it "raises an error if the recording gets out of order (i.e., we went to write but it expected a read)" do
105
+ expect {
106
+ TCR.use_cassette("spec/fixtures/google_smtp") do
107
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
108
+ io = Net::InternetMessageIO.new(tcp_socket)
109
+ io.write("hi")
110
+ end
111
+ }.to raise_error(TCR::CommandMismatchError)
112
+ end
113
+
114
+
115
+ context "multiple connections" do
116
+ it "records multiple sessions per cassette" do
117
+ TCR.use_cassette("test") do
118
+ smtp = Net::SMTP.start("aspmx.l.google.com", 25)
119
+ smtp.finish
120
+ smtp = Net::SMTP.start("mta6.am0.yahoodns.net", 25)
121
+ smtp.finish
122
+ end
123
+ cassette_contents = File.open("test.json") { |f| f.read }
124
+ cassette_contents.include?("google.com ESMTP").should == true
125
+ cassette_contents.include?("yahoo.com ESMTP").should == true
126
+ end
127
+
128
+ it "plays back multiple sessions per cassette in order" do
129
+ TCR.use_cassette("spec/fixtures/multitest") do
130
+ tcp_socket = TCPSocket.open("aspmx.l.google.com", 25)
131
+ io = Net::InternetMessageIO.new(tcp_socket)
132
+ line = io.readline.should include("google.com ESMTP")
133
+
134
+ tcp_socket = TCPSocket.open("mta6.am0.yahoodns.net", 25)
135
+ io = Net::InternetMessageIO.new(tcp_socket)
136
+ line = io.readline.should include("yahoo.com ESMTP")
137
+ end
138
+ end
139
+
140
+ it "raises an error if you try to playback more sessions than you previously recorded" do
141
+ expect {
142
+ TCR.use_cassette("spec/fixtures/multitest-smtp") do
143
+ smtp = Net::SMTP.start("aspmx.l.google.com", 25)
144
+ smtp = Net::SMTP.start("mta6.am0.yahoodns.net", 25)
145
+ smtp = Net::SMTP.start("mta6.am0.yahoodns.net", 25)
146
+ end
147
+ }.to raise_error(TCR::NoMoreSessionsError)
148
+ end
149
+ end
150
+ end
151
+ end
data/tcr.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tcr/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "shopify-tcr"
8
+ gem.version = TCR::VERSION
9
+ gem.authors = ["Luke Hutscal"]
10
+ gem.email = 'luke.hutscal@shopify.com'
11
+ gem.description = %q{TCR is a lightweight VCR for TCP sockets.}
12
+ gem.summary = %q{TCR is a lightweight VCR for TCP sockets.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency "rspec"
21
+ gem.add_development_dependency "geminabox"
22
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shopify-tcr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5.pre.shopify
5
+ platform: ruby
6
+ authors:
7
+ - Luke Hutscal
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: geminabox
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: TCR is a lightweight VCR for TCP sockets.
42
+ email: luke.hutscal@shopify.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - ".gitignore"
48
+ - ".rvmrc"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - lib/tcr.rb
54
+ - lib/tcr/cassette.rb
55
+ - lib/tcr/configuration.rb
56
+ - lib/tcr/errors.rb
57
+ - lib/tcr/recordable.rb
58
+ - lib/tcr/socket_extension.rb
59
+ - lib/tcr/ssl_socket_extension.rb
60
+ - lib/tcr/version.rb
61
+ - spec/fixtures/google_smtp.json
62
+ - spec/fixtures/multitest-smtp.json
63
+ - spec/fixtures/multitest.json
64
+ - spec/spec_helper.rb
65
+ - spec/tcr_spec.rb
66
+ - tcr.gemspec
67
+ homepage: ''
68
+ licenses: []
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">"
82
+ - !ruby/object:Gem::Version
83
+ version: 1.3.1
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.2.2
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: TCR is a lightweight VCR for TCP sockets.
90
+ test_files:
91
+ - spec/fixtures/google_smtp.json
92
+ - spec/fixtures/multitest-smtp.json
93
+ - spec/fixtures/multitest.json
94
+ - spec/spec_helper.rb
95
+ - spec/tcr_spec.rb