appurify 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +54 -0
- data/lib/appurify.rb +10 -0
- data/lib/appurify/client.rb +145 -0
- data/lib/appurify/version.rb +3 -0
- data/spec/client/client_spec.rb +130 -0
- data/spec/spec_helper.rb +62 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b7d5bc4ad41dcb6b3ca21b0ac0e94f9a8b9bd03d
|
4
|
+
data.tar.gz: de2314d5b7d454c8fe341e27129bf785c4073d79
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 33b869fbd81c20d9a7fd3c67b9bf471d74d6446c7b6acb73d698e690f2cb74b95d2d341ad095262b02f4c453971bd5c8d09c3ff2a03814adf0d1e92d9f3d113a
|
7
|
+
data.tar.gz: b16cb51f7486e3e0a1f3a0e99618ec54e0ea9b34e1e590b16cdd88e0acafcb1d5fe09dfcb9e7afbb0fb5d03af0617f78e5cfc74698edac6342f6fdf273211d3b
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Appurify Gem
|
2
|
+
|
3
|
+
The official Ruby client for the [Appurify](http://www.appurify.com) API.
|
4
|
+
|
5
|
+
### Installation
|
6
|
+
|
7
|
+
```
|
8
|
+
gem install appurify
|
9
|
+
```
|
10
|
+
|
11
|
+
### Configuration
|
12
|
+
|
13
|
+
```
|
14
|
+
client = Appurify::Client.new(key, secret, options)
|
15
|
+
```
|
16
|
+
|
17
|
+
### Listing Device Types
|
18
|
+
|
19
|
+
```
|
20
|
+
device_types = client.device_types
|
21
|
+
device_type_id = client.device_types.first["device_type_id"]
|
22
|
+
```
|
23
|
+
|
24
|
+
### Uploading An Application
|
25
|
+
|
26
|
+
```
|
27
|
+
response = client.upload_app_from_url(app_url)
|
28
|
+
application_id = response["app_id"]
|
29
|
+
```
|
30
|
+
|
31
|
+
### Uploading A Test
|
32
|
+
|
33
|
+
```
|
34
|
+
test_type = "uiautomation"
|
35
|
+
response = client.upload_test_from_url(test_url, test_type)
|
36
|
+
test_id = response["test_id"]
|
37
|
+
```
|
38
|
+
|
39
|
+
### Starting A Test Run
|
40
|
+
|
41
|
+
```
|
42
|
+
response = client.run_test(device_type_id, application_id, test_id)
|
43
|
+
test_run_id = response["test_run_id"]
|
44
|
+
```
|
45
|
+
|
46
|
+
### Retrieve Test Run Results
|
47
|
+
|
48
|
+
```
|
49
|
+
response = client.monitor_test(test_run_id)
|
50
|
+
```
|
51
|
+
|
52
|
+
### Contribution
|
53
|
+
|
54
|
+
Found a bug or want to add a much needed feature? Go for it and just send us the Pull Request!
|
data/lib/appurify.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
module Appurify
|
2
|
+
class Client
|
3
|
+
attr_accessor :scheme, :host, :port, :key, :secret, :request_timeout, :open_timeout, :last_request
|
4
|
+
|
5
|
+
def initialize(key, secret, options={})
|
6
|
+
@key = key
|
7
|
+
@secret = secret
|
8
|
+
|
9
|
+
@scheme, @host, @port, @request_timeout, @open_timeout = {
|
10
|
+
scheme: "https",
|
11
|
+
host: HOSTNAME,
|
12
|
+
port: 443,
|
13
|
+
request_timeout: 600,
|
14
|
+
open_timeout: 10
|
15
|
+
}.merge(options).values
|
16
|
+
end
|
17
|
+
|
18
|
+
def access_token
|
19
|
+
unless access_token_active?
|
20
|
+
url = build_url("access_token", "generate")
|
21
|
+
data = {
|
22
|
+
:key => @key,
|
23
|
+
:secret => @secret
|
24
|
+
}
|
25
|
+
|
26
|
+
#result = post(url, data, false)
|
27
|
+
result = post(url, data)
|
28
|
+
@access_token = result["access_token"]
|
29
|
+
@access_token_ttl = result["ttl"]
|
30
|
+
@access_token_created = Time.now
|
31
|
+
end
|
32
|
+
|
33
|
+
@access_token
|
34
|
+
end
|
35
|
+
|
36
|
+
def device_types
|
37
|
+
url = build_url("devices", "list")
|
38
|
+
get(url)
|
39
|
+
end
|
40
|
+
|
41
|
+
def network_conditions
|
42
|
+
url = build_url("devices", "config/networks/list")
|
43
|
+
get(url)
|
44
|
+
end
|
45
|
+
|
46
|
+
def upload_app_from_url(app_url)
|
47
|
+
url = build_url("apps", "upload")
|
48
|
+
data = {
|
49
|
+
:access_token => access_token,
|
50
|
+
:source_type => "url",
|
51
|
+
:source => app_url
|
52
|
+
}
|
53
|
+
|
54
|
+
post(url, data)
|
55
|
+
end
|
56
|
+
|
57
|
+
def upload_test_from_url(test_url, test_type)
|
58
|
+
url = build_url("tests", "upload")
|
59
|
+
data = {
|
60
|
+
:access_token => access_token,
|
61
|
+
:source_type => "url",
|
62
|
+
:test_type => test_type,
|
63
|
+
:source => test_url
|
64
|
+
}
|
65
|
+
|
66
|
+
post(url, data)
|
67
|
+
end
|
68
|
+
|
69
|
+
def upload_device_conditions(test_id, conditions)
|
70
|
+
url = build_url("config", "upload")
|
71
|
+
file_data = "[appurify]\n" + conditions.keys.collect{ |k| k.to_s + "=" + conditions[k].to_s }.join("\n")
|
72
|
+
|
73
|
+
file = StringIO.new(file_data)
|
74
|
+
file.class.class_eval { attr_accessor :name }
|
75
|
+
file.class.class_eval { attr_accessor :path }
|
76
|
+
file.name = "config.cnf"
|
77
|
+
file.path = "config.cnf"
|
78
|
+
|
79
|
+
data = {
|
80
|
+
:access_token => access_token,
|
81
|
+
:test_id => test_id,
|
82
|
+
:source => file
|
83
|
+
}
|
84
|
+
|
85
|
+
post(url, data)
|
86
|
+
end
|
87
|
+
|
88
|
+
def run_test(device_type_id, app_id, test_id, async=1)
|
89
|
+
url = build_url("tests", "run")
|
90
|
+
data = {
|
91
|
+
:access_token => access_token,
|
92
|
+
:device_type_id => device_type_id,
|
93
|
+
:app_id => app_id,
|
94
|
+
:test_id => test_id,
|
95
|
+
:async => async
|
96
|
+
}
|
97
|
+
|
98
|
+
post(url, data)
|
99
|
+
end
|
100
|
+
|
101
|
+
def monitor_test(test_run_id)
|
102
|
+
url = build_url("tests", "check")
|
103
|
+
params = { test_run_id: test_run_id }
|
104
|
+
get(url, params)
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def access_token_active?
|
110
|
+
@access_token && Time.now < @access_token_created + @access_token_ttl
|
111
|
+
end
|
112
|
+
|
113
|
+
def build_url(type, resource)
|
114
|
+
@scheme + "://" + [@host, "resource", type, resource].join("/") + "/"
|
115
|
+
end
|
116
|
+
|
117
|
+
def get(url, params={})
|
118
|
+
@last_request = {
|
119
|
+
url: url,
|
120
|
+
request: params
|
121
|
+
}
|
122
|
+
|
123
|
+
query_string_params = params.collect{ |p| "&#{p[0].to_s}=#{p[1].to_s}" }.join
|
124
|
+
result = RestClient::Request.execute(:method => :get, :url => "#{url}?access_token=#{access_token}#{query_string_params}", :timeout => @request_timeout, :open_timeout => @open_timeout)
|
125
|
+
@last_request[:response] = result
|
126
|
+
|
127
|
+
JSON.parse(result)["response"]
|
128
|
+
end
|
129
|
+
|
130
|
+
def post(url, data, capture_request=true)
|
131
|
+
if capture_request
|
132
|
+
@last_request = {
|
133
|
+
url: url,
|
134
|
+
request: data
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
result = RestClient::Request.execute(:method => :post, :url => url, :payload => data, :timeout => @request_timeout, :open_timeout => @open_timeout)
|
139
|
+
@last_request[:response] = result if capture_request
|
140
|
+
|
141
|
+
JSON.parse(result)["response"]
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fake_web'
|
3
|
+
require 'timecop'
|
4
|
+
|
5
|
+
describe Appurify do
|
6
|
+
|
7
|
+
let (:key) { "7ks6hmigudkbx3uuipgmqllhcoqmxf5mq" }
|
8
|
+
let (:secret) { "270td4563wpj2auoct4yu4tqx5kv4kotp" }
|
9
|
+
|
10
|
+
before do
|
11
|
+
FakeWeb.allow_net_connect = false
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "When configuring an Appurify Client" do
|
15
|
+
|
16
|
+
it "should correctly configure the key and secret" do
|
17
|
+
client = Appurify::Client.new(key, secret)
|
18
|
+
client.key.should == key
|
19
|
+
client.secret.should == secret
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should correctly configure connection options" do
|
23
|
+
options = {
|
24
|
+
scheme: "http",
|
25
|
+
host: "staging.appurify.com",
|
26
|
+
port: 80,
|
27
|
+
request_timeout: 5,
|
28
|
+
open_timeout: 5
|
29
|
+
}
|
30
|
+
|
31
|
+
client = Appurify::Client.new(key, secret, options)
|
32
|
+
client.scheme.should == options[:scheme]
|
33
|
+
client.host.should == options[:host]
|
34
|
+
client.port.should == options[:port]
|
35
|
+
client.request_timeout.should == options[:request_timeout]
|
36
|
+
client.open_timeout.should == options[:open_timeout]
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "When using an Appurify Client" do
|
42
|
+
|
43
|
+
let (:client) { Appurify::Client.new(key, secret) }
|
44
|
+
let (:token) { "e8k3jd64gfrgbtqrunaipx9pl34xkao6c" }
|
45
|
+
let (:ttl) { 86400 }
|
46
|
+
let (:application_id) { "lvq2g2y6hn0sr36k9i9mrcochh49tbww3" }
|
47
|
+
let (:test_id) { "d9yovkaekgg29c3d2nr4guhfppe0jewra" }
|
48
|
+
let (:test_type) { "ocunit" }
|
49
|
+
let (:device_type) { 1 }
|
50
|
+
let (:device_id) { 10 }
|
51
|
+
let (:app_url) { "https://www.cisimple.com/builds/1/build_steps/1/artifacts/cisimple.app.zip" }
|
52
|
+
let (:test_url) { "https://www.cisimple.com/builds/1/build_steps/1/artifacts/cisimple.octest.zip" }
|
53
|
+
|
54
|
+
before do
|
55
|
+
mock_access_token_response(token, ttl)
|
56
|
+
mock_application_upload_response(application_id)
|
57
|
+
mock_test_upload_response(test_id, test_type)
|
58
|
+
mock_run_test_response
|
59
|
+
mock_monitor_test_response(token)
|
60
|
+
mock_upload_device_conditions_response
|
61
|
+
mock_device_types_response(token)
|
62
|
+
mock_network_conditions_response(token)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should successfully retrieve an access token" do
|
66
|
+
client.access_token.should == token
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should cache access tokens" do
|
70
|
+
client.access_token
|
71
|
+
FakeWeb.clean_registry
|
72
|
+
mock_access_token_response
|
73
|
+
client.access_token.should == token
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should retrieve a new access token when the current one has expired" do
|
77
|
+
client.access_token
|
78
|
+
FakeWeb.clean_registry
|
79
|
+
expected_token = "2hmiusynojjtgxsnd6eqdop1lreeua56i"
|
80
|
+
mock_access_token_response(expected_token)
|
81
|
+
Timecop.travel(Time.now + ttl + 1)
|
82
|
+
client.access_token.should == expected_token
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should successfully upload an application from a url" do
|
86
|
+
response = client.upload_app_from_url(app_url)
|
87
|
+
response["id"].should == application_id
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should successfully upload a test from a url" do
|
91
|
+
response = client.upload_test_from_url(test_url, test_type)
|
92
|
+
response["id"].should == test_id
|
93
|
+
response["test_type"].should == test_type
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should successfully start a test on a device" do
|
97
|
+
test_run_id = 5
|
98
|
+
mock_run_test_response(test_run_id)
|
99
|
+
response = client.run_test(device_id, application_id, test_id)
|
100
|
+
response["test_run_id"].should == test_run_id
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should successfully monitor a test run" do
|
104
|
+
test_run_id = 5
|
105
|
+
mock_monitor_test_response(token, test_run_id)
|
106
|
+
response = client.monitor_test(test_run_id)
|
107
|
+
response["status"].should == "complete"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should successfully retrieve the list of device types" do
|
111
|
+
response = client.device_types
|
112
|
+
response.count.should == 2
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should successfully retrieve the list of network conditions" do
|
116
|
+
client.network_conditions.count.should == 5
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should be able to execute a test end to end" do
|
120
|
+
device_type = client.device_types.first["id"]
|
121
|
+
app_id = client.upload_app_from_url(app_url)["id"]
|
122
|
+
test_id = client.upload_test_from_url(test_url, test_type)["id"]
|
123
|
+
client.upload_device_conditions(test_id, {:memory => 300, :network => 5})
|
124
|
+
test_run_id = client.run_test(device_type, app_id, test_id)["test_run_id"]
|
125
|
+
client.monitor_test(test_run_id)
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'appurify'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.color_enabled = true
|
6
|
+
config.formatter = 'documentation'
|
7
|
+
end
|
8
|
+
|
9
|
+
def mock_access_token_response(token="r895ku94f167udxfukhkbntyclxvwl8sc", ttl=86400)
|
10
|
+
url = "https://live.appurify.com/resource/access_token/generate/"
|
11
|
+
response ="{\"meta\": {\"code\": 200, \"request_id\": 123.456}, \"response\": {\"access_token\": \"#{token}\", \"ttl\": #{ttl}}}"
|
12
|
+
FakeWeb.register_uri(:post, url, :body => response, :status => 200)
|
13
|
+
end
|
14
|
+
|
15
|
+
def mock_application_upload_response(application_id="qxp58i5tbaosgbq8nagosfkf490gs7spd")
|
16
|
+
url = "https://live.appurify.com/resource/apps/upload/"
|
17
|
+
response = "{\"meta\": {\"code\": 200, \"request_id\": 123}, \"response\": {\"name\": \"cisimple.app.zip\", \"test_type\": null, \"uploaded_on\": \"2013-03-13T21:39:59Z\", \"source_type\": \"url\", \"ttl\": 86400, \"id\": \"#{application_id}\", \"size\": 404423}}"
|
18
|
+
FakeWeb.register_uri(:post, url, :body => response, :status => 200)
|
19
|
+
end
|
20
|
+
|
21
|
+
def mock_test_upload_response(test_id="eh4x44nspdqcsva7v2nvabjesvoqvcn89", test_type="ocunit")
|
22
|
+
url = "https://live.appurify.com/resource/tests/upload/"
|
23
|
+
response = "{\"meta\": {\"code\": 200, \"request_id\": 452}, \"response\": {\"name\": \"cisimpleTests.octest.zip\", \"test_type\": \"#{test_type}\", \"uploaded_on\": \"2013-03-13T22:12:50Z\", \"source_type\": \"url\", \"ttl\": 86400, \"id\": \"#{test_id}\", \"size\": 7764}}"
|
24
|
+
FakeWeb.register_uri(:post, url, :body => response, :status => 200)
|
25
|
+
end
|
26
|
+
|
27
|
+
def mock_run_test_response(test_run_id=1)
|
28
|
+
url = "https://live.appurify.com/resource/tests/run/"
|
29
|
+
response = "{\"meta\": {\"code\": 200, \"request_id\": 123}, \"response\": { \"test_run_id\": #{test_run_id} }}"
|
30
|
+
FakeWeb.register_uri(:post, url, :body => response, :status => 200)
|
31
|
+
end
|
32
|
+
|
33
|
+
def mock_upload_device_conditions_response
|
34
|
+
url = "https://live.appurify.com/resource/config/upload/"
|
35
|
+
response = "{\"meta\": {\"code\": 200, \"request_id\": 123}, \"response\": { }}"
|
36
|
+
FakeWeb.register_uri(:post, url, :body => response, :status => 200)
|
37
|
+
end
|
38
|
+
|
39
|
+
def mock_monitor_test_response(access_token, test_run_id=1, status="complete")
|
40
|
+
url = "https://live.appurify.com/resource/tests/check/?access_token=#{access_token}&test_run_id=#{test_run_id}"
|
41
|
+
response = "{\"meta\": {\"code\": 200, \"request_id\": 123}, \"response\": { \"status\": \"#{status}\" }}"
|
42
|
+
FakeWeb.register_uri(:get, url, :body => response, :status => 200)
|
43
|
+
end
|
44
|
+
|
45
|
+
def mock_device_types_response(access_token)
|
46
|
+
url = "https://live.appurify.com/resource/devices/list/?access_token=#{access_token}"
|
47
|
+
response = "{\"meta\": {\"code\": 200, \"request_id\": 475}, \"response\": [{\"device_type_id\": 1, \"name\": \"4s\", \"battery\": true, \"brand\": \"iPhone\", \"os_name\": \"iOS\", \"os_version\": \"5.1.1\", \"has_available_device\": false, \"carrier\": null}, {\"device_type_id\": 2, \"name\": \"4\", \"battery\": true, \"brand\": \"iPhone\", \"os_name\": \"iOS\", \"os_version\": \"5.1.1\", \"has_available_device\": true, \"carrier\": null}]}"
|
48
|
+
FakeWeb.register_uri(:get, url, :body => response, :status => 200)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def mock_network_conditions_response(access_token)
|
53
|
+
url = "https://live.appurify.com/resource/devices/config/networks/list/?access_token=#{access_token}"
|
54
|
+
response = "{\"meta\": {\"code\": 200, \"request_id\": 9673}, \"response\": [
|
55
|
+
{\"network_id\": 29, \"network_group\": \"AT&T\", \"network_name\": \"4G_LTE\"},
|
56
|
+
{\"network_id\": 16, \"network_group\": \"AT&T\", \"network_name\": \"3G_4_Bars\"},
|
57
|
+
{\"network_id\": 17, \"network_group\": \"AT&T\", \"network_name\": \"3G_3_Bars\"},
|
58
|
+
{\"network_id\": 18, \"network_group\": \"AT&T\", \"network_name\": \"3G_2_Bars\"},
|
59
|
+
{\"network_id\": 19, \"network_group\": \"AT&T\", \"network_name\": \"3G_1_Bar\"}]}"
|
60
|
+
FakeWeb.register_uri(:get, url, :body => response, :status => 200)
|
61
|
+
end
|
62
|
+
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: appurify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.5'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kevin Rohling
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.11'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.11'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: fakeweb
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.30'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.30'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: timecop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.60'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.60'
|
69
|
+
description: API client for Appurify
|
70
|
+
email:
|
71
|
+
- support@appurify.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- README.md
|
77
|
+
- lib/appurify.rb
|
78
|
+
- lib/appurify/client.rb
|
79
|
+
- lib/appurify/version.rb
|
80
|
+
- spec/client/client_spec.rb
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
homepage: https://github.com/appurify/appurify-ruby
|
83
|
+
licenses: []
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options:
|
87
|
+
- --charset=UTF-8
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 2.0.6
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: Run tests using Appurify's mobile devices.
|
106
|
+
test_files:
|
107
|
+
- spec/client/client_spec.rb
|
108
|
+
- spec/spec_helper.rb
|