mno-enterprise-api 3.1.4 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mno_enterprise/config.js.coffee.erb +7 -1
  3. data/app/controllers/mno_enterprise/auth/omniauth_callbacks_controller.rb +3 -27
  4. data/app/controllers/mno_enterprise/auth/sessions_controller.rb +1 -3
  5. data/app/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller.rb +26 -0
  6. data/app/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller.rb +28 -0
  7. data/app/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller.rb +16 -0
  8. data/app/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller.rb +30 -0
  9. data/app/controllers/mno_enterprise/jpi/v1/admin/invites_controller.rb +1 -1
  10. data/app/controllers/mno_enterprise/jpi/v1/admin/organizations_controller.rb +55 -37
  11. data/app/controllers/mno_enterprise/jpi/v1/app_answers_controller.rb +22 -0
  12. data/app/controllers/mno_enterprise/jpi/v1/app_comments_controller.rb +22 -0
  13. data/app/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller.rb +14 -0
  14. data/app/controllers/mno_enterprise/jpi/v1/app_instances_controller.rb +1 -20
  15. data/app/controllers/mno_enterprise/jpi/v1/app_questions_controller.rb +25 -0
  16. data/app/controllers/mno_enterprise/jpi/v1/app_reviews_controller.rb +94 -0
  17. data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +12 -0
  18. data/app/controllers/mno_enterprise/jpi/v1/impac/alerts_controller.rb +5 -0
  19. data/app/controllers/mno_enterprise/jpi/v1/impac/kpis_controller.rb +1 -76
  20. data/app/controllers/mno_enterprise/jpi/v1/marketplace_controller.rb +1 -18
  21. data/app/controllers/mno_enterprise/jpi/v1/teams_controller.rb +1 -83
  22. data/app/jobs/mno_enterprise/event_logger_job.rb +10 -0
  23. data/app/views/mno_enterprise/auth/confirmations/new.html.haml +6 -6
  24. data/app/views/mno_enterprise/auth/passwords/new.html.haml +8 -8
  25. data/app/views/mno_enterprise/auth/registrations/new.html.haml +1 -0
  26. data/app/views/mno_enterprise/auth/sessions/new.html.haml +1 -0
  27. data/app/views/mno_enterprise/auth/shared/_links.html.haml +0 -5
  28. data/app/views/mno_enterprise/auth/shared/_omniauth.html.haml +10 -0
  29. data/app/views/mno_enterprise/jpi/v1/admin/app_answers/show.json.jbuilder +15 -0
  30. data/app/views/mno_enterprise/jpi/v1/admin/app_comments/show.json.jbuilder +15 -0
  31. data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/_app_review.json.jbuilder +13 -0
  32. data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/index.json.jbuilder +1 -0
  33. data/app/views/mno_enterprise/jpi/v1/admin/app_reviews/show.json.jbuilder +3 -0
  34. data/app/views/mno_enterprise/jpi/v1/admin/organizations/show.json.jbuilder +1 -0
  35. data/app/views/mno_enterprise/jpi/v1/admin/users/_user.json.jbuilder +1 -1
  36. data/app/views/mno_enterprise/jpi/v1/app_answers/_resource.json.jbuilder +4 -0
  37. data/app/views/mno_enterprise/jpi/v1/app_answers/index.json.jbuilder +5 -0
  38. data/app/views/mno_enterprise/jpi/v1/app_answers/show.json.jbuilder +3 -0
  39. data/app/views/mno_enterprise/jpi/v1/app_comments/_resource.json.jbuilder +3 -0
  40. data/app/views/mno_enterprise/jpi/v1/app_comments/index.json.jbuilder +5 -0
  41. data/app/views/mno_enterprise/jpi/v1/app_comments/show.json.jbuilder +3 -0
  42. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_comment.json.jbuilder +10 -0
  43. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/_resource.json.jbuilder +7 -0
  44. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/index.json.jbuilder +5 -0
  45. data/app/views/mno_enterprise/jpi/v1/app_feedbacks/show.json.jbuilder +4 -0
  46. data/app/views/mno_enterprise/jpi/v1/app_instances/_resource.json.jbuilder +9 -0
  47. data/app/views/mno_enterprise/jpi/v1/app_questions/_answer.json.jbuilder +3 -0
  48. data/app/views/mno_enterprise/jpi/v1/app_questions/_resource.json.jbuilder +8 -0
  49. data/app/views/mno_enterprise/jpi/v1/app_questions/index.json.jbuilder +5 -0
  50. data/app/views/mno_enterprise/jpi/v1/app_questions/show.json.jbuilder +3 -0
  51. data/app/views/mno_enterprise/jpi/v1/app_reviews/_resource.json.jbuilder +13 -0
  52. data/app/views/mno_enterprise/jpi/v1/app_reviews/index.json.jbuilder +5 -0
  53. data/app/views/mno_enterprise/jpi/v1/app_reviews/show.json.jbuilder +4 -0
  54. data/app/views/mno_enterprise/jpi/v1/base_resource/_app_review.json.jbuilder +17 -0
  55. data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +9 -1
  56. data/app/views/mno_enterprise/jpi/v1/impac/alerts/_alert.json.jbuilder +7 -0
  57. data/app/views/mno_enterprise/jpi/v1/impac/alerts/index.json.jbuilder +1 -0
  58. data/app/views/mno_enterprise/jpi/v1/impac/alerts/show.json.jbuilder +1 -0
  59. data/app/views/mno_enterprise/jpi/v1/impac/dashboards/_dashboard.json.jbuilder +8 -3
  60. data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +4 -1
  61. data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +1 -1
  62. data/app/views/mno_enterprise/jpi/v1/impac/widgets/index.json.jbuilder +3 -0
  63. data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +4 -0
  64. data/app/views/mno_enterprise/jpi/v1/marketplace/index.json.jbuilder +1 -2
  65. data/app/views/mno_enterprise/jpi/v1/marketplace/show.json.jbuilder +1 -1
  66. data/app/views/mno_enterprise/jpi/v1/organizations/_current_user.json.jbuilder +1 -1
  67. data/app/views/mno_enterprise/jpi/v1/organizations/_invoices.json.jbuilder +3 -2
  68. data/app/views/mno_enterprise/jpi/v1/organizations/_member.json.jbuilder +2 -2
  69. data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +2 -2
  70. data/app/views/mno_enterprise/jpi/v1/teams/_team.json.jbuilder +11 -5
  71. data/app/views/mno_enterprise/pages/terms.html.haml +219 -0
  72. data/app/views/mno_enterprise/provision/_select_organization.html.haml +6 -2
  73. data/config/initializers/devise.rb +31 -9
  74. data/config/initializers/devise_log.rb +4 -4
  75. data/config/routes.rb +41 -6
  76. data/lib/mno_enterprise/api.rb +1 -0
  77. data/lib/mno_enterprise/audit_events_listener.rb +28 -0
  78. data/lib/mno_enterprise/concerns/controllers/jpi/v1/app_instances_controller.rb +45 -0
  79. data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +14 -4
  80. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/alerts_controller.rb +76 -0
  81. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/dashboards_controller.rb +49 -23
  82. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/kpis_controller.rb +167 -0
  83. data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/widgets_controller.rb +33 -17
  84. data/lib/mno_enterprise/concerns/controllers/jpi/v1/marketplace_controller.rb +32 -0
  85. data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +68 -28
  86. data/lib/mno_enterprise/concerns/controllers/jpi/v1/teams_controller.rb +92 -0
  87. data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +17 -3
  88. data/lib/mno_enterprise/concerns/controllers/provision_controller.rb +17 -2
  89. data/lib/mno_enterprise/concerns/mailers/system_notification_mailer.rb +27 -3
  90. data/lib/mno_enterprise/event_logger.rb +34 -16
  91. data/lib/mno_enterprise/intercom_events_listener.rb +96 -0
  92. data/spec/controllers/mno_enterprise/auth/confirmation_controller_spec.rb +28 -0
  93. data/spec/controllers/mno_enterprise/auth/omniauth_callback_controller_spec.rb +34 -0
  94. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_answers_controller_spec.rb +45 -0
  95. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_comments_controller_spec.rb +45 -0
  96. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_instances_controller_spec.rb +31 -0
  97. data/spec/controllers/mno_enterprise/jpi/v1/admin/app_reviews_controller_spec.rb +103 -0
  98. data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +4 -15
  99. data/spec/controllers/mno_enterprise/jpi/v1/admin/cloud_apps_controller_spec.rb +12 -3
  100. data/spec/controllers/mno_enterprise/jpi/v1/admin/invites_controller_spec.rb +4 -0
  101. data/spec/controllers/mno_enterprise/jpi/v1/admin/invoices_controller_spec.rb +15 -0
  102. data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +17 -1
  103. data/spec/controllers/mno_enterprise/jpi/v1/admin/tenant_invoices_controller_spec.rb +5 -0
  104. data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +30 -16
  105. data/spec/controllers/mno_enterprise/jpi/v1/app_answers_controller_spec.rb +74 -0
  106. data/spec/controllers/mno_enterprise/jpi/v1/app_comments_controller_spec.rb +74 -0
  107. data/spec/controllers/mno_enterprise/jpi/v1/app_feedbacks_controller_spec.rb +84 -0
  108. data/spec/controllers/mno_enterprise/jpi/v1/app_instances_controller_spec.rb +36 -22
  109. data/spec/controllers/mno_enterprise/jpi/v1/app_questions_controller_spec.rb +80 -0
  110. data/spec/controllers/mno_enterprise/jpi/v1/app_reviews_controller_spec.rb +107 -0
  111. data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +16 -1
  112. data/spec/controllers/mno_enterprise/jpi/v1/impac/alerts_controller_spec.rb +82 -0
  113. data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +147 -10
  114. data/spec/controllers/mno_enterprise/jpi/v1/impac/widgets_controller_spec.rb +39 -0
  115. data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +19 -26
  116. data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +248 -303
  117. data/spec/controllers/mno_enterprise/jpi/v1/team_controller_spec.rb +4 -1
  118. data/spec/controllers/mno_enterprise/pages_controller_spec.rb +21 -0
  119. data/spec/controllers/mno_enterprise/provision_controller_spec.rb +65 -22
  120. data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +1 -1
  121. data/spec/jobs/mno_enterprise/event_logger_job_spec.rb +11 -0
  122. data/spec/lib/mno_enterprise/audit_events_listener_spec.rb +28 -0
  123. data/spec/lib/mno_enterprise/intercom_events_listener_spec.rb +110 -0
  124. data/spec/mailer/mno_enterprise/system_notification_mailer_spec.rb +81 -46
  125. data/spec/routing/mno_enterprise/jpi/v1/admin/app_instances_controller_routing_spec.rb +11 -0
  126. data/spec/routing/mno_enterprise/jpi/v1/admin/app_reviews_controller_routing_spec.rb +19 -0
  127. data/spec/routing/mno_enterprise/jpi/v1/app_instances_controller_routing_spec.rb +9 -2
  128. data/spec/routing/mno_enterprise/jpi/v1/app_reviews_controller_routing_spec.rb +15 -0
  129. data/spec/routing/mno_enterprise/jpi/v1/current_users_controller_routing_spec.rb +5 -0
  130. data/spec/routing/mno_enterprise/jpi/v1/impac/alerts_controller_routing_spec.rb +24 -0
  131. data/spec/routing/mno_enterprise/jpi/v1/impac/dashboards_controller_routing_spec.rb +28 -0
  132. data/spec/routing/mno_enterprise/jpi/v1/impac/kpis_controller_routing_spec.rb +17 -11
  133. data/spec/routing/mno_enterprise/jpi/v1/impac/widgets_controller_routing_spec.rb +24 -0
  134. data/spec/routing/mno_enterprise/jpi/v1/marketplace_controller_routing_spec.rb +2 -2
  135. data/spec/routing/mno_enterprise/pages_controller_routing_spec.rb +4 -0
  136. metadata +178 -9
  137. data/app/controllers/mno_enterprise/jpi/v1/industry_bundle_controller.rb +0 -25
  138. data/app/controllers/mno_enterprise/jpi/v1/shopping_cart_controller.rb +0 -93
  139. data/spec/lib/mno_enterprise/event_logger_spec.rb +0 -28
@@ -0,0 +1,80 @@
1
+ require 'rails_helper'
2
+
3
+ module MnoEnterprise
4
+ describe Jpi::V1::AppQuestionsController, type: :controller do
5
+ include MnoEnterprise::TestingSupport::JpiV1TestHelper
6
+ render_views
7
+ routes { MnoEnterprise::Engine.routes }
8
+ before { request.env["HTTP_ACCEPT"] = 'application/json' }
9
+
10
+
11
+ #===============================================
12
+ # Assignments
13
+ #===============================================
14
+ let(:user) { build(:user) }
15
+ before { api_stub_for(get: "/users/#{user.id}", response: from_api(user)) }
16
+ before { sign_in user }
17
+
18
+ let(:app) { build(:app) }
19
+ let(:question_answer_1) { build(:app_answer) }
20
+ let(:question_answer_2) { build(:app_answer) }
21
+ let(:app_question) { build(:app_question, answers: [question_answer_1, question_answer_2]) }
22
+ let(:expected_hash_for_answer_1) do
23
+ attrs = %w(id description status user_id user_name organization_id organization_name app_id question_id app_name user_admin_role edited edited_by_name edited_by_admin_role edited_by_id)
24
+ question_answer_1.attributes.slice(*attrs).merge({'created_at' => question_answer_1.created_at.as_json, 'updated_at' => question_answer_1.updated_at.as_json})
25
+ end
26
+ let(:expected_hash_for_answer_2) do
27
+ attrs = %w(id description status user_id user_name organization_id organization_name app_id question_id app_name user_admin_role edited edited_by_name edited_by_admin_role edited_by_id)
28
+ question_answer_2.attributes.slice(*attrs).merge({'created_at' => question_answer_2.created_at.as_json, 'updated_at' => question_answer_2.updated_at.as_json})
29
+ end
30
+ let(:expected_array_for_answers) { [expected_hash_for_answer_1, expected_hash_for_answer_2] }
31
+ let(:expected_hash_for_question) do
32
+ attrs = %w(id description status user_id user_name organization_id organization_name app_id app_name user_admin_role answers edited edited_by_name edited_by_admin_role edited_by_id)
33
+ app_question.attributes.slice(*attrs).merge({'created_at' => app_question.created_at.as_json, 'updated_at' => app_question.updated_at.as_json, 'answers' => expected_array_for_answers})
34
+ end
35
+ let(:expected_hash_for_questions) do
36
+ {
37
+ 'app_questions' => [expected_hash_for_question],
38
+ }
39
+ end
40
+
41
+ before do
42
+ api_stub_for(get: "/apps/#{app.id}", response: from_api(app))
43
+ end
44
+
45
+ describe 'GET #index' do
46
+
47
+ before do
48
+ api_stub_for(get: "/app_questions?filter[reviewable_id]=#{app.id}", response: from_api([app_question]))
49
+ end
50
+
51
+ subject { get :index, id: app.id }
52
+
53
+ it_behaves_like "jpi v1 protected action"
54
+
55
+ it_behaves_like "a paginated action"
56
+
57
+ it 'renders the list of reviews' do
58
+ subject
59
+ expect(JSON.parse(response.body)).to eq(expected_hash_for_questions)
60
+ end
61
+ end
62
+
63
+ describe 'POST #create', focus: true do
64
+ let(:params) { {organization_id: 1, description: 'A Review', foo: 'bar'} }
65
+
66
+ before do
67
+ api_stub_for(post: "/app_questions", response: from_api(app_question))
68
+ api_stub_for(get: "/app_questions/#{app_question.id}", response: from_api(app_question))
69
+ end
70
+
71
+ subject { post :create, id: app.id, app_question: params }
72
+
73
+ it_behaves_like "jpi v1 protected action"
74
+
75
+ it 'renders the new review' do
76
+ expect(JSON.parse(subject.body)).to include('app_question' => expected_hash_for_question)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,107 @@
1
+ require 'rails_helper'
2
+
3
+ module MnoEnterprise
4
+ describe Jpi::V1::AppReviewsController, type: :controller do
5
+ include MnoEnterprise::TestingSupport::JpiV1TestHelper
6
+ render_views
7
+ routes { MnoEnterprise::Engine.routes }
8
+ before { request.env["HTTP_ACCEPT"] = 'application/json' }
9
+
10
+
11
+ #===============================================
12
+ # Assignments
13
+ #===============================================
14
+ let(:user) { build(:user) }
15
+ before { api_stub_for(get: "/users/#{user.id}", response: from_api(user)) }
16
+ before { sign_in user }
17
+
18
+ let(:app) { build(:app) }
19
+ let(:app_review) { build(:app_review) }
20
+ let(:expected_hash_for_review) do
21
+ attrs = %w(id rating description status user_id user_name organization_id organization_name app_id app_name json.user_admin_role user_admin_role edited edited_by_name edited_by_admin_role edited_by_id)
22
+ app_review.attributes.slice(*attrs).merge({'created_at' => app_review.created_at.as_json, 'updated_at' => app_review.updated_at.as_json})
23
+ end
24
+ let(:expected_hash_for_reviews) do
25
+ {
26
+ 'app_reviews' => [expected_hash_for_review],
27
+ }
28
+ end
29
+
30
+ before do
31
+ api_stub_for(get: "/apps/#{app.id}", response: from_api(app))
32
+ end
33
+
34
+ describe 'GET #index' do
35
+
36
+ before do
37
+ api_stub_for(get: "/app_reviews?filter[reviewable_id]=#{app.id}", response: from_api([app_review]))
38
+ end
39
+
40
+ subject { get :index, id: app.id }
41
+
42
+ it_behaves_like "jpi v1 protected action"
43
+
44
+ it_behaves_like "a paginated action"
45
+
46
+ it 'renders the list of reviews' do
47
+ subject
48
+ expect(JSON.parse(response.body)).to eq(expected_hash_for_reviews)
49
+ end
50
+ end
51
+
52
+ describe 'POST #create', focus: true do
53
+ let(:params) { {organization_id: 1, description: 'A Review', rating: 5, foo: 'bar'} }
54
+ let(:app_review) { build(:app_review) }
55
+
56
+ before do
57
+ api_stub_for(post: "/app_reviews", response: from_api(app_review))
58
+ api_stub_for(get: "/app_reviews/#{app_review.id}", response: from_api(app_review))
59
+ end
60
+
61
+ subject { post :create, id: app.id, app_review: params }
62
+
63
+ it_behaves_like "jpi v1 protected action"
64
+
65
+ it 'renders the new review' do
66
+ expect(JSON.parse(subject.body)).to include('app_review' => expected_hash_for_review)
67
+ end
68
+
69
+ it 'renders the new average rating' do
70
+ expect(JSON.parse(subject.body)).to include('average_rating' => app.average_rating)
71
+ end
72
+ end
73
+
74
+ describe 'PATCH #update', focus: true do
75
+ let(:params) { {description: 'A Review 2', rating: 1} }
76
+ let(:app_review) { build(:app_review, user_id: user.id) }
77
+
78
+ before do
79
+ api_stub_for(put: "/app_reviews/#{app_review.id}", response: from_api(app_review))
80
+ api_stub_for(get: "/app_reviews/#{app_review.id}", response: from_api(app_review))
81
+ end
82
+
83
+ subject { put :update, id: app.id, review_id: app_review.id, app_review: params }
84
+
85
+ it 'renders the new review' do
86
+ expect(JSON.parse(subject.body)).to include('app_review' => expected_hash_for_review)
87
+ expect(JSON.parse(subject.body)).to include('average_rating' => app.average_rating)
88
+ end
89
+ end
90
+
91
+ describe 'DELETE #destroy', focus: true do
92
+ let(:app_review) { build(:app_review, user_id: user.id) }
93
+
94
+ before do
95
+ api_stub_for(delete: "/app_reviews/#{app_review.id}", response: from_api(app_review))
96
+ api_stub_for(get: "/app_reviews/#{app_review.id}", response: from_api(app_review))
97
+ end
98
+
99
+ subject { delete :destroy, id: app.id, review_id: app_review.id }
100
+
101
+ it 'renders the new review' do
102
+ expect(JSON.parse(subject.body)).to include('app_review' => expected_hash_for_review)
103
+ expect(JSON.parse(subject.body)).to include('average_rating' => app.average_rating)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -26,6 +26,8 @@ module MnoEnterprise
26
26
  'created_at' => res.created_at ? res.created_at.iso8601 : nil,
27
27
  'company' => res.company,
28
28
  'phone' => res.phone,
29
+ 'api_secret' => res.api_secret,
30
+ 'api_key' => res.api_key,
29
31
  'phone_country_code' => res.phone_country_code,
30
32
  'country_code' => res.geo_country_code || 'US',
31
33
  'website' => res.website,
@@ -54,13 +56,15 @@ module MnoEnterprise
54
56
  'token' => res.deletion_request.token
55
57
  }
56
58
  end
59
+
60
+ hash['kpi_enabled'] = !!res.kpi_enabled
57
61
  end
58
62
 
59
63
  hash
60
64
  end
61
65
 
62
66
  # Stub user retrieval
63
- let!(:user) { build(:user, :with_deletion_request, :with_organizations) }
67
+ let!(:user) { build(:user, :with_deletion_request, :with_organizations, :kpi_enabled) }
64
68
  before { api_stub_for(get: "/users/#{user.id}", response: from_api(user)) }
65
69
 
66
70
  describe "GET #show" do
@@ -111,6 +115,17 @@ module MnoEnterprise
111
115
  end
112
116
  end
113
117
 
118
+ describe 'PUT #register_developer' do
119
+ before { api_stub_for(put: "/users/#{user.id}", response: from_api(user)) }
120
+ before { sign_in user }
121
+ subject { put :register_developer}
122
+
123
+ describe 'logged in' do
124
+ before { subject }
125
+ it { expect(response).to be_success }
126
+ end
127
+ end
128
+
114
129
  describe 'PUT #update_password' do
115
130
  let(:attrs) { {current_password: 'password', password: 'blablabla', password_confirmation: 'blablabla'} }
116
131
  before { api_stub_for(put: "/users/#{user.id}", response: from_api(user)) }
@@ -0,0 +1,82 @@
1
+ require 'rails_helper'
2
+
3
+ module MnoEnterprise
4
+ describe Jpi::V1::Impac::AlertsController, type: :controller do
5
+ include MnoEnterprise::TestingSupport::JpiV1TestHelper
6
+ render_views
7
+ routes { MnoEnterprise::Engine.routes }
8
+ before { request.env["HTTP_ACCEPT"] = 'application/json' }
9
+
10
+ # Stub ability
11
+ let!(:ability) { stub_ability }
12
+ before { allow(ability).to receive(:can?).with(any_args).and_return(true) }
13
+
14
+ # Stub user and user call
15
+ let!(:user) { build(:user) }
16
+ before { api_stub_for(get: "/users/#{user.id}", response: from_api(user)) }
17
+ before { sign_in user }
18
+
19
+ let(:kpi) { build(:impac_kpi) }
20
+ let(:alert) { build(:impac_alert, kpi: kpi) }
21
+ let(:alert_hash) { from_api(alert)[:data].except(:kpi) }
22
+
23
+ describe 'GET #index' do
24
+ before { api_stub_for(get: "/users/#{user.id}/alerts", response: from_api([alert])) }
25
+ subject { get :index }
26
+ end
27
+
28
+ describe 'POST #create' do
29
+ before { api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi)) }
30
+ before { api_stub_for(post: "/users/#{user.id}/alerts", response: from_api(alert)) }
31
+ before { api_stub_for(get: "/users/#{user.id}/alerts", response: from_api([])) }
32
+
33
+ subject { post :create, kpi_id: kpi.id, alert: alert_hash }
34
+
35
+ it_behaves_like "jpi v1 authorizable action"
36
+
37
+ it "creates and assigns the alert" do
38
+ subject
39
+ expect(assigns(:alert)).to eq(alert)
40
+ end
41
+
42
+ it "attaches the alert to the kpi" do
43
+ subject
44
+ expect(assigns(:alert).kpi).to eq(kpi)
45
+ end
46
+
47
+ it { subject; expect(response.code).to eq('200') }
48
+ end
49
+
50
+ describe 'PUT #update' do
51
+ let(:update_alert_hash) { {title: 'test', webhook: 'test', sent: true, forbidden: 'test'} }
52
+ let(:updated_alert) { build(:impac_alert, kpi: kpi, title: 'test', webhook: 'test', sent: true) }
53
+
54
+ before { api_stub_for(get: "/alerts/#{alert.id}", response: from_api(alert)) }
55
+ before { api_stub_for(put: "/alerts/#{alert.id}", response: from_api(updated_alert)) }
56
+
57
+ subject { put :update, id: alert.id, alert: update_alert_hash }
58
+
59
+ it_behaves_like "jpi v1 authorizable action"
60
+
61
+ it "assigns the alert" do
62
+ subject
63
+ expect(assigns(:alert)).to eq(updated_alert)
64
+ end
65
+
66
+ it { subject; expect(response.code).to eq('200') }
67
+ end
68
+
69
+ describe 'DELETE #destroy' do
70
+ before { api_stub_for(get: "/alerts/#{alert.id}", response: from_api(alert)) }
71
+ before { api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi)) }
72
+ before { api_stub_for(delete: "/alerts/#{alert.id}", response: from_api([])) }
73
+
74
+ subject { delete :destroy, id: alert.id }
75
+
76
+ it_behaves_like "jpi v1 authorizable action"
77
+
78
+ it { subject; expect(response.code).to eq('200') }
79
+ it { subject; expect(JSON.parse(response.body)).to eq({"deleted" => {"service" => alert.service}}) }
80
+ end
81
+ end
82
+ end
@@ -17,18 +17,76 @@ module MnoEnterprise
17
17
  before { sign_in user }
18
18
 
19
19
  let(:dashboard) { build(:impac_dashboard) }
20
+
21
+ # TODO KPI DISABLED TEST CASES
22
+
23
+ # Stub the dashboard owner
20
24
  before { allow_any_instance_of(MnoEnterprise::Impac::Dashboard).to receive(:owner).and_return(user) }
21
- before { api_stub_for(get: "/dashboards/#{dashboard.id}", response: from_api(dashboard)) }
22
25
 
23
- let(:kpi) { build(:impac_kpi, dashboard: dashboard) }
26
+ let(:kpi_targets) { { evolution: [{max: "20"}] } }
27
+ let(:kpi) { build(:impac_kpi, dashboard: dashboard, targets: kpi_targets) }
24
28
  let(:kpi_hash) { from_api(kpi)[:data].except(:dashboard) }
25
29
 
26
- before { api_stub_for(post: "/dashboards/#{dashboard.id}/kpis", response: from_api(kpi)) }
27
- before { api_stub_for(get: "/dashboards/#{dashboard.id}/kpis", response: from_api([])) }
30
+ let(:alert) { build(:impac_alert, kpi: kpi) }
31
+ let(:alerts_hashes) { [from_api(alert)[:data]] }
32
+
33
+ describe 'GET index' do
34
+ let(:params) { { 'metadata' => {'organization_ids' => ['some_id']}, 'opts' => {'some' => 'opts'} } }
35
+ subject { get :index, metadata: params['metadata'], opts: params['opts'] }
28
36
 
37
+ let(:impac_available_kpis) do
38
+ [
39
+ {"name"=>"Debtor Due Days", "endpoint"=>"invoicing/due_days/debtor", "watchables"=>["max", "average"], "attachables"=>nil, "target_placeholders"=>{"max"=>{"mode"=>"max", "value"=>90, "unit"=>"days"}, "average"=>{"mode"=>"max", "value"=>30, "unit"=>"days"}}},
40
+ {"name"=>"Account Balance", "endpoint"=>"accounting/balance", "watchables"=>["balance"], "attachables"=>["accounts/balance"], "target_placeholders"=>{"balance"=>{"mode"=>"min", "value"=>15000, "unit"=>"currency"}}}
41
+ ]
42
+ end
43
+
44
+ let(:expected_result) do
45
+ {
46
+ "kpis" => [
47
+ {"name"=>"Debtor Due Days Max", "endpoint"=>"invoicing/due_days/debtor", "watchables"=>["max"], "attachables"=>nil, "target_placeholders"=>{"max"=>{"mode"=>"max", "value"=>90, "unit"=>"days"}}},
48
+ {"name"=>"Debtor Due Days Average", "endpoint"=>"invoicing/due_days/debtor", "watchables"=>["average"], "attachables"=>nil, "target_placeholders"=>{"average"=>{"mode"=>"max", "value"=>30, "unit"=>"days"}}},
49
+ {"name"=>"Account Balance", "endpoint"=>"accounting/balance", "watchables"=>["balance"], "attachables"=>["accounts/balance"], "target_placeholders"=>{"balance"=>{"mode"=>"min", "value"=>15000, "unit"=>"currency"}}},
50
+ ]
51
+ }
52
+ end
53
+
54
+ let(:auth) { { username: 'username', password: 'password' } }
55
+ before { allow(MnoEnterprise::ImpacClient).to receive(:send_get).with('/api/v2/kpis', params, basic_auth: auth).and_return('kpis' => impac_available_kpis) }
56
+ before { allow(MnoEnterprise).to receive(:tenant_id).and_return(auth[:username]) }
57
+ before { allow(MnoEnterprise).to receive(:tenant_key).and_return(auth[:password]) }
58
+
59
+ it { subject; expect(response.code).to eq('200') }
60
+
61
+ it "successfully discovers and customises available kpis" do
62
+ expect(MnoEnterprise::ImpacClient).to receive(:send_get)
63
+ subject
64
+ expect(JSON.parse(response.body)).to eq(expected_result)
65
+ end
66
+
67
+ context "when impac api request raises an error" do
68
+ before { allow(MnoEnterprise::ImpacClient).to receive(:send_get).and_raise }
69
+
70
+ it "rescues responding with an error message" do
71
+ subject
72
+ expect(JSON.parse(response.body)).to include('message')
73
+ end
74
+ end
75
+ end
29
76
 
30
77
  describe 'POST #create' do
31
78
  subject { post :create, dashboard_id: dashboard.id, kpi: kpi_hash }
79
+ let (:kpi_targets) { {} }
80
+
81
+ before do
82
+ api_stub_for(get: "/dashboards/#{dashboard.id}", response: from_api(dashboard))
83
+ api_stub_for(post: "/dashboards/#{dashboard.id}/kpis", response: from_api(kpi))
84
+ api_stub_for(get: "/dashboards/#{dashboard.id}/kpis", response: from_api([]))
85
+ api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi)) # kpi.reload
86
+ # TODO: this call should not happen as alerts should be wrapped into the kpi object
87
+ api_stub_for(get: "/kpis/#{kpi.id}/alerts", response: from_api(alerts_hashes))
88
+ end
89
+
32
90
  it_behaves_like "jpi v1 authorizable action"
33
91
 
34
92
  it ".dashboard retrieves the correct dashboard" do
@@ -41,17 +99,35 @@ module MnoEnterprise
41
99
  expect(assigns(:kpi)).to eq(kpi)
42
100
  end
43
101
 
102
+ context "when there are kpi targets" do
103
+ let(:kpi_targets) { { evolution: [{max: "20"}] } }
104
+
105
+ before do
106
+ api_stub_for(post: "/users/#{user.id}/alerts", response: from_api(alert))
107
+ api_stub_for(get: "/users/#{user.id}/alerts", response: from_api({}))
108
+ end
109
+
110
+ it "creates kpi alerts" do
111
+ subject
112
+ expect(assigns(:kpi).alerts).to eq([alert])
113
+ expect(response.code).to eq('200')
114
+ end
115
+ end
116
+
44
117
  it { subject; expect(response.code).to eq('200') }
45
- it { subject; expect(JSON.parse(response.body)).to eq(kpi_hash) }
46
118
  end
47
119
 
48
120
  describe 'PUT #update' do
49
121
  let(:kpi_hash) { from_api(kpi)[:data].except(:dashboard).merge(element_watched: 'New Watchable') }
122
+ let(:params) { {} }
50
123
 
51
- subject { put :update, id: kpi.id, kpi: kpi_hash }
124
+ subject { put :update, id: kpi.id, kpi: kpi_hash.merge(params) }
52
125
 
53
- before { api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi)) }
54
- before { api_stub_for(put: "/kpis/#{kpi.id}", response: kpi_hash) }
126
+ before do
127
+ api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi))
128
+ api_stub_for(put: "/kpis/#{kpi.id}", response: kpi_hash)
129
+ api_stub_for(get: "/kpis/#{kpi.id}/alerts", response: from_api(alerts_hashes))
130
+ end
55
131
 
56
132
  before { kpi.save }
57
133
 
@@ -60,10 +136,71 @@ module MnoEnterprise
60
136
  it "updates the kpi" do
61
137
  subject
62
138
  expect(assigns(:kpi).element_watched).to eq('New Watchable')
139
+ expect(response.code).to eq('200')
63
140
  end
64
141
 
65
- it { subject; expect(response.code).to eq('200') }
66
- it { subject; expect(JSON.parse(response.body)).to eq(kpi_hash) }
142
+ context "target set for the first time" do
143
+ let(:kpi_targets) { nil }
144
+ let(:params) { { targets: {evolution: [{max:'20'}]} } }
145
+
146
+ before do
147
+ api_stub_for(post: "/users/#{user.id}/alerts", response: from_api(alert))
148
+ api_stub_for(get: "/users/#{user.id}/alerts", response: from_api({}))
149
+ end
150
+
151
+ it "creates an alert" do
152
+ subject
153
+ expect(assigns(:kpi).alerts).to eq([alert])
154
+ expect(response.code).to eq('200')
155
+ end
156
+ end
157
+
158
+ context "when targets have changed" do
159
+ let(:alert) { build(:impac_alert, kpi: kpi, sent: true) }
160
+ let(:params) { { targets: {evolution: [{max:'30'}]} } }
161
+
162
+ before { api_stub_for(put: "/alerts/#{alert.id}", response: from_api({})) }
163
+
164
+ it "updates the sent status of all the kpi's alerts" do
165
+ subject
166
+ expect(assigns(:kpi).alerts).to eq([alert])
167
+ expect(response.code).to eq('200')
168
+ end
169
+ end
170
+
171
+ context "when a kpi has no targets, nor is being updated with any" do
172
+ let(:kpi_targets) { nil }
173
+ let(:params) { { targets: {} } }
174
+
175
+ before { api_stub_for(delete: "/alerts/#{alert.id}", response: from_api({})) }
176
+
177
+ it "destroys the kpi's alerts" do
178
+ subject
179
+ expect(response.code).to eq('200')
180
+ end
181
+ end
182
+
183
+ context "when no targets are given / targets are nil" do
184
+ let(:kpi) { build(:impac_kpi, dashboard: dashboard, targets: kpi_targets, settings: { currency: 'GBP' }) }
185
+ let(:params) { { targets: nil } }
186
+
187
+ it "does not remove the kpi targets" do
188
+ subject
189
+ expect(assigns(:kpi).targets).to eq(kpi_targets.deep_stringify_keys)
190
+ expect(response.code).to eq('200')
191
+ end
192
+ end
193
+
194
+ context "when no extra_params are given / extra_params are nil" do
195
+ let(:kpi) { build(:impac_kpi, dashboard: dashboard, targets: kpi_targets, extra_params: ['some-param'], settings: { currency: 'GBP' }) }
196
+ let(:params) { { extra_params: nil } }
197
+
198
+ it "does not remove the kpi extra_params" do
199
+ subject
200
+ expect(assigns(:kpi).extra_params).to eq(['some-param'])
201
+ expect(response.code).to eq('200')
202
+ end
203
+ end
67
204
  end
68
205
 
69
206
  describe 'DELETE #destroy' do