rainforest 1.0.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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