rainforest 1.0.7 → 2.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -6
  3. data/.travis.yml +13 -1
  4. data/Gemfile +6 -0
  5. data/README.md +72 -21
  6. data/Rakefile +6 -13
  7. data/VERSION +1 -1
  8. data/bin/rainforest-console +1 -1
  9. data/gemfiles/default-with-activesupport.gemfile +8 -1
  10. data/gemfiles/json.gemfile +10 -2
  11. data/gemfiles/yajl.gemfile +10 -2
  12. data/lib/rainforest.rb +61 -240
  13. data/lib/rainforest/apibits/api_client.rb +28 -0
  14. data/lib/rainforest/apibits/api_endpoint.rb +11 -0
  15. data/lib/rainforest/apibits/api_list.rb +88 -0
  16. data/lib/rainforest/apibits/api_method.rb +95 -0
  17. data/lib/rainforest/apibits/api_object.rb +52 -0
  18. data/lib/rainforest/apibits/api_resource.rb +153 -0
  19. data/lib/rainforest/apibits/headers_builder.rb +47 -0
  20. data/lib/rainforest/apibits/params_builder.rb +27 -0
  21. data/lib/rainforest/apibits/path_builder.rb +38 -0
  22. data/lib/rainforest/apibits/requester.rb +104 -0
  23. data/lib/rainforest/apibits/util.rb +51 -0
  24. data/lib/rainforest/clients/default_client.rb +59 -0
  25. data/lib/rainforest/endpoints/client_stats_endpoint.rb +11 -0
  26. data/lib/rainforest/endpoints/environment_runs_endpoint.rb +11 -0
  27. data/lib/rainforest/endpoints/environments_endpoint.rb +48 -0
  28. data/lib/rainforest/endpoints/generator_rows_endpoint.rb +17 -0
  29. data/lib/rainforest/endpoints/generators_endpoint.rb +48 -0
  30. data/lib/rainforest/endpoints/integrations_endpoint.rb +33 -0
  31. data/lib/rainforest/endpoints/run_tests_endpoint.rb +20 -0
  32. data/lib/rainforest/endpoints/runs_endpoint.rb +48 -0
  33. data/lib/rainforest/endpoints/schedules_endpoint.rb +48 -0
  34. data/lib/rainforest/endpoints/site_environments_endpoint.rb +24 -0
  35. data/lib/rainforest/endpoints/sites_endpoint.rb +39 -0
  36. data/lib/rainforest/endpoints/tests_endpoint.rb +57 -0
  37. data/lib/rainforest/endpoints/users_endpoint.rb +48 -0
  38. data/lib/rainforest/errors/api_connection_error.rb +1 -1
  39. data/lib/rainforest/errors/api_error.rb +32 -1
  40. data/lib/rainforest/errors/authentication_error.rb +1 -1
  41. data/lib/rainforest/errors/rainforest_error.rb +2 -9
  42. data/lib/rainforest/resources/client_stats.rb +31 -0
  43. data/lib/rainforest/resources/environment.rb +73 -0
  44. data/lib/rainforest/resources/generator.rb +73 -0
  45. data/lib/rainforest/resources/integration.rb +52 -0
  46. data/lib/rainforest/resources/run.rb +93 -0
  47. data/lib/rainforest/resources/schedule.rb +63 -0
  48. data/lib/rainforest/resources/site.rb +53 -0
  49. data/lib/rainforest/resources/site_environment.rb +40 -0
  50. data/lib/rainforest/resources/test.rb +98 -0
  51. data/lib/rainforest/resources/user.rb +75 -0
  52. data/rainforest.gemspec +8 -6
  53. data/test/rainforest/api_client_test.rb +51 -0
  54. data/test/rainforest/api_endpoint_test.rb +13 -0
  55. data/test/rainforest/api_list_test.rb +49 -0
  56. data/test/rainforest/api_method_test.rb +78 -0
  57. data/test/rainforest/headers_builder_test.rb +28 -0
  58. data/test/rainforest/params_builder_test.rb +57 -0
  59. data/test/rainforest/path_builder_test.rb +50 -0
  60. data/test/rainforest/requester_test.rb +86 -0
  61. data/test/rainforest/util_test.rb +41 -19
  62. data/test/test_data.rb +72 -0
  63. data/test/test_helper.rb +17 -134
  64. metadata +99 -59
  65. data/CONTRIBUTORS +0 -2
  66. data/History.txt +0 -4
  67. data/LICENSE +0 -21
  68. data/lib/data/ca-certificates.crt +0 -3918
  69. data/lib/rainforest/api_operations/create.rb +0 -16
  70. data/lib/rainforest/api_operations/delete.rb +0 -11
  71. data/lib/rainforest/api_operations/list.rb +0 -16
  72. data/lib/rainforest/api_operations/update.rb +0 -61
  73. data/lib/rainforest/api_resource.rb +0 -33
  74. data/lib/rainforest/errors/invalid_request_error.rb +0 -10
  75. data/lib/rainforest/json.rb +0 -21
  76. data/lib/rainforest/list_object.rb +0 -35
  77. data/lib/rainforest/rainforest_object.rb +0 -165
  78. data/lib/rainforest/run.rb +0 -8
  79. data/lib/rainforest/singleton_api_resource.rb +0 -20
  80. data/lib/rainforest/util.rb +0 -100
  81. data/test/rainforest/api_resource_test.rb +0 -11
  82. data/test/rainforest/auth_test.rb +0 -24
  83. data/test/rainforest/list_object_test.rb +0 -7
  84. data/test/rainforest/metadata_test.rb +0 -7
  85. data/test/rainforest/run_test.rb +0 -36
@@ -0,0 +1,75 @@
1
+ module Rainforest
2
+ class User < ApiResource
3
+ attr_accessor :analytics_id
4
+ attr_accessor :client_analytics_id
5
+ attr_accessor :created_at
6
+ attr_accessor :email
7
+ attr_accessor :id
8
+ attr_accessor :name
9
+ attr_accessor :profiles
10
+ attr_accessor :role
11
+ attr_accessor :settings
12
+ attr_accessor :state
13
+
14
+ def self.all(params={}, headers={})
15
+ res = client.users.all(params, headers)
16
+ res
17
+ end
18
+
19
+ def self.retrieve(user_id, params={}, headers={})
20
+ res = client.users.retrieve(user_id, params, headers)
21
+ res
22
+ end
23
+
24
+ def self.update(user_id, params={}, headers={})
25
+ res = client.users.update(user_id, params, headers)
26
+ res
27
+ end
28
+
29
+ def self.create(params={}, headers={})
30
+ res = client.users.create(params, headers)
31
+ res
32
+ end
33
+
34
+ def self.reset_password(email, params={}, headers={})
35
+ res = client.users.reset_password(email, params, headers)
36
+ res
37
+ end
38
+
39
+ def refresh(params={}, headers={})
40
+ res = client.users.retrieve(id, params, headers)
41
+ self.refresh_from(res.json, res.api_method, res.client)
42
+ end
43
+
44
+ def update(params={}, headers={})
45
+ res = client.users.update(id, params, headers)
46
+ self.refresh_from(res.json, res.api_method, res.client)
47
+ end
48
+
49
+ def save(params={}, headers={})
50
+ params = ParamsBuilder.merge(api_attributes, params)
51
+ res = client.users.update(id, params, headers)
52
+ self.refresh_from(res.json, res.api_method, res.client)
53
+ end
54
+
55
+ def reset_password(params={}, headers={})
56
+ res = client.users.reset_password(email, params, headers)
57
+ res
58
+ end
59
+
60
+ # Everything below here is used behind the scenes.
61
+ ApiResource.register_api_subclass(self, "user")
62
+ @api_attributes = {
63
+ :analytics_id => {},
64
+ :client_analytics_id => {},
65
+ :created_at => {},
66
+ :email => {},
67
+ :id => {},
68
+ :name => {},
69
+ :profiles => {},
70
+ :role => {},
71
+ :settings => {},
72
+ :state => {},
73
+ }
74
+ end
75
+ end
@@ -4,16 +4,17 @@ require 'rainforest/version'
4
4
 
5
5
  spec = Gem::Specification.new do |s|
6
6
  s.name = 'rainforest'
7
+ s.summary = 'Ruby bindings for Rainforest API'
8
+ s.description = 'Rainforest automates your functional and integration testing with our QA-as-a-Service API.'
9
+ s.homepage = 'https://docs.rainfroestqa.com'
10
+ s.authors = ['Apibits.com']
11
+ s.email = ['libraries@apibits.com']
7
12
  s.version = Rainforest::VERSION
8
- s.summary = 'Ruby bindings for the Rainforest API'
9
- s.description = 'Rainforest allows you to create tests for your website in plain English, then run them across all major browsers with a single click. See https://www.rainforestqa.com/ for details.'
10
- s.authors = ['Jon Calhon']
11
- s.email = ['joncalhoun@gmail.com']
12
- s.homepage = 'https://github.com/joncalhoun/rainforest-ruby'
13
13
  s.license = 'MIT'
14
14
 
15
15
  s.add_dependency('rest-client', '~> 1.4')
16
- s.add_dependency('multi_json', '>= 1.0.4', '< 2')
16
+ s.add_dependency('mime-types', '>= 1.25', '< 3.0')
17
+ s.add_dependency('json', '~> 1.8.1')
17
18
 
18
19
  s.add_development_dependency('mocha', '~> 0.13.2')
19
20
  s.add_development_dependency('shoulda', '~> 3.4.0')
@@ -25,3 +26,4 @@ spec = Gem::Specification.new do |s|
25
26
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
27
  s.require_paths = ['lib']
27
28
  end
29
+
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class ApiClientTest < ::Test::Unit::TestCase
5
+ setup do
6
+ @headers = {
7
+ :Accept => "application/json",
8
+ :Authorization => "Fake Auth"
9
+ }
10
+ @params = {
11
+ :customer_id => 123
12
+ }
13
+ @client = ApiClient.new(@headers, @params)
14
+ end
15
+
16
+ context '#execute' do
17
+ setup do
18
+ @api_method = mock
19
+ @api_method.stubs(:headers).returns({
20
+ :fake_header => "fake-header-val"
21
+ })
22
+ @api_method.stubs(:headers=)
23
+ @api_method.stubs(:params).returns({
24
+ :fake_param => "fake-param"
25
+ })
26
+ @api_method.stubs(:params=)
27
+ @api_method.stubs(:execute)
28
+ end
29
+
30
+ should 'merge the client headers and params into the api_method' do
31
+ expected_headers = { :hello => true }
32
+ expected_params = { :goodbye => false }
33
+
34
+ ParamsBuilder.expects(:merge).with(@api_method.headers, @headers).returns(expected_headers)
35
+ ParamsBuilder.expects(:merge).with(@api_method.params, @params).returns(expected_params)
36
+
37
+ @api_method.expects(:headers=).with(expected_headers)
38
+ @api_method.expects(:params=).with(expected_params)
39
+
40
+ @client.execute(@api_method)
41
+ end
42
+
43
+ should 'call api_method.execute and return the results' do
44
+ expected = { :status => "success!" }
45
+ @api_method.expects(:execute).returns(expected)
46
+ assert_equal(expected, @client.execute(@api_method))
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class ApiEndpointTest < ::Test::Unit::TestCase
5
+ context '#initialize' do
6
+ should 'set the client and parent' do
7
+ ep = ApiEndpoint.new("client", "parent")
8
+ assert_equal("client", ep.client)
9
+ assert_equal("parent", ep.parent)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class ApiListTest < ::Test::Unit::TestCase
5
+
6
+ context '#initialize' do
7
+ setup do
8
+ @fake_resource = { :data => "fake-data" }
9
+ @list = ApiList.new(ApiResource, [@fake_resource])
10
+ end
11
+
12
+ should 'set the klass' do
13
+ assert_equal(ApiResource, @list.klass)
14
+ end
15
+
16
+ should 'convert the data to klass instances' do
17
+ assert(@list.first.is_a?(ApiResource))
18
+ assert_equal(@fake_resource, @list.first.json)
19
+ end
20
+ end
21
+
22
+ context '#refresh_from' do
23
+ setup do
24
+ @fake_resource = { :data => "fake-data" }
25
+ @fake_method = "fake-api-method"
26
+ @fake_client = "fake-client"
27
+ @list = ApiList.new(ApiResource, [], "invalid", "invalid")
28
+ end
29
+
30
+ should 'update the api_method' do
31
+ @list.refresh_from([@fake_resource], @fake_method)
32
+ assert_equal(@list.api_method, @fake_method)
33
+ end
34
+
35
+ should 'update the client' do
36
+ @list.refresh_from([@fake_resource], nil, @fake_client)
37
+ assert_equal(@list.client, @fake_client)
38
+ end
39
+
40
+ should 'clear existing data' do
41
+ @list.refresh_from(["new-data"])
42
+
43
+ assert_nil(@list.api_method)
44
+ assert_nil(@list.client)
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,78 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class ApiMethodTest < ::Test::Unit::TestCase
5
+ setup do
6
+ @method = :get
7
+ @path = "/testing"
8
+ @params = { :param_a => "1" }
9
+ @headers = { :header_a => "a" }
10
+ @object = mock
11
+ @api_method = ApiMethod.new(@method, @path, @params, @headers, @object)
12
+ end
13
+
14
+ context '#initialize' do
15
+ should 'set the api_base' do
16
+ assert_equal(Rainforest.api_base, @api_method.api_base)
17
+ end
18
+
19
+ should 'use PathBuilder with path, object, and params' do
20
+ PathBuilder.expects(:build).with(@path, @object, @params).returns(@path)
21
+ ApiMethod.new(@method, @path, @params, @headers, @object)
22
+ end
23
+
24
+ should 'use ParamsBuilder with params' do
25
+ ParamsBuilder.expects(:build).with(@params).returns(@params)
26
+ ApiMethod.new(@method, @path, @params, @headers, @object)
27
+ end
28
+
29
+ should 'use HeadersBuilder with headers, api_key, and nil auth_header' do
30
+ HeadersBuilder.expects(:build).with(@headers).returns(@headers)
31
+ ApiMethod.new(@method, @path, @params, @headers, @object)
32
+ end
33
+ end
34
+
35
+ context '#execute' do
36
+ setup do
37
+ @mock_response = mock
38
+ @mock_response.stubs(:body).returns('{"status": "success"}')
39
+ @mock_response.stubs(:code).returns(200)
40
+ end
41
+
42
+ should 'call Requester.request with the set attrs' do
43
+ Requester.expects(:request).with(@method, @api_method.url, @api_method.params, @api_method.headers).returns(@mock_response)
44
+ @api_method.execute
45
+ end
46
+
47
+ should 'create an ApiError if the request fails' do
48
+ Requester.expects(:request).raises(RestClient::RequestTimeout.new)
49
+
50
+ assert_raises(ApiError) { @api_method.execute }
51
+ end
52
+
53
+ should 'return the response parsed as json' do
54
+ Requester.expects(:request).returns(@mock_response)
55
+ assert_equal({:status => "success"}, @api_method.execute)
56
+ end
57
+
58
+ should 'return an AuthenticationError if the status is 401' do
59
+ error = RestClient::ExceptionWithResponse.new
60
+ error.expects(:http_code).returns(401)
61
+
62
+ Requester.expects(:request).raises(error)
63
+ assert_raises(AuthenticationError) { @api_method.execute }
64
+ end
65
+ end
66
+
67
+ context '#response_json' do
68
+ setup do
69
+ @api_method.response_body = 'not-valid-json'
70
+ end
71
+
72
+ should 'throw an error if the response_body isnt valid json' do
73
+ assert_raises(ApiError) { @api_method.response_json }
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class HeadersBuilderTest < ::Test::Unit::TestCase
5
+
6
+ setup do
7
+ @headers = {
8
+ :dog => "dog-value"
9
+ }
10
+ @built_headers = HeadersBuilder.build(@headers)
11
+ end
12
+
13
+ should 'set the user_agent' do
14
+ assert(@built_headers.has_key?(:user_agent))
15
+ assert(@built_headers[:user_agent].include?(Rainforest::VERSION))
16
+ assert(@built_headers[:user_agent].include?(Rainforest.api_version))
17
+ end
18
+
19
+ should 'set a client user agent' do
20
+ # This can be raw or json encoded depending on various things
21
+ unless @built_headers.has_key?(:x_rainforest_client_user_agent) ||
22
+ @built_headers.has_key?(:x_rainforest_client_raw_user_agent)
23
+ raise "No valid client user agent found"
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class ParamsBuilderTest < ::Test::Unit::TestCase
5
+
6
+ setup do
7
+ @params = {
8
+ :dog => "dog-value",
9
+ "string" => "str-value"
10
+ }
11
+ end
12
+
13
+ context '#clean' do
14
+ setup do
15
+ @built_params = ParamsBuilder.clean(@params)
16
+ end
17
+
18
+ should 'convert keys to symbols' do
19
+ assert(@built_params.has_key?(:string))
20
+ assert_equal(@params["string"], @built_params[:string])
21
+ end
22
+
23
+ should 'not have any string keys' do
24
+ @built_params.each do |k, v|
25
+ assert(k.is_a?(Symbol))
26
+ end
27
+ end
28
+ end
29
+
30
+ context '#merge' do
31
+ setup do
32
+ @to_merge = {
33
+ :string => "other-str-value",
34
+ "cat" => "cat-value"
35
+ }
36
+ @built_params = ParamsBuilder.merge(@params, @to_merge)
37
+ end
38
+
39
+ should 'convert keys to symbols' do
40
+ assert(@built_params.has_key?(:cat))
41
+ assert(@built_params.has_key?(:string))
42
+ assert(!@built_params.has_key?("string"))
43
+ end
44
+
45
+ should 'merge in all values' do
46
+ assert_equal(@params[:dog], @built_params[:dog])
47
+ assert_equal(@to_merge[:string], @built_params[:string])
48
+ assert_equal(@to_merge["cat"], @built_params[:cat])
49
+ end
50
+
51
+ should 'prioritize values in @to_merge' do
52
+ assert_equal(@to_merge[:string], @built_params[:string])
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,50 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class PathBuilderTest < ::Test::Unit::TestCase
5
+ class FakeClass
6
+ def abc; return "abc-value"; end
7
+ def self.xyz; return "xyz-value"; end
8
+ end
9
+
10
+ setup do
11
+ @params = {
12
+ :dog => "dog-value"
13
+ }
14
+ @obj = FakeClass.new
15
+ end
16
+
17
+ should 'use instance methods' do
18
+ path = "/a/:abc/123"
19
+ expected = "/a/abc-value/123"
20
+
21
+ actual = PathBuilder.build(path, @obj, nil)
22
+ assert_equal(expected, actual)
23
+ end
24
+
25
+ should 'use class methods' do
26
+ path = "/a/:xyz/123"
27
+ expected = "/a/xyz-value/123"
28
+
29
+ actual = PathBuilder.build(path, FakeClass, nil)
30
+ assert_equal(expected, actual)
31
+ end
32
+
33
+ should 'use param values' do
34
+ path = "/a/:dog/123"
35
+ expected = "/a/dog-value/123"
36
+
37
+ actual = PathBuilder.build(path, nil, @params)
38
+ assert_equal(expected, actual)
39
+ end
40
+
41
+ should 'use both methods and params' do
42
+ path = "/a/:dog/:abc/123"
43
+ expected = "/a/dog-value/abc-value/123"
44
+
45
+ actual = PathBuilder.build(path, @obj, @params)
46
+ assert_equal(expected, actual)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ module Rainforest
4
+ class RequesterTest < ::Test::Unit::TestCase
5
+ setup do
6
+ end
7
+
8
+ context '#prepare_params' do
9
+ setup do
10
+ @url = "test_url"
11
+ @params = { :a => 1, :b => [2, 3] }
12
+ end
13
+
14
+ should 'convert :get params to a query string' do
15
+ url, params = Requester.prepare_params(:get, @url, @params)
16
+ assert(url != @url)
17
+ assert(params.nil?)
18
+ end
19
+
20
+ should 'convert :delete params to a query string' do
21
+ url, params = Requester.prepare_params(:delete, @url, @params)
22
+ assert(url != @url)
23
+ assert(params.nil?)
24
+ end
25
+
26
+ should 'convert :head params to a query string' do
27
+ url, params = Requester.prepare_params(:head, @url, @params)
28
+ assert(url != @url)
29
+ assert(params.nil?)
30
+ end
31
+
32
+ context 'method = :post' do
33
+ setup do
34
+ @method = :post
35
+ end
36
+
37
+ should 'not convert params to a query string if a file is in them' do
38
+ expected = { file: File.new(__FILE__) }
39
+ url, params = Requester.prepare_params(@method, @url, expected)
40
+ assert_equal(expected, params)
41
+ end
42
+
43
+ should 'convert params to a query string if a file is not present' do
44
+ url, params = Requester.prepare_params(@method, @url, @params)
45
+ assert(params.is_a?(String))
46
+ end
47
+ end
48
+ end
49
+
50
+ context '#query_string' do
51
+ should 'join #query_array results with an "&"' do
52
+ start = { :a => 1, :b => [2, 3] }
53
+ expected = ["a=1", "b[]=2", "b[]=3"]
54
+
55
+ actual = Requester.query_string(start).split('&')
56
+ actual.each do |str|
57
+ assert(expected.include?(str))
58
+ end
59
+ end
60
+ end
61
+
62
+ context '#query_array' do
63
+ should 'convert { :a => "value" } to ["a=value"]' do
64
+ start = { :a => "value" }
65
+ finish = ["a=value"]
66
+
67
+ assert_equal(finish, Requester.query_array(start))
68
+ end
69
+
70
+ should 'convert { :a => { :b => { :c => "cvalue" } } } to ["a[b][c]=cvalue"]' do
71
+ start = { :a => { :b => { :c => "cvalue" } } }
72
+ finish = ["a[b][c]=cvalue"]
73
+
74
+ assert_equal(finish, Requester.query_array(start))
75
+ end
76
+
77
+ should 'convert { :a => [1, 2] } to ["a[]=1", "a[]=2"]' do
78
+ start = { :a => [1, 2] }
79
+ finish = ["a[]=1", "a[]=2"]
80
+
81
+ assert_equal(finish, Requester.query_array(start))
82
+ end
83
+ end
84
+
85
+ end
86
+ end