cangaroo 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.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +32 -0
  4. data/app/controllers/cangaroo/application_controller.rb +4 -0
  5. data/app/controllers/cangaroo/endpoint_controller.rb +49 -0
  6. data/app/interactors/cangaroo/authenticate_connection.rb +19 -0
  7. data/app/interactors/cangaroo/count_json_object.rb +20 -0
  8. data/app/interactors/cangaroo/handle_request.rb +10 -0
  9. data/app/interactors/cangaroo/perform_jobs.rb +31 -0
  10. data/app/interactors/cangaroo/validate_json_schema.rb +31 -0
  11. data/app/jobs/cangaroo/job.rb +63 -0
  12. data/app/models/cangaroo/connection.rb +12 -0
  13. data/config/routes.rb +3 -0
  14. data/db/migrate/20151028172151_create_cangaroo_connections.rb +12 -0
  15. data/db/migrate/20151030140821_add_parameters_to_cangaroo_connection.rb +5 -0
  16. data/lib/cangaroo.rb +10 -0
  17. data/lib/cangaroo/engine.rb +17 -0
  18. data/lib/cangaroo/version.rb +3 -0
  19. data/lib/cangaroo/webhook/client.rb +44 -0
  20. data/lib/cangaroo/webhook/error.rb +6 -0
  21. data/lib/tasks/cangaroo_tasks.rake +4 -0
  22. data/spec/controllers/cangaroo/endpoint_controller_spec.rb +72 -0
  23. data/spec/dummy/README.rdoc +28 -0
  24. data/spec/dummy/Rakefile +6 -0
  25. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  26. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  27. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  28. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  29. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  30. data/spec/dummy/bin/bundle +3 -0
  31. data/spec/dummy/bin/rails +4 -0
  32. data/spec/dummy/bin/rake +4 -0
  33. data/spec/dummy/bin/setup +29 -0
  34. data/spec/dummy/config.ru +4 -0
  35. data/spec/dummy/config/application.rb +31 -0
  36. data/spec/dummy/config/boot.rb +5 -0
  37. data/spec/dummy/config/database.yml +11 -0
  38. data/spec/dummy/config/environment.rb +5 -0
  39. data/spec/dummy/config/environments/development.rb +41 -0
  40. data/spec/dummy/config/environments/production.rb +79 -0
  41. data/spec/dummy/config/environments/test.rb +42 -0
  42. data/spec/dummy/config/initializers/assets.rb +11 -0
  43. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  44. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  45. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  46. data/spec/dummy/config/initializers/inflections.rb +16 -0
  47. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  48. data/spec/dummy/config/initializers/session_store.rb +3 -0
  49. data/spec/dummy/config/initializers/wrap_parameters.rb +9 -0
  50. data/spec/dummy/config/locales/en.yml +23 -0
  51. data/spec/dummy/config/routes.rb +4 -0
  52. data/spec/dummy/config/secrets.yml +22 -0
  53. data/spec/dummy/db/development.sqlite3 +0 -0
  54. data/spec/dummy/db/schema.rb +29 -0
  55. data/spec/dummy/db/test.sqlite3 +0 -0
  56. data/spec/dummy/log/cangaroo.log +0 -0
  57. data/spec/dummy/log/development.log +3466 -0
  58. data/spec/dummy/log/test.log +139640 -0
  59. data/spec/dummy/public/404.html +67 -0
  60. data/spec/dummy/public/422.html +67 -0
  61. data/spec/dummy/public/500.html +66 -0
  62. data/spec/dummy/public/favicon.ico +0 -0
  63. data/spec/factories/cangaroo_connections.rb +9 -0
  64. data/spec/fixtures/json_payload_no_id.json +21 -0
  65. data/spec/fixtures/json_payload_ok.json +22 -0
  66. data/spec/fixtures/json_payload_wrong_key.json +22 -0
  67. data/spec/interactors/cangaroo/authenticate_connection_spec.rb +46 -0
  68. data/spec/interactors/cangaroo/count_json_object_spec.rb +17 -0
  69. data/spec/interactors/cangaroo/handle_request_spec.rb +18 -0
  70. data/spec/interactors/cangaroo/perform_jobs_spec.rb +42 -0
  71. data/spec/interactors/cangaroo/validate_json_schema_spec.rb +51 -0
  72. data/spec/jobs/cangaroo/job_spec.rb +55 -0
  73. data/spec/lib/cangaroo/webhook/client_spec.rb +69 -0
  74. data/spec/models/cangaroo/connection_spec.rb +15 -0
  75. data/spec/rails_helper.rb +85 -0
  76. data/spec/spec_helper.rb +9 -0
  77. data/spec/support/spec_helpers.rb +11 -0
  78. metadata +345 -0
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/404.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The page you were looking for doesn't exist.</h1>
62
+ <p>You may have mistyped the address or the page may have moved.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+ factory :cangaroo_connection, class: 'Cangaroo::Connection' do
3
+ name :store
4
+ url 'www.store.com'
5
+ parameters { { first: 'first', second: 'second' } }
6
+ key '1e4e888ac66f8dd41e00c5a7ac36a32a9950d271'
7
+ token '8d49cddb4291562808bfca1bee8a9f7cf947a987'
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ {
2
+ "orders":[
3
+ {
4
+ "state":"cart"
5
+ },
6
+ {
7
+ "id":"O154085343224",
8
+ "state":"payed"
9
+ }
10
+ ],
11
+ "shipments":[
12
+ {
13
+ "id":"S53454325",
14
+ "state":"shipped"
15
+ },
16
+ {
17
+ "id":"S53565543",
18
+ "state":"waiting"
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "orders":[
3
+ {
4
+ "id":"O154085346172",
5
+ "state":"cart"
6
+ },
7
+ {
8
+ "id":"O154085343224",
9
+ "state":"payed"
10
+ }
11
+ ],
12
+ "shipments":[
13
+ {
14
+ "id":"S53454325",
15
+ "state":"shipped"
16
+ },
17
+ {
18
+ "id":"S53565543",
19
+ "state":"waiting"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "Wrong Key":[
3
+ {
4
+ "id":"O154085346172",
5
+ "state":"cart"
6
+ },
7
+ {
8
+ "id":"O154085343224",
9
+ "state":"payed"
10
+ }
11
+ ],
12
+ "shipments":[
13
+ {
14
+ "id":"S53454325",
15
+ "state":"shipped"
16
+ },
17
+ {
18
+ "id":"S53565543",
19
+ "state":"waiting"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,46 @@
1
+ require 'rails_helper'
2
+
3
+ describe Cangaroo::AuthenticateConnection do
4
+ subject(:context) do
5
+ Cangaroo::AuthenticateConnection.call(key: 'connection_key',
6
+ token: 'secret_token')
7
+ end
8
+
9
+ describe '.call' do
10
+ context 'when given valid credentials' do
11
+ let(:connection) { double(:connection) }
12
+
13
+ before do
14
+ allow(Cangaroo::Connection).to receive(:authenticate)
15
+ .with('connection_key', 'secret_token').and_return(connection)
16
+ end
17
+
18
+ it 'succeeds' do
19
+ expect(context).to be_a_success
20
+ end
21
+
22
+ it 'provides the connection' do
23
+ expect(context.source_connection).to eq(connection)
24
+ end
25
+ end
26
+
27
+ context 'when given invalid credentials' do
28
+ before do
29
+ allow(Cangaroo::Connection).to receive(:authenticate)
30
+ .with('connection_key', 'secret_token').and_return(nil)
31
+ end
32
+
33
+ it 'fails' do
34
+ expect(context).to be_a_failure
35
+ end
36
+
37
+ it 'provides a failure message' do
38
+ expect(context.message).to be_present
39
+ end
40
+
41
+ it 'provides a failure error code' do
42
+ expect(context.error_code).to eq 401
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails_helper'
2
+
3
+ describe Cangaroo::CountJsonObject do
4
+ subject(:context) { Cangaroo::CountJsonObject.call(json_body: json_body) }
5
+
6
+ let(:json_body) { load_fixture('json_payload_ok.json') }
7
+
8
+ describe '.call' do
9
+ it 'provides the object_count' do
10
+ expect(context.object_count).to eq('orders' => 2, 'shipments' => 2)
11
+ end
12
+
13
+ it 'succeeds' do
14
+ expect(context).to be_a_success
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails_helper'
2
+
3
+ describe Cangaroo::HandleRequest do
4
+ subject { described_class.new }
5
+
6
+ context 'organizes interactors' do
7
+ subject { described_class.organized }
8
+
9
+ let(:interactors) do
10
+ [Cangaroo::AuthenticateConnection,
11
+ Cangaroo::ValidateJsonSchema,
12
+ Cangaroo::CountJsonObject,
13
+ Cangaroo::PerformJobs]
14
+ end
15
+
16
+ it { is_expected.to eql interactors }
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ require 'rails_helper'
2
+
3
+ class JobA < Cangaroo::Job; end
4
+ class JobB < Cangaroo::Job; end
5
+
6
+ describe Cangaroo::PerformJobs do
7
+ subject(:context) do
8
+ Cangaroo::PerformJobs.call(json_body: json_body,
9
+ jobs: [JobA, JobB],
10
+ source_connection: connection)
11
+ end
12
+
13
+ let(:connection) { create(:cangaroo_connection) }
14
+
15
+ before do
16
+ allow(JobA).to receive(:new).with(any_args).and_return(job_a)
17
+ allow(JobB).to receive(:new).with(any_args).and_return(job_b)
18
+ end
19
+
20
+ describe '.call' do
21
+ let(:json_body) { load_fixture('json_payload_ok.json') }
22
+
23
+ let(:job_a) { double('job_a', perform?: true, enqueue: nil) }
24
+ let(:job_b) { double('job_b', perform?: false, enqueue: nil) }
25
+
26
+ it 'instantiates jobs' do
27
+ context
28
+ expect(JobA).to have_received(:new).exactly(4).times
29
+ expect(JobB).to have_received(:new).exactly(4).times
30
+ end
31
+
32
+ it 'enqueues only cangaroo jobs that can perform' do
33
+ context
34
+ expect(job_a).to have_received(:enqueue).exactly(4).times
35
+ expect(job_b).to_not have_received(:enqueue)
36
+ end
37
+
38
+ it 'succeeds' do
39
+ expect(context).to be_a_success
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,51 @@
1
+ require 'rails_helper'
2
+
3
+ describe Cangaroo::ValidateJsonSchema do
4
+ subject(:context) { Cangaroo::ValidateJsonSchema.call(json_body: json_body) }
5
+
6
+ describe '.call' do
7
+ context 'when json is well formatted' do
8
+ let(:json_body) { JSON.parse(load_fixture('json_payload_ok.json')) }
9
+
10
+ it 'succeeds' do
11
+ expect(context).to be_a_success
12
+ end
13
+ end
14
+
15
+ context 'when json is not well formatted' do
16
+ describe 'with wrong main key' do
17
+ let(:json_body) do
18
+ JSON.parse(load_fixture('json_payload_wrong_key.json'))
19
+ end
20
+
21
+ it 'fails' do
22
+ expect(context).to be_a_failure
23
+ end
24
+
25
+ it 'provides a failure message' do
26
+ expect(context.message).to be_present
27
+ end
28
+
29
+ it 'provides a failure error code' do
30
+ expect(context.error_code).to eq 500
31
+ end
32
+ end
33
+
34
+ describe 'without an object id' do
35
+ let(:json_body) { JSON.parse(load_fixture('json_payload_no_id.json')) }
36
+
37
+ it 'fails' do
38
+ expect(context).to be_a_failure
39
+ end
40
+
41
+ it 'provides a failure message' do
42
+ expect(context.message).to be_present
43
+ end
44
+
45
+ it 'provides a failure error code' do
46
+ expect(context.error_code).to eq 500
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end