vanilli-ruby 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rubocop.yml +8 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +25 -0
- data/README.md +63 -0
- data/Rakefile +9 -0
- data/bin/console +8 -0
- data/bin/setup +7 -0
- data/lib/vanilli/client.rb +180 -0
- data/lib/vanilli/server.rb +45 -0
- data/vanilli-ruby.gemspec +31 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f6e60458d2a143b7ab40102bb484447123451bc4
|
4
|
+
data.tar.gz: a3cee75a0c3765f16505c2456c50b42f5d87c1d3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6e8b5484f7db8964cf147da31b57c0240fafbc63eba528351c91c8b33335be45651a1392ed1272aed7f550a420a129c4c32a911ce34d1e47bf7178e97c910c5
|
7
|
+
data.tar.gz: db24cf62f4c37f3a924dbd4db64ca558b0a9c7c30eeb72da1281d20e2e0bd5dd1aafb1a07051cff8147a8b2023eecb89d4b82b6b65b2eaf6ba4ad713d1e320b8
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2013-2015, MixRadio
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
11
|
+
documentation and/or other materials provided with the distribution.
|
12
|
+
3. Neither the name of Alistair Dutton nor the names of its contributors
|
13
|
+
may be used to endorse or promote products derived from this software
|
14
|
+
without specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY ALISTAIR DUTTON ''AS IS'' AND ANY
|
17
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
19
|
+
DISCLAIMED. IN NO EVENT SHALL ALISTAIR DUTTON BE LIABLE FOR ANY
|
20
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
21
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
22
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
23
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
24
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# vanilli-ruby
|
2
|
+
Ruby bindings for use with [vanilli](https://github.com/mixradio/vanilli).
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'vanilli-ruby'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install vanilli-ruby
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
Two classes are provided `VanilliServer` and `VanilliClient`.
|
22
|
+
|
23
|
+
### VanilliClient
|
24
|
+
This class provides a client API for interacting with a running vanilli server. The API has
|
25
|
+
deliberately been kept as close as possible to the canonical javascript API with a few "rubifications"
|
26
|
+
(snake case on method names for example). However, the API is close enough that providing extra
|
27
|
+
documentation here is counter-productive - please see the [javascript documentation](https://github.com/mixradio/vanilli/wiki/API).
|
28
|
+
|
29
|
+
Instantiating the client is straightforward:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require 'vanilli/client'
|
33
|
+
|
34
|
+
vanilli = VanilliClient.new
|
35
|
+
|
36
|
+
vanilli.stub(...)
|
37
|
+
#etc.
|
38
|
+
```
|
39
|
+
|
40
|
+
### VanilliServer
|
41
|
+
Of course, to be able to make use of the client one needs a vanilli server running to connect to. This
|
42
|
+
can be achieved in a number of ways:
|
43
|
+
|
44
|
+
* Start vanilli via its CLI
|
45
|
+
```sh
|
46
|
+
npm install -g vanilli
|
47
|
+
vanilli --port 9000
|
48
|
+
```
|
49
|
+
|
50
|
+
* Start vanilli from javascript
|
51
|
+
i.e. use the javascript API perhaps from some grunt/gulp/npm based task.
|
52
|
+
|
53
|
+
* Use VanilliServer provided with this ruby gem
|
54
|
+
This just acts as a wrapper around the vanilli CLI. Therefore you *MUST* have vanilli installed to your
|
55
|
+
path for this to work. Once installed, start something like this:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
vanilli_server = VanilliServer.new(port: 9000,
|
59
|
+
log_level: "debug",
|
60
|
+
static_root: "/your/web/app/assets",
|
61
|
+
static_include: ['**/*.html', '**/*.js', '**/*.css*', '/robots.txt'])
|
62
|
+
.start
|
63
|
+
```
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
private def unwrap_regex(thing)
|
5
|
+
if thing.is_a?(Regexp)
|
6
|
+
return { regex: thing.source }
|
7
|
+
else
|
8
|
+
return thing
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private def fail_body_with_no_contenttype(body, content_type)
|
13
|
+
fail 'Body was specified for but content-type was missing.' if body && !content_type
|
14
|
+
end
|
15
|
+
|
16
|
+
private def map_over_hash(h, f)
|
17
|
+
if h.nil?
|
18
|
+
return nil
|
19
|
+
else
|
20
|
+
return h.map { |key, value| { key => send(f, value) } }.reduce(:merge)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private def strip_nils(h)
|
25
|
+
h.delete_if { |_k, v| v.nil? }
|
26
|
+
end
|
27
|
+
|
28
|
+
private def stringify_non_json_content(content_blob)
|
29
|
+
body = content_blob[:body]
|
30
|
+
|
31
|
+
if (body.is_a? Hash) && (content_blob[:contentType] != 'application/json')
|
32
|
+
return content_blob.merge(body: body.to_json)
|
33
|
+
else
|
34
|
+
return content_blob
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Provides ruby bindings for the vanilli client. API is a
|
39
|
+
# "rubified" (i.e. snake-case for camel-case) version of the
|
40
|
+
# default javascript API provided with vanilli.
|
41
|
+
class VanilliClient
|
42
|
+
# Represents a single stub as will be registered with
|
43
|
+
# the vanilli server.
|
44
|
+
class Stub
|
45
|
+
attr_writer :expect
|
46
|
+
|
47
|
+
def initialize(criteria:, priority:)
|
48
|
+
@criteria = criteria
|
49
|
+
@priority = priority
|
50
|
+
end
|
51
|
+
|
52
|
+
# Construct the response for the stub
|
53
|
+
def respond_with(status, body: nil, content_type: nil, headers: nil, times: 1)
|
54
|
+
fail 'Status code is missing.' if status.nil?
|
55
|
+
fail_body_with_no_contenttype(body, content_type)
|
56
|
+
|
57
|
+
@response = stringify_non_json_content(strip_nils(status: status,
|
58
|
+
contentType: content_type,
|
59
|
+
body: body,
|
60
|
+
headers: headers))
|
61
|
+
@times = times
|
62
|
+
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# Vanilli will wait the specified number of milliseconds
|
67
|
+
# before responding with the stub response.
|
68
|
+
def wait(milliseconds:)
|
69
|
+
@response[:wait] = milliseconds
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
# The body of the matching request(s) will be logged by vanilli
|
74
|
+
# under the specified capture id.
|
75
|
+
def capture(capture_id)
|
76
|
+
@capture_id = capture_id
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
# Converts the stub to JSON for sending to vanilli.
|
81
|
+
def to_json
|
82
|
+
strip_nils(criteria: strip_nils(@criteria),
|
83
|
+
priority: @priority,
|
84
|
+
response: strip_nils(@response),
|
85
|
+
times: @times,
|
86
|
+
captureId: @capture_id,
|
87
|
+
expect: @expect).to_json
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Create a new Stub that will be matched
|
92
|
+
# against the specified criteria.
|
93
|
+
def on_request(method, url, content_type: nil, body: nil, query: nil, headers: nil, priority: nil)
|
94
|
+
fail 'Url is missing.' unless url
|
95
|
+
fail_body_with_no_contenttype(body, content_type)
|
96
|
+
|
97
|
+
Stub.new(criteria: stringify_non_json_content(method: method,
|
98
|
+
url: unwrap_regex(url),
|
99
|
+
contentType: content_type,
|
100
|
+
body: body,
|
101
|
+
query: map_over_hash(query, :unwrap_regex),
|
102
|
+
headers: map_over_hash(headers, :unwrap_regex)),
|
103
|
+
priority: priority)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Creates a Stub for a GET request that will be
|
107
|
+
# matched against the specified criteria.
|
108
|
+
def on_get(url, query: nil, headers: nil, priority: nil)
|
109
|
+
on_request('GET', url, query: query, headers: headers, priority: priority)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Creates a Stub for a POST request that will be
|
113
|
+
# matched against the specified criteria.
|
114
|
+
def on_post(url, query: nil, headers: nil, priority: nil, content_type: nil, body: nil)
|
115
|
+
on_request('POST', url, query: query, headers: headers, priority: priority, content_type: content_type, body: body)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Creates a Stub for a PUT request that will be
|
119
|
+
# matched against the specified criteria.
|
120
|
+
def on_put(url, query: nil, headers: nil, priority: nil, content_type: nil, body: nil)
|
121
|
+
on_request('PUT', url, query: query, headers: headers, priority: priority, content_type: content_type, body: body)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Creates a Stub for a DELETE request that will be
|
125
|
+
# matched against the specified criteria.
|
126
|
+
def on_delete(url, query: nil, headers: nil, priority: nil)
|
127
|
+
on_request('DELETE', url, query: query, headers: headers, priority: priority)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Registers the specified Stub(s) with the vanilli server.
|
131
|
+
def stub(*stubs)
|
132
|
+
stubs.each do |stub|
|
133
|
+
begin
|
134
|
+
RestClient.post 'http://localhost:9000/_vanilli/stubs', stub.to_json, content_type: :json, accept: :json
|
135
|
+
rescue => e
|
136
|
+
raise e.response
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Registers the specified Stub as an expectation on the
|
142
|
+
# vanilli server.
|
143
|
+
def expect(expectation)
|
144
|
+
expectation.expect = true
|
145
|
+
stub(expectation)
|
146
|
+
end
|
147
|
+
|
148
|
+
# Clears the vanilli server of all stubs.
|
149
|
+
def clear
|
150
|
+
RestClient.delete 'http://localhost:9000/_vanilli/stubs'
|
151
|
+
rescue => e
|
152
|
+
raise e.response
|
153
|
+
end
|
154
|
+
|
155
|
+
# Verifies that all vanilli expectations have been met. If
|
156
|
+
# not, an error is thrown.
|
157
|
+
def verify
|
158
|
+
begin
|
159
|
+
res = JSON.parse(RestClient.get 'http://localhost:9000/_vanilli/verify')
|
160
|
+
rescue => e
|
161
|
+
raise e.response
|
162
|
+
end
|
163
|
+
|
164
|
+
fail 'VERIFICATION FAILED: ' + res['errors'].join('\n') if res['errors'].length > 0
|
165
|
+
end
|
166
|
+
|
167
|
+
# Pulls back details of all requests that were logged against the
|
168
|
+
# specified capture id.
|
169
|
+
def get_captures(capture_id)
|
170
|
+
JSON.parse(RestClient.get 'http://localhost:9000/_vanilli/captures/' + capture_id)
|
171
|
+
rescue => e
|
172
|
+
raise e.response
|
173
|
+
end
|
174
|
+
|
175
|
+
# Pulls back details of the last request that was logged against the
|
176
|
+
# specified capture id.
|
177
|
+
def get_capture(capture_id)
|
178
|
+
get_captures(capture_id).last
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
|
3
|
+
# Provides hooks for starting and stopping a vanilli server. Relies on the vanilli CLI
|
4
|
+
# API and therefore requires vanilli to be installed.
|
5
|
+
class VanilliServer
|
6
|
+
def initialize(port:, static_root: nil, static_include: [], static_exclude: [], static_default: 'index.html', log_level: 'warn')
|
7
|
+
@static_root = static_root
|
8
|
+
@static_default = static_default
|
9
|
+
@static_include = static_include.join(',')
|
10
|
+
@static_exclude = static_exclude.join(',')
|
11
|
+
@port = port
|
12
|
+
@log_level = log_level
|
13
|
+
end
|
14
|
+
|
15
|
+
# Shells out to start vanilli
|
16
|
+
def start(cwd: '.')
|
17
|
+
@pid = spawn("vanilli --port #{@port} \
|
18
|
+
--logLevel=#{@log_level} \
|
19
|
+
--staticRoot=#{@static_root} \
|
20
|
+
--staticDefault=#{@static_default} \
|
21
|
+
--staticInclude=#{@static_include} \
|
22
|
+
--staticExclude=#{@static_exclude}", chdir: cwd)
|
23
|
+
|
24
|
+
Timeout.timeout(3) do
|
25
|
+
begin
|
26
|
+
RestClient.get "http://localhost:#{@port}/_vanilli/ping"
|
27
|
+
rescue
|
28
|
+
sleep 0.1
|
29
|
+
retry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
# Stops the vanilli server by killing the
|
37
|
+
# process started when shelling out to start vanilli
|
38
|
+
def stop
|
39
|
+
if @pid
|
40
|
+
Process.kill('KILL', @pid)
|
41
|
+
Process.wait @pid
|
42
|
+
end
|
43
|
+
@pid = nil
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "vanilli-ruby"
|
7
|
+
spec.version = "0.0.1"
|
8
|
+
spec.authors = ["Alistair Dutton"]
|
9
|
+
spec.email = ["kelveden@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Ruby bindings for vanilli"
|
12
|
+
spec.description = "Provides a ruby API for starting a vanilli server and interacting with it."
|
13
|
+
spec.homepage = "https://github.com/mixradio/vanilli-ruby"
|
14
|
+
spec.license = "BSD-3-Clause"
|
15
|
+
|
16
|
+
if spec.respond_to?(:metadata)
|
17
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
18
|
+
else
|
19
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
20
|
+
end
|
21
|
+
|
22
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.4"
|
29
|
+
spec.add_development_dependency "rubocop", "~> 0.31"
|
30
|
+
spec.add_runtime_dependency "rest-client", "~> 1.8"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vanilli-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alistair Dutton
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.9'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.31'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.31'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rest-client
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.8'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.8'
|
69
|
+
description: Provides a ruby API for starting a vanilli server and interacting with
|
70
|
+
it.
|
71
|
+
email:
|
72
|
+
- kelveden@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- ".rubocop.yml"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- bin/console
|
84
|
+
- bin/setup
|
85
|
+
- lib/vanilli/client.rb
|
86
|
+
- lib/vanilli/server.rb
|
87
|
+
- vanilli-ruby.gemspec
|
88
|
+
homepage: https://github.com/mixradio/vanilli-ruby
|
89
|
+
licenses:
|
90
|
+
- BSD-3-Clause
|
91
|
+
metadata:
|
92
|
+
allowed_push_host: https://rubygems.org
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.4.6
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Ruby bindings for vanilli
|
113
|
+
test_files: []
|