hockeyapp 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ module HockeyApp
2
+ class AndroidAppUrls
3
+ def initialize app
4
+ @app=app
5
+ end
6
+
7
+ def direct_download_url
8
+ "https://rink.hockeyapp.net/api/2/apps/#{@app.public_identifier}?format=apk"
9
+ end
10
+
11
+ def install_url
12
+ direct_download_url
13
+ end
14
+
15
+ end
16
+
17
+ class AndroidVersionUrls
18
+ def initialize version
19
+ @version=version
20
+ end
21
+
22
+ def direct_download_url
23
+ "https://rink.hockeyapp.net/api/2/apps/#{@version.app.public_identifier}/app_versions/#{@version.id.to_s}?format=apk"
24
+ end
25
+
26
+ def install_url
27
+ direct_download_url
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ module HockeyApp
2
+ class IOSAppUrls
3
+ def initialize app
4
+ @app=app
5
+ end
6
+ def download_url
7
+ "https://rink.hockeyapp.net/apps/#{@app.public_identifier}"
8
+ end
9
+
10
+ def direct_download_url
11
+ @app.last_version.direct_download_url
12
+ end
13
+
14
+ def install_url
15
+ @app.last_version.install_url
16
+ end
17
+
18
+ end
19
+
20
+ class IOSVersionUrls
21
+
22
+ def initialize version
23
+ @version = version
24
+ end
25
+
26
+ def direct_download_url
27
+ "https://rink.hockeyapp.net/api/2/apps/#{@version.app.public_identifier}/app_versions/#{@version.id.to_s}?format=ipa"
28
+ end
29
+
30
+ def install_url
31
+ location = "https://rink.hockeyapp.net/api/2/apps/#{@version.app.public_identifier}/app_versions/#{@version.id.to_s}?format=plist"
32
+ "itms-services://?action=download-manifest&url=#{CGI::escape(location)}"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,72 @@
1
+ module HockeyApp
2
+ class Client
3
+
4
+ def initialize ws
5
+ @ws = ws
6
+ end
7
+
8
+ def get_apps
9
+ apps_hash = ws.get_apps
10
+ assert_success apps_hash
11
+ apps_hash["apps"].map{|app_hash|App.from_hash(app_hash, self)}
12
+ end
13
+
14
+ def get_crashes app
15
+ crashes_hash = ws.get_crashes app.public_identifier
16
+ assert_success crashes_hash
17
+ crashes_hash["crashes"].map{|crash_hash|Crash.from_hash(crash_hash, app, self)}
18
+ end
19
+
20
+ def get_crash_groups app
21
+ crash_groups_hash = ws.get_crash_groups app.public_identifier
22
+ assert_success crash_groups_hash
23
+ crash_groups_hash["crash_reasons"].map{|reason_hash|CrashGroup.from_hash(reason_hash, app, self)}
24
+ end
25
+
26
+ def get_crash_log crash
27
+ ws.get_crash_log crash.app.public_identifier, crash.id
28
+ end
29
+
30
+ def get_crash_description crash
31
+ ws.get_crash_description crash.app.public_identifier, crash.id
32
+ end
33
+
34
+ def get_versions app
35
+ versions_hash = ws.get_versions app.public_identifier
36
+ versions_hash["app_versions"].map{|version_hash|Version.from_hash(version_hash, app, self)}
37
+ end
38
+
39
+ def post_new_version version
40
+ app_id = version.app.public_identifier
41
+ ipa = version.ipa
42
+ raise "There must be an executable file" if ipa.nil?
43
+ version_hash = ws.post_new_version(app_id, ipa, version.dsym, version.notes, version.notes_type, version.notify, version.status)
44
+ raise version_hash['errors'].map{|e|e.to_s}.join("\n") unless version_hash['errors'].nil?
45
+ Version.from_hash(version_hash, version.app, self)
46
+ end
47
+
48
+ def remove_app app
49
+ resp = ws.remove_app app.public_identifier
50
+ raise "unexpected response" if resp.code != 200
51
+ resp.code == 200
52
+ end
53
+
54
+ def create_app file_ipa
55
+ resp = ws.post_new_app(file_ipa)
56
+ raise resp['errors'].map{|e|e.to_s}.join("\n") unless resp['errors'].nil?
57
+ App.from_hash(resp, self)
58
+ end
59
+
60
+
61
+
62
+ private
63
+
64
+ attr_reader :ws
65
+
66
+ def assert_success hash
67
+ status = hash["status"]
68
+ raise "Bad Status : #{status}" unless status == "success"
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,96 @@
1
+ require 'httmultiparty'
2
+
3
+ module HockeyApp
4
+ class WS
5
+ include HTTMultiParty
6
+ base_uri 'https://rink.hockeyapp.net/api/2'
7
+ headers 'Accept' => 'application/json'
8
+ format :json
9
+
10
+
11
+ def initialize (options = {})
12
+ @options = Config.to_h.merge(options)
13
+ raise "No API Token Given" if (@options[:token].nil?)
14
+ self.class.headers 'X-HockeyAppToken' => @options[:token]
15
+ self.class.base_uri @options[:base_uri] if @options[:base_uri].present?
16
+ end
17
+
18
+
19
+ def get_apps
20
+ self.class.get '/apps'
21
+ end
22
+
23
+
24
+ def get_crashes app_id, options = {}
25
+ self.class.get "/apps/#{app_id}/crashes", options
26
+ end
27
+
28
+ def get_crash_groups app_id, options = {}
29
+ self.class.get "/apps/#{app_id}/crash_reasons", options
30
+ end
31
+
32
+ # this is damn not thread safe !
33
+ def get_crash_log app_id, crash_id, options = {}
34
+ self.class.format :plain
35
+ log = self.class.get "/apps/#{app_id}/crashes/#{crash_id}?format=log", options
36
+ self.class.format :json
37
+ log
38
+ end
39
+
40
+ # this is damn not thread safe !
41
+ def get_crash_description app_id, crash_id, options = {}
42
+ self.class.format :plain
43
+ description = self.class.get "/apps/#{app_id}/crashes/#{crash_id}?format=text", options
44
+ self.class.format :json
45
+ description
46
+ end
47
+
48
+ def get_versions app_id, options = {}
49
+ self.class.get "/apps/#{app_id}/app_versions", options
50
+ end
51
+
52
+ def post_new_version(
53
+ app_id,
54
+ ipa,
55
+ dsym=nil,
56
+ notes="New version",
57
+ notes_type=Version::NOTES_TYPES_TO_SYM.invert[:textile],
58
+ notify=Version::NOTIFY_TO_BOOL.invert[false],
59
+ status=Version::STATUS_TO_SYM.invert[:allow]
60
+ )
61
+ params = {
62
+ :ipa => ipa ,
63
+ :dsym => dsym ,
64
+ :notes => notes,
65
+ :notes_type => notes_type,
66
+ :notify => notify,
67
+ :status => status
68
+ }
69
+ params.reject!{|_,v|v.nil?}
70
+ self.class.post "/apps/#{app_id}/app_versions", :body => params
71
+ end
72
+
73
+
74
+ def remove_app app_id
75
+ self.class.format :plain
76
+ response = self.class.delete "/apps/#{app_id}"
77
+ self.class.format :json
78
+ response
79
+ end
80
+
81
+ def post_new_app(file_ipa,
82
+ notes="New app",
83
+ notes_type=App::NOTES_TYPES_TO_SYM.invert[:textile],
84
+ notify=App::NOTIFY_TO_BOOL.invert[false],
85
+ status=App::STATUS_TO_SYM.invert[:allow])
86
+ params = {
87
+ :ipa => file_ipa,
88
+ :notes => notes,
89
+ :notes_type => notes_type,
90
+ :notify => notify,
91
+ :status => status
92
+ }
93
+ self.class.post "/apps", :body => params
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'support/rspec_helper'
2
+
3
+ describe HockeyApp::Config do
4
+
5
+ it "can be set throug configure method" do
6
+ HockeyApp::Config.configure do |config|
7
+ config.token = "ABCDEF"
8
+ end
9
+
10
+ HockeyApp::Config.token.should == "ABCDEF"
11
+ end
12
+
13
+ it "can store a token" do
14
+ HockeyApp::Config.token = "ABCDEF"
15
+ HockeyApp::Config.token.should == "ABCDEF"
16
+ end
17
+
18
+ it "can store a base_uri" do
19
+ HockeyApp::Config.base_uri = "foo"
20
+ HockeyApp::Config.base_uri.should == "foo"
21
+ end
22
+
23
+ it "can transform into a hash" do
24
+ HockeyApp::Config.configure do |config|
25
+ config.token = "ABCDEF"
26
+ config.base_uri = "foobar"
27
+ end
28
+ hash = HockeyApp::Config.to_h
29
+ hash.should == {
30
+ :token => "ABCDEF",
31
+ :base_uri => "foobar"
32
+ }
33
+ end
34
+
35
+ end
@@ -0,0 +1,13 @@
1
+ require 'support/rspec_helper'
2
+
3
+ describe HockeyApp do
4
+ before :each do
5
+ HockeyApp::Config.configure do |config|
6
+ config.token = "ABCDEF"
7
+ end
8
+ end
9
+ it "can build a ws client" do
10
+ client = HockeyApp.build_client
11
+ client.should be_a HockeyApp::Client
12
+ end
13
+ end
@@ -0,0 +1,143 @@
1
+ require_relative '../support/rspec_helper'
2
+
3
+ describe HockeyApp::App do
4
+
5
+ before :each do
6
+ h = {
7
+ "bundle_identifier" => "de.codenauts.hockeytest.beta",
8
+ "device_family" => "iPhone/iPod",
9
+ "public_identifier" => "1234567890abcdef1234567890abcdef",
10
+ "company" => "some company",
11
+ "release_type" => 0,
12
+ "platform" => "iOS",
13
+ "title" => "Hockey Test",
14
+ "role" => 0,
15
+ "status" => 2,
16
+ "minimum_os_version" => "4.0",
17
+ "owner" => "John Doe"
18
+ }
19
+ @client = HockeyApp::Client.new(HockeyApp::FakeWS.new)
20
+ @app = HockeyApp::App.from_hash h, @client
21
+ @model = @app
22
+ end
23
+
24
+ it_behaves_like "ActiveModel"
25
+
26
+ it "can give me info about my application" do
27
+ @app.bundle_identifier.should == "de.codenauts.hockeytest.beta"
28
+ @app.device_family.should == "iPhone/iPod"
29
+ @app.public_identifier.should == "1234567890abcdef1234567890abcdef"
30
+ @app.company.should == "some company"
31
+ @app.release_type.should == 0
32
+ @app.platform.should == "iOS"
33
+ @app.title.should == "Hockey Test"
34
+ @app.role.should == 0
35
+ @app.status.should == 2
36
+ @app.minimum_os_version.should == "4.0"
37
+ @app.owner.should == "John Doe"
38
+ end
39
+
40
+
41
+ it "will call client once when asked for crashes" do
42
+ @client.should_receive(:get_crashes).with(@app).and_return([])
43
+ @app.crashes
44
+ @client.should_not_receive(:get_crashes).with(@app)
45
+ @app.crashes
46
+ end
47
+
48
+ it "will call client once when asked for crash reasons" do
49
+ @client.should_receive(:get_crash_groups).with(@app).and_return([])
50
+ @app.crash_reasons
51
+ @client.should_not_receive(:get_crash_groups).with(@app)
52
+ @app.crash_reasons
53
+ end
54
+
55
+ it "will call client once when asked for versions" do
56
+ @client.should_receive(:get_versions).with(@app).and_return([])
57
+ @app.versions
58
+ @client.should_not_receive(:get_versions).with(@app)
59
+ @app.versions
60
+ end
61
+
62
+ it "can generate a download url" do
63
+ @app.download_url.should == "https://rink.hockeyapp.net/apps/0873e2b98ad046a92c170a243a8515f6/app_versions/208"
64
+ end
65
+
66
+
67
+
68
+ it "can generate a direct download url for Android" do
69
+ @app.platform = "Android"
70
+ @app.direct_download_url.should == "https://rink.hockeyapp.net/api/2/apps/1234567890abcdef1234567890abcdef?format=apk"
71
+ end
72
+
73
+ it "can generate a direct download url for iOS" do
74
+ @app.platform = "iOS"
75
+ @app.direct_download_url.should == "https://rink.hockeyapp.net/api/2/apps/1234567890abcdef1234567890abcdef/app_versions/208?format=ipa"
76
+ end
77
+
78
+ it "can generate an install url for iOS" do
79
+ @app.install_url.should == "itms-services://?action=download-manifest&url=https%3A%2F%2Frink.hockeyapp.net%2Fapi%2F2%2Fapps%2F1234567890abcdef1234567890abcdef%2Fapp_versions%2F208%3Fformat%3Dplist"
80
+ end
81
+
82
+ it "can generate an icon url for iOS" do
83
+ @app.icon.should == "https://rink.hockeyapp.net/api/2/apps/1234567890abcdef1234567890abcdef?format=png"
84
+ end
85
+
86
+ it "can generate an icon url for Android" do
87
+ @app.platform = "Android"
88
+ @app.icon.should == "https://rink.hockeyapp.net/api/2/apps/1234567890abcdef1234567890abcdef?format=png"
89
+ end
90
+
91
+ it "can generate an install url for Android" do
92
+ @app.platform = "Android"
93
+ @app.install_url.should == @app.direct_download_url
94
+ end
95
+
96
+
97
+ describe "#create_version" do
98
+ it "will create a new version instance and pass it to the webservice" do
99
+ release_notes = "New version from automated test"
100
+ binary_file = double('file')
101
+ fake_version = double('version')
102
+ HockeyApp::Version.should_receive(:new).with(@app, @client).and_return(fake_version)
103
+ fake_version.should_receive(:ipa=).with(binary_file)
104
+ fake_version.should_receive(:notes=).with(release_notes)
105
+ @client.should_receive(:post_new_version).with(fake_version)
106
+ @app.create_version(binary_file, release_notes)
107
+ end
108
+
109
+ end
110
+
111
+ describe "#remove_app", :js => true do
112
+ it "will remove an app from hockeyapp", :driver => :webkit do
113
+ @client.should_receive(:remove_app).with(@app).and_return(true)
114
+ @app.remove
115
+ end
116
+ end
117
+
118
+ describe "#last_version" do
119
+
120
+ it "sorts the versions" do
121
+ versions = double("versions")
122
+ @app.should_receive(:versions).and_return(versions)
123
+ versions.should_receive(:sort_by).and_return([])
124
+ @app.last_version
125
+ end
126
+
127
+ context "there are 3 versions for this app" do
128
+ before :each do
129
+ @version1 = double("Version1", :version => "5")
130
+ @version2 = double("Version2", :version => "10")
131
+ @version3 = double("Version3", :version => "6")
132
+ @versions = [@version1, @version2, @version3]
133
+
134
+ end
135
+ it "returns the last version" do
136
+ @app.should_receive(:versions).and_return(@versions)
137
+ @app.last_version.version.should == "10"
138
+ end
139
+ end
140
+
141
+
142
+ end
143
+ end
@@ -0,0 +1,53 @@
1
+ require_relative '../support/rspec_helper'
2
+
3
+ describe HockeyApp::CrashGroup do
4
+
5
+ before :each do
6
+ h = {
7
+ "file" => "AbstractParser.java",
8
+ "reason" => "java.lang.RuntimeException: An error occured while executing doInBackground()",
9
+ "status" => 1,
10
+ "id" => 135837,
11
+ "class" => "com.tapptic.common.parser.AbstractParser",
12
+ "bundle_version" => "2",
13
+ "last_crash_at" => "2011-12-15T20:07:11Z",
14
+ "app_version_id" => 2,
15
+ "line" => "48",
16
+ "updated_at" => "2012-01-03T13:22:01Z",
17
+ "bundle_short_version" => "0.2",
18
+ "method" => "parse",
19
+ "number_of_crashes" => 2,
20
+ "fixed" => true,
21
+ "created_at" => "2011-12-15T20:06:49Z",
22
+ "app_id" => 9999
23
+ }
24
+ @client = HockeyApp::Client.new(HockeyApp::FakeWS.new)
25
+ @app = HockeyApp::App.from_hash( {"public_identifier" => "91423bc5519dd2462513abbb54598959"}, @client)
26
+ @crash_group = HockeyApp::CrashGroup.from_hash h, @app, @client
27
+ @model = @crash_group
28
+ end
29
+
30
+ it_behaves_like "ActiveModel"
31
+
32
+ it "can give me info about the crash group" do
33
+ @crash_group.file.should == "AbstractParser.java"
34
+ @crash_group.reason.should == "java.lang.RuntimeException: An error occured while executing doInBackground()"
35
+ @crash_group.status.should == 1
36
+ @crash_group.id.should == 135837
37
+ @crash_group.crash_class.should == "com.tapptic.common.parser.AbstractParser"
38
+ @crash_group.bundle_version.should == "2"
39
+ @crash_group.last_crash_at.should == "2011-12-15T20:07:11Z"
40
+ @crash_group.app_version_id.should == 2
41
+ @crash_group.updated_at.should == "2012-01-03T13:22:01Z"
42
+ @crash_group.bundle_short_version.should == "0.2"
43
+ @crash_group.method.should == "parse"
44
+ @crash_group.number_of_crashes.should == 2
45
+ @crash_group.fixed.should == true
46
+ @crash_group.created_at.should == "2011-12-15T20:06:49Z"
47
+ @crash_group.app_id.should == 9999
48
+ end
49
+
50
+
51
+
52
+ end
53
+