simple-websocket-vcr 0.0.1

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: db5656145b23681ce7430ff7033e3bbb40f2a56b
4
+ data.tar.gz: abd01476ee358c3a897f44d99afeee61e3bf2856
5
+ SHA512:
6
+ metadata.gz: 56a331b9c80dbed37bbda8f3598886f8ac325868c6a845cd721640fea1992e002f0d4097a16c63a67b35ac92bf8cd2c815f26f0adf4c2912236ea88fc2f04a55
7
+ data.tar.gz: 8824ae144e9cfcb09628fcb58d94be3f88bdcf5c95d32c8e178beb1a79a5204ac5387c8b245052ba5c9fb97315bdce8e02fcc8379309714c89bd580343854adb
data/.gitignore ADDED
@@ -0,0 +1,50 @@
1
+ ## Environment normalisation:
2
+ /.bundle/
3
+ /vendor/bundle
4
+ /lib/bundler/man/
5
+
6
+ # for a library or gem, you might want to ignore these files since the code is
7
+ # intended to run in multiple environments; otherwise, check them in:
8
+ Gemfile.lock
9
+ # .ruby-version
10
+ # .ruby-gemset
11
+
12
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
13
+ .rvmrc
14
+
15
+ # test config
16
+ spec/endpoint.yml
17
+
18
+ # IDE files
19
+ .project
20
+ .classpath
21
+ .settings
22
+ .idea
23
+ *.ipr
24
+ *.iml
25
+ *.iws
26
+ nb-configuration.xml
27
+
28
+ # KDE
29
+ .directory
30
+
31
+ # OSX
32
+ .DS_Store
33
+
34
+ # Ruby
35
+ *.gem
36
+ *.rbc
37
+ .bundle
38
+ .yardoc
39
+ Gemfile.lock
40
+ InstalledFiles
41
+ _yardoc
42
+ coverage
43
+ doc/
44
+ pkg
45
+ rdoc
46
+ spec/reports
47
+ test/tmp
48
+ test/version_tmp
49
+ *.gem
50
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --color
3
+ --order random
data/.rubocop.yml ADDED
@@ -0,0 +1,26 @@
1
+ # possible values:
2
+ # https://github.com/bbatsov/rubocop/blob/master/config/
3
+
4
+ #
5
+ # Overrides
6
+ #
7
+ CyclomaticComplexity:
8
+ Severity: refactor
9
+ Metrics/LineLength:
10
+ Max: 120
11
+
12
+ #
13
+ # Enabled/Disabled
14
+ #
15
+ ClassLength:
16
+ Enabled: false
17
+ Documentation:
18
+ Enabled: false
19
+ MethodLength:
20
+ Enabled: false
21
+ Metrics/AbcSize:
22
+ Enabled: false
23
+ ModuleLength:
24
+ Enabled: false
25
+ Style/ClassAndModuleChildren:
26
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
5
+ - 2.2
6
+ - 2.3
data/CHANGES.md ADDED
@@ -0,0 +1,8 @@
1
+ ## Changes
2
+
3
+ This document describes the relevant changes between releases of the
4
+ _simple-websocket-vcr_ project.
5
+
6
+ ### V 0.0.1
7
+
8
+ * First release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in simple-websocket-vcr.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,202 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright {yyyy} {name of copyright owner}
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # Simple websocket VCR
2
+
3
+ [![Build Status](https://travis-ci.org/Jiri-Kremser/simple-websocket-vcr.png?branch=master)](https://travis-ci.org/Jiri-Kremser/simple-websocket-vcr)
4
+
5
+ TODO: this
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/vcr.rb ADDED
@@ -0,0 +1,99 @@
1
+ require 'vcr/cassette'
2
+ require 'vcr/configuration'
3
+ require 'vcr/errors'
4
+ require 'vcr/recordable_websocket_client'
5
+ require 'vcr/version'
6
+ require 'json'
7
+ require 'websocket-client-simple'
8
+
9
+ module VCR
10
+ module WebSocket
11
+ def configure
12
+ yield configuration
13
+ end
14
+
15
+ def configuration
16
+ @configuration ||= Configuration.new
17
+ end
18
+
19
+ def cassette
20
+ @cassette
21
+ end
22
+
23
+ def cassette=(v)
24
+ @cassette = v
25
+ end
26
+
27
+ def disabled
28
+ @disabled || false
29
+ end
30
+
31
+ def disabled=(v)
32
+ @disabled = v
33
+ end
34
+
35
+ def save_session
36
+ end
37
+
38
+ def use_cassette(name, _options = {})
39
+ raise ArgumentError, '`VCR.use_cassette` requires a block.' unless block_given?
40
+ self.cassette = Cassette.new(name)
41
+ yield
42
+ cassette.save
43
+ self.cassette = nil
44
+ end
45
+
46
+ def record(example, context, options = {}, &block)
47
+ raise ArgumentError, '`VCR.record` requires a block.' unless block_given?
48
+ name = filename_helper(example, context)
49
+ use_cassette(name, options, &block)
50
+ end
51
+
52
+ def turn_off!(options = {})
53
+ # TODO: impl
54
+ end
55
+
56
+ def turned_on?
57
+ # TODO: impl
58
+ end
59
+
60
+ def turn_on!
61
+ # TODO: impl
62
+ end
63
+
64
+ private
65
+
66
+ def filename_helper(example, context)
67
+ if context.class.metadata[:parent_example_group].nil?
68
+ example_name = example.description.gsub(/\s+/, '_')
69
+ directory = context.class.metadata[:description].gsub(/\s+/, '_')
70
+ else
71
+ example_name = "#{context.class.metadata[:description]}_#{example.description}".gsub(/\s+/, '_')
72
+ directory = context.class.metadata[:parent_example_group][:description].gsub(/\s+/, '_')
73
+ end
74
+ "#{directory}/#{example_name}.json"
75
+ end
76
+
77
+ module_function :configure, :configuration, :cassette, :cassette=, :disabled, :disabled=, :save_session,
78
+ :use_cassette, :record, :turn_off!, :turned_on?, :turn_on!, :filename_helper
79
+ end
80
+ end
81
+
82
+ module WebSocket::Client::Simple
83
+ class << self
84
+ alias real_connect connect
85
+
86
+ def connect(url, options = {})
87
+ if VCR::WebSocket.configuration.hook_uris.any? { |u| url.include?(u) }
88
+ cassette = VCR::WebSocket.cassette
89
+ live = cassette.recording?
90
+ real_client = real_connect(url, options) if live
91
+ fake_client = VCR::WebSocket::RecordableWebsocketClient.new(cassette, live ? real_client : nil)
92
+ yield fake_client if block_given?
93
+ fake_client
94
+ else
95
+ real_connect(url, options)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,51 @@
1
+ require 'vcr/errors'
2
+ require 'fileutils'
3
+
4
+ module VCR
5
+ module WebSocket
6
+ include Errors
7
+
8
+ class Cassette
9
+ attr_reader :name, :recording
10
+
11
+ alias recording? recording
12
+
13
+ def initialize(name)
14
+ @name = name
15
+
16
+ if File.exist?(filename)
17
+ @recording = false
18
+ @contents = File.open(filename, &:read)
19
+ @sessions = JSON.parse(@contents)
20
+ else
21
+ @recording = true
22
+ @sessions = []
23
+ end
24
+ end
25
+
26
+ def next_session
27
+ if recording?
28
+ @sessions << []
29
+ @sessions.last
30
+ else
31
+ raise NoMoreSessionsError if @sessions.empty?
32
+ @sessions.shift
33
+ end
34
+ end
35
+
36
+ def save
37
+ if recording?
38
+ dirname = File.dirname(filename)
39
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
40
+ File.open(filename, 'w') { |f| f.write(JSON.pretty_generate(@sessions)) }
41
+ end
42
+ end
43
+
44
+ protected
45
+
46
+ def filename
47
+ "#{VCR::WebSocket.configuration.cassette_library_dir}/#{name}"
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,16 @@
1
+ module VCR
2
+ module WebSocket
3
+ class Configuration
4
+ attr_accessor :cassette_library_dir, :hook_uris
5
+
6
+ def initialize
7
+ reset_defaults!
8
+ end
9
+
10
+ def reset_defaults!
11
+ @cassette_library_dir = 'spec/fixtures/vcr_cassettes'
12
+ @hook_uris = []
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/vcr/errors.rb ADDED
@@ -0,0 +1,11 @@
1
+ module VCR
2
+ module WebSocket
3
+ module Errors
4
+ class VCRError < StandardError; end
5
+ class OperationMismatchError < VCRError; end
6
+ class DataMismatchError < VCRError; end
7
+ class NoCassetteError < VCRError; end
8
+ class NoMoreSessionsError < VCRError; end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,112 @@
1
+ require 'delegate'
2
+ require 'websocket-client-simple'
3
+ require 'base64'
4
+ require 'vcr/errors'
5
+
6
+ module VCR
7
+ module WebSocket
8
+ include Errors
9
+
10
+ class RecordableWebsocketClient
11
+ include EventEmitter
12
+
13
+ attr_reader :live, :client
14
+ attr_accessor :recording, :open
15
+
16
+ def initialize(cassette, real_client)
17
+ raise NoCassetteError 'specify the cassette' unless cassette
18
+
19
+ if cassette.recording?
20
+ @live = true
21
+ @client = real_client
22
+ else
23
+ @live = false
24
+ @open = true
25
+ end
26
+ @recording = cassette.next_session
27
+ end
28
+
29
+ def send(data_param, opt = { type: :text })
30
+ data = data_param.dup
31
+ data = Base64.encode64(data) if opt[:type] != :text
32
+ _write(:send, data, opt)
33
+ end
34
+
35
+ # or on
36
+ def on(event, params = {}, &block)
37
+ _read(:add_listener, event, params, &block)
38
+ end
39
+
40
+ def emit(event, *data)
41
+ @recording << { operation: 'read', data: data } if live
42
+ super(event, *data)
43
+ end
44
+
45
+ def open?
46
+ if live
47
+ @client.open?
48
+ else
49
+ @open
50
+ end
51
+ end
52
+
53
+ def close
54
+ if live
55
+ @recording << { operation: 'close' }
56
+ @client.close
57
+ else
58
+ record = @recording.shift
59
+ _ensure_operation('close', record['operation'])
60
+ @open = false
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def _write(method, data, opt)
67
+ if live
68
+ @client.__send__(method, data, opt)
69
+ @recording << { operation: 'write', data: data }
70
+ else
71
+ record = @recording.shift
72
+ _ensure_operation('write', record['operation'])
73
+ _ensure_data(data, record['data'])
74
+ end
75
+ end
76
+
77
+ def _read(method, event, params, &block)
78
+ if live
79
+ rec = @recording
80
+ @client.on(event, params) do |msg|
81
+ msg = Base64.decode64(msg) if msg.type != :text
82
+ rec << { operation: 'read', type: msg.type, data: msg }
83
+ yield(msg)
84
+ end
85
+ @client.__send__(method, event, params, &block)
86
+ else
87
+ raise EOFError if @recording.empty?
88
+ record = _take_first_read
89
+ return if record.nil?
90
+ _ensure_operation('read', record['operation'])
91
+ data = record['data']
92
+ data = Base64.decode64(msg) if record['type'] != 'text'
93
+ emit(event, data)
94
+ end
95
+ end
96
+
97
+ def _take_first_read
98
+ @recording.delete_at(@recording.index { |record| record['operation'] == 'read' } || @recording.length)
99
+ end
100
+
101
+ def _ensure_operation(desired, actual)
102
+ string = "Expected to '#{desired}' but next in recording was '#{actual}'"
103
+ raise OperationMismatchError string unless desired == actual
104
+ end
105
+
106
+ def _ensure_data(desired, actual)
107
+ string = "Expected data to be '#{desired}' but next in recording was '#{actual}'"
108
+ raise DataMismatchError string unless desired == actual
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,5 @@
1
+ module VCR
2
+ module WebSocket
3
+ VERSION = '0.0.1'.freeze
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vcr/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'simple-websocket-vcr'
8
+ gem.version = VCR::WebSocket::VERSION
9
+ gem.authors = ['Jirka Kremser']
10
+ gem.email = ['jkremser@redhat.com']
11
+ gem.description = 'Websocket VCR add-on'
12
+ gem.summary = 'simple-websocket-vcr is VCR add-on for websockets.'
13
+ gem.homepage = 'https://github.com/Jiri-Kremser/simple-websocket-vcr'
14
+ gem.license = 'Apache-2.0'
15
+
16
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ['lib']
20
+
21
+ gem.add_development_dependency('rspec-rails', '~> 3.0')
22
+ gem.add_development_dependency('websocket-client-simple', '~> 0.3')
23
+ end
@@ -0,0 +1,30 @@
1
+ [
2
+ [
3
+ {
4
+ "operation": "read",
5
+ "type": "text",
6
+ "data": "WelcomeResponse={\"sessionId\":\"GmAOS1avTLE0453s0l3o8HkLUCmVMlRlIBHqK2cN\"}"
7
+ },
8
+ {
9
+ "operation": "write",
10
+ "data": "something_1"
11
+ },
12
+ {
13
+ "operation": "read",
14
+ "type": "text",
15
+ "data": "GenericErrorResponse={\"errorMessage\":\"Failed to process message [?]\",\"stackTrace\":\"java.lang.IllegalArgumentException: Cannot deserialize: [something_1]\\n\\tat org.hawkular.cmdgw.api.ApiDeserializer.fromHawkularFormat(ApiDeserializer.java:68)\\n\\tat org.hawkular.cmdgw.api.ApiDeserializer.deserialize(ApiDeserializer.java:84)\\n\\tat org.hawkular.cmdgw.command.ws.server.AbstractGatewayWebSocket.onMessage(AbstractGatewayWebSocket.java:213)\\n\\tat sun.reflect.GeneratedMethodAccessor544.invoke(Unknown Source)\\n\\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\\n\\tat java.lang.reflect.Method.invoke(Method.java:497)\\n\\tat io.undertow.websockets.jsr.annotated.BoundMethod.invoke(BoundMethod.java:87)\\n\\tat io.undertow.websockets.jsr.annotated.AnnotatedEndpoint$2$1.run(AnnotatedEndpoint.java:150)\\n\\tat io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:553)\\n\\tat io.undertow.websockets.jsr.annotated.AnnotatedEndpoint$2.onMessage(AnnotatedEndpoint.java:145)\\n\\tat io.undertow.websockets.jsr.FrameHandler$7.run(FrameHandler.java:283)\\n\\tat io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:553)\\n\\tat io.undertow.websockets.jsr.ServerWebSocketContainer$5.run(ServerWebSocketContainer.java:538)\\n\\tat io.undertow.websockets.jsr.OrderedExecutor$ExecutorTask.run(OrderedExecutor.java:67)\\n\\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\\n\\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\\n\\tat java.lang.Thread.run(Thread.java:745)\\n\"}"
16
+ },
17
+ {
18
+ "operation": "write",
19
+ "data": "something_2"
20
+ },
21
+ {
22
+ "operation": "read",
23
+ "type": "text",
24
+ "data": "GenericErrorResponse={\"errorMessage\":\"Failed to process message [?]\",\"stackTrace\":\"java.lang.IllegalArgumentException: Cannot deserialize: [something_2]\\n\\tat org.hawkular.cmdgw.api.ApiDeserializer.fromHawkularFormat(ApiDeserializer.java:68)\\n\\tat org.hawkular.cmdgw.api.ApiDeserializer.deserialize(ApiDeserializer.java:84)\\n\\tat org.hawkular.cmdgw.command.ws.server.AbstractGatewayWebSocket.onMessage(AbstractGatewayWebSocket.java:213)\\n\\tat sun.reflect.GeneratedMethodAccessor544.invoke(Unknown Source)\\n\\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\\n\\tat java.lang.reflect.Method.invoke(Method.java:497)\\n\\tat io.undertow.websockets.jsr.annotated.BoundMethod.invoke(BoundMethod.java:87)\\n\\tat io.undertow.websockets.jsr.annotated.AnnotatedEndpoint$2$1.run(AnnotatedEndpoint.java:150)\\n\\tat io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:553)\\n\\tat io.undertow.websockets.jsr.annotated.AnnotatedEndpoint$2.onMessage(AnnotatedEndpoint.java:145)\\n\\tat io.undertow.websockets.jsr.FrameHandler$7.run(FrameHandler.java:283)\\n\\tat io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:553)\\n\\tat io.undertow.websockets.jsr.ServerWebSocketContainer$5.run(ServerWebSocketContainer.java:538)\\n\\tat io.undertow.websockets.jsr.OrderedExecutor$ExecutorTask.run(OrderedExecutor.java:67)\\n\\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\\n\\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\\n\\tat java.lang.Thread.run(Thread.java:745)\\n\"}"
25
+ },
26
+ {
27
+ "operation": "close"
28
+ }
29
+ ]
30
+ ]
@@ -0,0 +1,21 @@
1
+ [
2
+ [
3
+ {
4
+ "operation": "read",
5
+ "type": "text",
6
+ "data": "WelcomeResponse={\"sessionId\":\"-gGp6ATYH0bEfiOtumWEnieSFNgRtHL3i0RAndui\"}"
7
+ },
8
+ {
9
+ "operation": "write",
10
+ "data": "something 1"
11
+ },
12
+ {
13
+ "operation": "write",
14
+ "data": "something 2"
15
+ },
16
+ {
17
+ "operation": "write",
18
+ "data": "something 3"
19
+ }
20
+ ]
21
+ ]
@@ -0,0 +1,12 @@
1
+ [
2
+ [
3
+ {
4
+ "operation": "read",
5
+ "type": "text",
6
+ "data": "WelcomeResponse={\"sessionId\":\"QDPovsVv6q8eZx4ARSa6tdU4PJDJH1Bo4j45u3SQ\"}"
7
+ },
8
+ {
9
+ "operation": "close"
10
+ }
11
+ ]
12
+ ]
@@ -0,0 +1,9 @@
1
+ [
2
+ [
3
+ {
4
+ "operation": "read",
5
+ "type": "text",
6
+ "data": "WelcomeResponse={\"sessionId\":\"_f8ZS9Q2r_Tn9BVdz5vGoJueZ-dl4pbv6erAM8am\"}"
7
+ }
8
+ ]
9
+ ]
@@ -0,0 +1,4 @@
1
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
2
+ RSpec.configure do |config|
3
+ config.order = 'random'
4
+ end
data/spec/vcr_spec.rb ADDED
@@ -0,0 +1,162 @@
1
+ require 'vcr'
2
+ require 'thread'
3
+ require 'websocket-client-simple'
4
+ require 'json'
5
+
6
+ describe 'VCR for WS' do
7
+ HOST = 'localhost:8080'.freeze
8
+
9
+ let(:example) do |e|
10
+ e
11
+ end
12
+
13
+ before(:each) do
14
+ VCR::WebSocket.configuration.reset_defaults!
15
+ end
16
+
17
+ it 'should record the very first message caught on the client yielded by the connect method' do
18
+ VCR::WebSocket.configure do |c|
19
+ c.hook_uris = [HOST]
20
+ end
21
+ VCR::WebSocket.record(example, self) do
22
+ url = "ws://#{HOST}/hawkular/command-gateway/ui/ws"
23
+ c = WebSocket::Client::Simple.connect url do |client|
24
+ client.on(:message, once: true, &:data)
25
+ end
26
+ sleep 1
27
+
28
+ expect(c).not_to be nil
29
+ expect(c.open?).to be true
30
+ end
31
+ end
32
+
33
+ it 'should record also the outgoing communication' do
34
+ VCR::WebSocket.configure do |c|
35
+ c.hook_uris = [HOST]
36
+ end
37
+ VCR::WebSocket.record(example, self) do
38
+ url = "ws://#{HOST}/hawkular/command-gateway/ui/ws"
39
+ c = WebSocket::Client::Simple.connect url do |client|
40
+ client.on(:message, once: true, &:data)
41
+ end
42
+ sleep 1
43
+ c.send('something 1')
44
+ c.send('something 2')
45
+ c.send('something 3')
46
+
47
+ expect(c).not_to be nil
48
+ expect(c.open?).to be true
49
+ end
50
+ end
51
+
52
+ it 'should record the closing event' do
53
+ VCR::WebSocket.configure do |c|
54
+ c.hook_uris = [HOST]
55
+ end
56
+ VCR::WebSocket.record(example, self) do
57
+ url = "ws://#{HOST}/hawkular/command-gateway/ui/ws"
58
+ c = WebSocket::Client::Simple.connect url do |client|
59
+ client.on(:message, once: true, &:data)
60
+ end
61
+ sleep 1
62
+
63
+ expect(c).not_to be nil
64
+ expect(c.open?).to be true
65
+ sleep 1
66
+ c.close
67
+ expect(c.open?).to be false
68
+ end
69
+ end
70
+
71
+ it 'should record complex communications' do
72
+ VCR::WebSocket.configure do |c|
73
+ c.hook_uris = [HOST]
74
+ end
75
+ cassette_path = '/EXPLICIT/some_explicitly_specified_cassette.json'
76
+ VCR::WebSocket.use_cassette(cassette_path) do
77
+ url = "ws://#{HOST}/hawkular/command-gateway/ui/ws"
78
+ c = WebSocket::Client::Simple.connect url do |client|
79
+ client.on(:message, once: true, &:data)
80
+ end
81
+ sleep 1
82
+ c.send('something_1')
83
+ c.on(:message, once: true, &:data)
84
+ sleep 1
85
+
86
+ c.send('something_2')
87
+ c.on(:message, once: true, &:data)
88
+ sleep 1
89
+
90
+ expect(c).not_to be nil
91
+ expect(c.open?).to be true
92
+ c.close
93
+ expect(c.open?).to be false
94
+ sleep 1
95
+ end
96
+
97
+ # check that everything was recorded in the json file
98
+ file_path = VCR::WebSocket.configuration.cassette_library_dir + cassette_path
99
+ expect(File.readlines(file_path).grep(/WelcomeResponse/).size).to eq(1)
100
+ # once in the client message and once in the GenericErrorResponse from the server
101
+ expect(File.readlines(file_path).grep(/something_1/).size).to eq(2)
102
+ expect(File.readlines(file_path).grep(/something_2/).size).to eq(2)
103
+ expect(File.readlines(file_path).grep(/close/).size).to eq(1)
104
+ end
105
+
106
+ context 'automatically picked cassette name is ok, when using context foo' do
107
+ it 'and example bar' do
108
+ VCR::WebSocket.record(example, self) do
109
+ # nothing
110
+ end
111
+ prefix = VCR::WebSocket.configuration.cassette_library_dir
112
+ name = 'automatically_picked_cassette_name_is_ok,_when_using_context_foo_and_example_bar.json'
113
+ expect(File.exist?(prefix + '/VCR_for_WS/' + name)).to be true
114
+ end
115
+ end
116
+
117
+ describe 'automatically picked cassette name is ok, when describing parent' do
118
+ it 'and example child1' do
119
+ VCR::WebSocket.record(example, self) do
120
+ # nothing
121
+ end
122
+ prefix = VCR::WebSocket.configuration.cassette_library_dir
123
+ name = 'automatically_picked_cassette_name_is_ok,_when_describing_parent_and_example_child1.json'
124
+ expect(File.exist?(prefix + '/VCR_for_WS/' + name)).to be true
125
+ end
126
+
127
+ it 'and example child2' do
128
+ VCR::WebSocket.record(example, self) do
129
+ # nothing
130
+ end
131
+ prefix = VCR::WebSocket.configuration.cassette_library_dir
132
+ name = 'automatically_picked_cassette_name_is_ok,_when_describing_parent_and_example_child2.json'
133
+ expect(File.exist?(prefix + '/VCR_for_WS/' + name)).to be true
134
+ end
135
+ end
136
+
137
+ describe '.configuration' do
138
+ it 'has a default cassette location configured' do
139
+ expect(VCR::WebSocket.configuration.cassette_library_dir).to eq('spec/fixtures/vcr_cassettes')
140
+ end
141
+
142
+ it 'has an empty list of hook ports by default' do
143
+ expect(VCR::WebSocket.configuration.hook_uris).to eq([])
144
+ end
145
+ end
146
+
147
+ describe '.configure' do
148
+ it 'configures cassette location' do
149
+ expect do
150
+ VCR::WebSocket.configure { |c| c.cassette_library_dir = 'foo/bar' }
151
+ end.to change { VCR::WebSocket.configuration.cassette_library_dir }
152
+ .from('spec/fixtures/vcr_cassettes')
153
+ .to('foo/bar')
154
+ end
155
+
156
+ it 'configures URIs to hook' do
157
+ expect do
158
+ VCR::WebSocket.configure { |c| c.hook_uris = ['127.0.0.1:1337'] }
159
+ end.to change { VCR::WebSocket.configuration.hook_uris }.from([]).to(['127.0.0.1:1337'])
160
+ end
161
+ end
162
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple-websocket-vcr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jirka Kremser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: websocket-client-simple
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.3'
41
+ description: Websocket VCR add-on
42
+ email:
43
+ - jkremser@redhat.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rspec"
50
+ - ".rubocop.yml"
51
+ - ".travis.yml"
52
+ - CHANGES.md
53
+ - Gemfile
54
+ - LICENSE.txt
55
+ - README.md
56
+ - Rakefile
57
+ - lib/vcr.rb
58
+ - lib/vcr/cassette.rb
59
+ - lib/vcr/configuration.rb
60
+ - lib/vcr/errors.rb
61
+ - lib/vcr/recordable_websocket_client.rb
62
+ - lib/vcr/version.rb
63
+ - simple-websocket-vcr.gemspec
64
+ - spec/fixtures/vcr_cassettes/EXPLICIT/some_explicitly_specified_cassette.json
65
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/automatically_picked_cassette_name_is_ok,_when_describing_parent_and_example_child1.json
66
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/automatically_picked_cassette_name_is_ok,_when_describing_parent_and_example_child2.json
67
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/automatically_picked_cassette_name_is_ok,_when_using_context_foo_and_example_bar.json
68
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/should_record_also_the_outgoing_communication.json
69
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/should_record_the_closing_event.json
70
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/should_record_the_very_first_message_caught_on_the_client_yielded_by_the_connect_method.json
71
+ - spec/spec_helper.rb
72
+ - spec/vcr_spec.rb
73
+ homepage: https://github.com/Jiri-Kremser/simple-websocket-vcr
74
+ licenses:
75
+ - Apache-2.0
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.6.2
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: simple-websocket-vcr is VCR add-on for websockets.
97
+ test_files:
98
+ - spec/fixtures/vcr_cassettes/EXPLICIT/some_explicitly_specified_cassette.json
99
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/automatically_picked_cassette_name_is_ok,_when_describing_parent_and_example_child1.json
100
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/automatically_picked_cassette_name_is_ok,_when_describing_parent_and_example_child2.json
101
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/automatically_picked_cassette_name_is_ok,_when_using_context_foo_and_example_bar.json
102
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/should_record_also_the_outgoing_communication.json
103
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/should_record_the_closing_event.json
104
+ - spec/fixtures/vcr_cassettes/VCR_for_WS/should_record_the_very_first_message_caught_on_the_client_yielded_by_the_connect_method.json
105
+ - spec/spec_helper.rb
106
+ - spec/vcr_spec.rb