appurify 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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!
@@ -0,0 +1,10 @@
1
+ require 'open-uri'
2
+ require 'json'
3
+ require 'net/https'
4
+ require 'rest-client'
5
+ require 'appurify/version'
6
+ require 'appurify/client'
7
+
8
+ module Appurify
9
+ HOSTNAME = "live.appurify.com"
10
+ end
@@ -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,3 @@
1
+ module Appurify
2
+ VERSION = '0.5'
3
+ 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
@@ -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