testingbot 0.2.3 → 1.0.0

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.
@@ -0,0 +1,11 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Endpoints under /jobs.
4
+ module Jobs
5
+ # Poll the status/result of an asynchronous job (e.g. a Codeless Lab run).
6
+ def get_job(job_id)
7
+ get("/jobs/#{escape(job_id)}")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,74 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Codeless Lab test endpoints under /lab.
4
+ module Lab
5
+ def get_lab_tests(offset = 0, count = 10)
6
+ get("/lab#{query(:offset => offset, :count => count)}")
7
+ end
8
+
9
+ def create_lab_test(params = {})
10
+ post("/lab", params)
11
+ end
12
+
13
+ def get_lab_test(lab_test_id)
14
+ get("/lab/#{escape(lab_test_id)}")
15
+ end
16
+
17
+ def update_lab_test(lab_test_id, params = {})
18
+ put("/lab/#{escape(lab_test_id)}", params)
19
+ end
20
+
21
+ def delete_lab_test(lab_test_id)
22
+ delete("/lab/#{escape(lab_test_id)}")
23
+ end
24
+
25
+ def get_lab_test_steps(lab_test_id)
26
+ get("/lab/#{escape(lab_test_id)}/steps")
27
+ end
28
+
29
+ def set_lab_test_steps(lab_test_id, params = {})
30
+ post("/lab/#{escape(lab_test_id)}/steps", params)
31
+ end
32
+
33
+ def get_lab_test_browsers(lab_test_id)
34
+ get("/lab/#{escape(lab_test_id)}/browsers")
35
+ end
36
+
37
+ def set_lab_test_browsers(lab_test_id, params = {})
38
+ post("/lab/#{escape(lab_test_id)}/browsers", params)
39
+ end
40
+
41
+ def add_lab_test_alert(lab_test_id, params = {})
42
+ post("/lab/#{escape(lab_test_id)}/alert", params)
43
+ end
44
+
45
+ def update_lab_test_alert(lab_test_id, params = {})
46
+ put("/lab/#{escape(lab_test_id)}/alert", params)
47
+ end
48
+
49
+ def create_lab_test_report(lab_test_id, params = {})
50
+ post("/lab/#{escape(lab_test_id)}/report", params)
51
+ end
52
+
53
+ def update_lab_test_report(lab_test_id, params = {})
54
+ put("/lab/#{escape(lab_test_id)}/report", params)
55
+ end
56
+
57
+ def schedule_lab_test(lab_test_id, params = {})
58
+ post("/lab/#{escape(lab_test_id)}/schedule", params)
59
+ end
60
+
61
+ def trigger_lab_test(lab_test_id, params = {})
62
+ post("/lab/#{escape(lab_test_id)}/trigger", params)
63
+ end
64
+
65
+ def stop_lab_test(lab_test_id)
66
+ put("/lab/#{escape(lab_test_id)}/stop")
67
+ end
68
+
69
+ def trigger_all_lab_tests(params = {})
70
+ post("/lab/trigger_all", params)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,46 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Codeless Lab suite endpoints under /labsuites.
4
+ module LabSuites
5
+ def get_lab_suites(offset = 0, count = 10)
6
+ get("/labsuites#{query(:offset => offset, :count => count)}")
7
+ end
8
+
9
+ def create_lab_suite(params = {})
10
+ post("/labsuites", params)
11
+ end
12
+
13
+ def get_lab_suite(suite_id)
14
+ get("/labsuites/#{escape(suite_id)}")
15
+ end
16
+
17
+ def delete_lab_suite(suite_id)
18
+ delete("/labsuites/#{escape(suite_id)}")
19
+ end
20
+
21
+ def get_lab_suite_tests(suite_id)
22
+ get("/labsuites/#{escape(suite_id)}/tests")
23
+ end
24
+
25
+ def add_lab_suite_tests(suite_id, params = {})
26
+ post("/labsuites/#{escape(suite_id)}/tests", params)
27
+ end
28
+
29
+ def remove_lab_suite_test(suite_id, test_id)
30
+ delete("/labsuites/#{escape(suite_id)}/tests/#{escape(test_id)}")
31
+ end
32
+
33
+ def get_lab_suite_browsers(suite_id)
34
+ get("/labsuites/#{escape(suite_id)}/browsers")
35
+ end
36
+
37
+ def set_lab_suite_browsers(suite_id, params = {})
38
+ post("/labsuites/#{escape(suite_id)}/browsers", params)
39
+ end
40
+
41
+ def trigger_lab_suite(suite_id, params = {})
42
+ post("/labsuites/#{escape(suite_id)}/trigger", params)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Browser, device and configuration endpoints.
4
+ module Platform
5
+ def get_browsers
6
+ get("/browsers")
7
+ end
8
+
9
+ # Optionally filter server-side by platform and/or web capability.
10
+ def get_devices(platform = nil, web = nil)
11
+ get("/devices#{query(:platform => platform, :web => web)}")
12
+ end
13
+
14
+ def get_available_devices
15
+ get("/devices/available")
16
+ end
17
+
18
+ # Fetch a single physical device by its numeric ID.
19
+ def get_device(device_id)
20
+ get("/devices/#{escape(device_id)}")
21
+ end
22
+
23
+ # List the IP ranges TestingBot tests originate from (firewall allow-listing).
24
+ def get_ip_ranges
25
+ get("/configuration/ip-ranges")
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Endpoints under /screenshots.
4
+ module Screenshots
5
+ def take_screenshots(configuration)
6
+ post("/screenshots", configuration)
7
+ end
8
+
9
+ def get_screenshots_history(offset = 0, count = 10)
10
+ get("/screenshots#{query(:offset => offset, :count => count)}")
11
+ end
12
+
13
+ # +params+ accepts the optional excludeIds query param.
14
+ def get_screenshots(screenshots_id, params = {})
15
+ get("/screenshots/#{escape(screenshots_id)}#{query(params)}")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ require 'digest'
2
+
3
+ module TestingBot
4
+ module Resources
5
+ # Test/build sharing helpers.
6
+ module Sharing
7
+ # Compute the hash used to share private tests/builds with other people.
8
+ def get_authentication_hash(identifier)
9
+ Digest::MD5.hexdigest("#{@key}:#{@secret}:#{identifier}")
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ module TestingBot
2
+ module Resources
3
+ # TestingBot Storage endpoints under /storage (mobile app testing).
4
+ #
5
+ # App URLs target a wildcard route, so they are only stripped of their
6
+ # tb:// scheme (slashes are preserved, not escaped).
7
+ module Storage
8
+ def upload_local_file(file_path)
9
+ File.open(file_path, 'rb') do |io|
10
+ @connection.request(:post, "/storage", { :multipart => true, :file => io }, :timeout => 600)
11
+ end
12
+ end
13
+
14
+ def upload_remote_file(url)
15
+ post("/storage", { :url => url })
16
+ end
17
+
18
+ # Replace the binary stored under an existing app key with a local file.
19
+ def update_local_file(app_url, file_path)
20
+ File.open(file_path, 'rb') do |io|
21
+ @connection.request(:post, "/storage/#{strip_scheme(app_url)}",
22
+ { :multipart => true, :file => io }, :timeout => 600)
23
+ end
24
+ end
25
+
26
+ # Replace the binary stored under an existing app key with a remote URL.
27
+ def update_remote_file(app_url, url)
28
+ post("/storage/#{strip_scheme(app_url)}", { :url => url })
29
+ end
30
+
31
+ def get_uploaded_files(offset = 0, count = 10)
32
+ get("/storage#{query(:offset => offset, :count => count)}")
33
+ end
34
+
35
+ def get_uploaded_file(app_url)
36
+ get("/storage/#{strip_scheme(app_url)}")
37
+ end
38
+
39
+ def delete_uploaded_file(app_url)
40
+ success?(delete("/storage/#{strip_scheme(app_url)}"))
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,35 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Endpoints under /team-management.
4
+ module Team
5
+ def get_team
6
+ get("/team-management")
7
+ end
8
+
9
+ def get_users_in_team(offset = 0, count = 10)
10
+ get("/team-management/users#{query(:offset => offset, :count => count)}")
11
+ end
12
+
13
+ def get_user_in_team(user_id)
14
+ get("/team-management/users/#{escape(user_id)}")
15
+ end
16
+
17
+ # Fetch a team member's API client key (requires ADMIN rights).
18
+ def get_user_client_key(user_id)
19
+ get("/team-management/users/#{escape(user_id)}/client-key")
20
+ end
21
+
22
+ def create_user_in_team(user = {})
23
+ post("/team-management/users", user)
24
+ end
25
+
26
+ def update_user_in_team(user_id, user = {})
27
+ put("/team-management/users/#{escape(user_id)}", user)
28
+ end
29
+
30
+ def reset_credentials(user_id)
31
+ post("/team-management/users/#{escape(user_id)}/reset-keys")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Endpoints under /tests.
4
+ module Tests
5
+ # +filters+ accepts the backend's optional query params: since, browser_id,
6
+ # group, build, skip_fields.
7
+ def get_tests(offset = 0, count = 10, filters = {})
8
+ get("/tests#{query({ :offset => offset, :count => count }.merge(filters))}")
9
+ end
10
+
11
+ def get_test(test_id)
12
+ get("/tests/#{escape(test_id)}")
13
+ end
14
+
15
+ def update_test(test_id, params = {})
16
+ success?(put("/tests/#{escape(test_id)}", wrap_params("test", params)))
17
+ end
18
+
19
+ def delete_test(test_id)
20
+ success?(delete("/tests/#{escape(test_id)}"))
21
+ end
22
+
23
+ def stop_test(test_id)
24
+ success?(put("/tests/#{escape(test_id)}/stop"))
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Endpoints under /tunnel.
4
+ module Tunnels
5
+ def get_tunnels
6
+ get("/tunnel/list")
7
+ end
8
+
9
+ # Fetch the active tunnel, or a specific tunnel by numeric ID.
10
+ def get_tunnel(tunnel_identifier = nil)
11
+ tunnel_identifier ? get("/tunnel/#{escape(tunnel_identifier)}") : get("/tunnel")
12
+ end
13
+
14
+ # Delete a tunnel by ID, or the active tunnel when called without an argument.
15
+ def delete_tunnel(tunnel_identifier = nil)
16
+ delete(tunnel_identifier ? "/tunnel/#{escape(tunnel_identifier)}" : "/tunnel")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module TestingBot
2
+ module Resources
3
+ # Endpoints under /user.
4
+ module User
5
+ def get_user_info
6
+ get("/user")
7
+ end
8
+
9
+ def update_user_info(params = {})
10
+ success?(put("/user", wrap_params("user", params)))
11
+ end
12
+
13
+ # Retrieve the account's API key/secret pair.
14
+ def get_user_keys
15
+ get("/user/keys")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
- module Testingbot
2
- VERSION = "0.2.3"
1
+ module TestingBot
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/testingbot.rb CHANGED
@@ -1 +1,4 @@
1
- require "testingbot/api"
1
+ require "testingbot/version"
2
+ require "testingbot/errors"
3
+ require "testingbot/connection"
4
+ require "testingbot/api"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testingbot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jochen Delabie
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-22 00:00:00.000000000 Z
11
+ date: 2026-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
69
83
  description: This gem makes interacting with the TestingBot API easy with Ruby
70
84
  email:
71
85
  - info@testingbot.com
@@ -74,8 +88,10 @@ executables:
74
88
  extensions: []
75
89
  extra_rdoc_files: []
76
90
  files:
91
+ - ".github/workflows/release.yml"
77
92
  - ".github/workflows/test.yml"
78
93
  - ".gitignore"
94
+ - CHANGELOG.md
79
95
  - Gemfile
80
96
  - LICENSE
81
97
  - README.md
@@ -83,10 +99,21 @@ files:
83
99
  - bin/testingbot
84
100
  - lib/testingbot.rb
85
101
  - lib/testingbot/api.rb
102
+ - lib/testingbot/connection.rb
103
+ - lib/testingbot/errors.rb
104
+ - lib/testingbot/resources/builds.rb
105
+ - lib/testingbot/resources/jobs.rb
106
+ - lib/testingbot/resources/lab.rb
107
+ - lib/testingbot/resources/lab_suites.rb
108
+ - lib/testingbot/resources/platform.rb
109
+ - lib/testingbot/resources/screenshots.rb
110
+ - lib/testingbot/resources/sharing.rb
111
+ - lib/testingbot/resources/storage.rb
112
+ - lib/testingbot/resources/team.rb
113
+ - lib/testingbot/resources/tests.rb
114
+ - lib/testingbot/resources/tunnels.rb
115
+ - lib/testingbot/resources/user.rb
86
116
  - lib/testingbot/version.rb
87
- - spec/integration/api_spec.rb
88
- - spec/resources/test.apk
89
- - spec/spec_helper.rb
90
117
  homepage: https://testingbot.com
91
118
  licenses:
92
119
  - MIT
@@ -95,7 +122,7 @@ metadata:
95
122
  documentation_uri: https://github.com/testingbot/testingbot_ruby
96
123
  homepage_uri: https://github.com/testingbot/testingbot_ruby
97
124
  source_code_uri: https://github.com/testingbot/testingbot_ruby
98
- post_install_message:
125
+ post_install_message:
99
126
  rdoc_options: []
100
127
  require_paths:
101
128
  - lib
@@ -110,11 +137,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
137
  - !ruby/object:Gem::Version
111
138
  version: '0'
112
139
  requirements: []
113
- rubygems_version: 3.0.3.1
114
- signing_key:
140
+ rubygems_version: 3.5.22
141
+ signing_key:
115
142
  specification_version: 4
116
143
  summary: Ruby API Gem to be used with testingbot.com
117
- test_files:
118
- - spec/integration/api_spec.rb
119
- - spec/resources/test.apk
120
- - spec/spec_helper.rb
144
+ test_files: []
@@ -1,108 +0,0 @@
1
- require "uri"
2
- require "net/http"
3
- require 'rspec'
4
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
5
-
6
- describe "Testingbot Api" do
7
- context "the API should return valid user information" do
8
- it "should return info for the current user" do
9
- @api = TestingBot::Api.new
10
- @api.get_user_info.should_not be_empty
11
- @api.get_user_info["first_name"].should_not be_empty
12
- end
13
-
14
- it "should raise an error when wrong credentials are provided" do
15
- @api = TestingBot::Api.new("bogus", "false")
16
- lambda { @api.get_user_info }.should raise_error(RestClient::Unauthorized)
17
- end
18
- end
19
-
20
- context "updating my user info via the API should work" do
21
- it "should allow me to update my own user info" do
22
- @api = TestingBot::Api.new
23
- new_name = rand(36**9).to_s(36)
24
- @api.update_user_info({ "first_name" => new_name }).should == true
25
- @api.get_user_info["first_name"].should == new_name
26
- end
27
- end
28
-
29
- context "retrieve my own tests" do
30
- it "should retrieve a list of my own tests" do
31
- @api = TestingBot::Api.new
32
- @api.get_tests.include?("data").should == true
33
- end
34
-
35
- it "should provide info for a specific test" do
36
- @api = TestingBot::Api.new
37
- data = @api.get_tests["data"]
38
- if data.length > 0
39
- test_id = data.first["id"]
40
-
41
- single_test = @api.get_test(test_id)
42
- single_test["id"].should == test_id
43
- end
44
- end
45
-
46
- it "should fail when trying to access a test that is not mine" do
47
- @api = TestingBot::Api.new
48
- lambda { @api.get_test(123423423423423) }.should raise_error(RestClient::NotFound)
49
- end
50
- end
51
-
52
- context "update a test" do
53
- it "should update a test of mine" do
54
- @api = TestingBot::Api.new
55
- data = @api.get_tests["data"]
56
- if data.length > 0
57
- test_id = data.first["id"]
58
- new_name = rand(36**9).to_s(36)
59
- @api.update_test(test_id, { :name => new_name }).should == true
60
- single_test = @api.get_test(test_id)
61
- single_test["name"].should == new_name
62
- end
63
- end
64
-
65
- it "should not update a test that is not mine" do
66
- @api = TestingBot::Api.new
67
- lambda { @api.update_test(123423423423423, { :name => "testingbot" }) }.should raise_error(RestClient::NotFound)
68
- end
69
- end
70
-
71
- context "fetch browsers" do
72
- it "should fetch a list of browsers" do
73
- @api = TestingBot::Api.new
74
- @api.get_browsers.should_not be_empty
75
- end
76
- end
77
-
78
- context "delete a test" do
79
- it "should delete a test of mine" do
80
- @api = TestingBot::Api.new
81
- data = @api.get_tests["data"]
82
- if data.length > 0
83
- test_id = data.first["id"]
84
- @api.delete_test(test_id).should == true
85
- lambda { @api.get_test(test_id) }.should raise_error(RestClient::NotFound)
86
- end
87
- end
88
-
89
- it "should not delete a test that is not mine" do
90
- @api = TestingBot::Api.new
91
- lambda { @api.delete_test(123423423423423) }.should raise_error(RestClient::NotFound)
92
- end
93
- end
94
-
95
- context "TestingBot Storage" do
96
- it "should upload a local file" do
97
- @api = TestingBot::Api.new
98
- response = @api.upload_local_file(File.join(File.dirname(__FILE__), "../resources/test.apk"))
99
- response["app_url"].should include("tb://")
100
- end
101
-
102
- it "should upload a remote file" do
103
- @api = TestingBot::Api.new
104
- response = @api.upload_remote_file("https://testingbot.com/appium/sample.apk")
105
- response["app_url"].should include("tb://")
106
- end
107
- end
108
- end
@@ -1 +0,0 @@
1
- ok
data/spec/spec_helper.rb DELETED
@@ -1,7 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../lib/testingbot/api.rb')
2
- require File.expand_path(File.dirname(__FILE__) + '/../lib/testingbot.rb')
3
- RSpec.configure do |config|
4
- config.expect_with :rspec do |expectations|
5
- expectations.syntax = :should
6
- end
7
- end