mno-enterprise-api 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/mno_enterprise/config.js.coffee.erb +8 -0
- data/app/controllers/mno_enterprise/admin/invoices_controller.rb +18 -0
- data/app/controllers/mno_enterprise/impersonate_controller.rb +5 -1
- data/app/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller.rb +9 -0
- data/app/controllers/mno_enterprise/jpi/v1/admin/users_controller.rb +10 -4
- data/app/controllers/mno_enterprise/jpi/v1/audit_events_controller.rb +28 -0
- data/app/controllers/mno_enterprise/jpi/v1/base_resource_controller.rb +1 -1
- data/app/controllers/mno_enterprise/webhook/events_controller.rb +7 -0
- data/app/views/mno_enterprise/auth/confirmations/lounge.html.haml +26 -25
- data/app/views/mno_enterprise/jpi/v1/admin/audit_events/_audit_event.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/admin/audit_events/index.csv.erb +14 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/_invoices.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/admin/organizations/_organization.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/admin/users/show.json.jbuilder +1 -0
- data/app/views/mno_enterprise/jpi/v1/audit_events/_audit_event.json.jbuilder +5 -0
- data/app/views/mno_enterprise/jpi/v1/audit_events/index.csv.erb +12 -0
- data/app/views/mno_enterprise/jpi/v1/audit_events/index.json.jbuilder +4 -0
- data/app/views/mno_enterprise/jpi/v1/current_users/show.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/impac/kpis/_kpi.json.jbuilder +1 -1
- data/app/views/mno_enterprise/jpi/v1/impac/widgets/_widget.json.jbuilder +3 -1
- data/app/views/mno_enterprise/jpi/v1/marketplace/_app.json.jbuilder +10 -1
- data/app/views/mno_enterprise/jpi/v1/organizations/_organization.json.jbuilder +1 -1
- data/app/views/mno_enterprise/webhook/o_auth/authorize.html.haml +1 -1
- data/config/routes.rb +16 -5
- data/lib/mno_enterprise/audit_events_listener.rb +11 -6
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/current_users_controller.rb +6 -1
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/kpis_controller.rb +9 -10
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/impac/widgets_controller.rb +6 -3
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/marketplace_controller.rb +20 -8
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/organizations_controller.rb +12 -0
- data/lib/mno_enterprise/concerns/controllers/jpi/v1/teams_controller.rb +13 -0
- data/lib/mno_enterprise/concerns/controllers/pages_controller.rb +2 -0
- data/lib/mno_enterprise/concerns/controllers/webhook/events_controller.rb +22 -0
- data/lib/mno_enterprise/concerns/controllers/webhook/o_auth_controller.rb +12 -3
- data/lib/mno_enterprise/event_logger.rb +2 -2
- data/lib/mno_enterprise/intercom_events_listener.rb +25 -30
- data/spec/controllers/mno_enterprise/admin/invoices_controller_spec.rb +38 -0
- data/spec/controllers/mno_enterprise/impersonate_controller_spec.rb +6 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/audit_events_controller_spec.rb +9 -0
- data/spec/controllers/mno_enterprise/jpi/v1/admin/organizations_controller_spec.rb +3 -2
- data/spec/controllers/mno_enterprise/jpi/v1/admin/users_controller_spec.rb +2 -1
- data/spec/controllers/mno_enterprise/jpi/v1/audit_events_controller_spec.rb +49 -0
- data/spec/controllers/mno_enterprise/jpi/v1/current_users_controller_spec.rb +16 -0
- data/spec/controllers/mno_enterprise/jpi/v1/impac/kpis_controller_spec.rb +124 -89
- data/spec/controllers/mno_enterprise/jpi/v1/marketplace_controller_spec.rb +83 -36
- data/spec/controllers/mno_enterprise/jpi/v1/organizations_controller_spec.rb +18 -3
- data/spec/controllers/mno_enterprise/org_invites_controller_spec.rb +3 -3
- data/spec/controllers/mno_enterprise/provision_controller_spec.rb +2 -2
- data/spec/controllers/mno_enterprise/webhook/o_auth_controller_spec.rb +1 -1
- data/spec/lib/mno_enterprise/audit_events_listener_spec.rb +11 -0
- data/spec/lib/mno_enterprise/intercom_events_listener_spec.rb +74 -31
- data/spec/routing/devise/registrations_routing_spec.rb +43 -6
- data/spec/routing/mno_enterprise/admin/invoices_controller_routing_spec.rb +11 -0
- data/spec/routing/mno_enterprise/impersonate_controller_routing_spec.rb +30 -4
- data/spec/routing/mno_enterprise/jpi/v1/audit_events_controller_routing_spec.rb +11 -0
- metadata +20 -4
@@ -26,6 +26,12 @@ module MnoEnterprise
|
|
26
26
|
get :create, user_id: user2.id
|
27
27
|
expect(controller.current_user.id).to eq(user2.id)
|
28
28
|
end
|
29
|
+
|
30
|
+
context 'with an organisation id in parameters' do
|
31
|
+
before { get :create, user_id: user.id, dhbRefId: 10 }
|
32
|
+
|
33
|
+
it { is_expected.to redirect_to('/dashboard/#!?dhbRefId=10') }
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
37
|
describe "#destroy" do
|
@@ -35,6 +35,15 @@ module MnoEnterprise
|
|
35
35
|
expect(response).to render_template :index
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
context 'csv' do
|
40
|
+
before { request.env["HTTP_ACCEPT"] = 'text/csv' }
|
41
|
+
|
42
|
+
it 'renders the :index view' do
|
43
|
+
subject
|
44
|
+
expect(response).to render_template :index
|
45
|
+
end
|
46
|
+
end
|
38
47
|
end
|
39
48
|
end
|
40
49
|
end
|
@@ -67,7 +67,8 @@ module MnoEnterprise
|
|
67
67
|
'name' => organization.name,
|
68
68
|
'soa_enabled' => organization.soa_enabled,
|
69
69
|
'created_at' => organization.created_at,
|
70
|
-
'credit_card' => {'presence' => organization.credit_card?}
|
70
|
+
'credit_card' => {'presence' => organization.credit_card?},
|
71
|
+
'account_frozen' => organization.account_frozen
|
71
72
|
}],
|
72
73
|
'metadata' => {'pagination' => {'count' => 1}}
|
73
74
|
}
|
@@ -138,7 +139,7 @@ module MnoEnterprise
|
|
138
139
|
end
|
139
140
|
|
140
141
|
it 'provision the app instances' do
|
141
|
-
params
|
142
|
+
params[:app_nids] = ['xero', app_instance.app.nid]
|
142
143
|
|
143
144
|
# Track the API call
|
144
145
|
create = false
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
module MnoEnterprise
|
4
|
+
describe Jpi::V1::AuditEventsController, type: :controller do
|
5
|
+
include MnoEnterprise::TestingSupport::JpiV1TestHelper
|
6
|
+
|
7
|
+
render_views
|
8
|
+
routes { MnoEnterprise::Engine.routes }
|
9
|
+
before { request.env["HTTP_ACCEPT"] = 'application/json' }
|
10
|
+
|
11
|
+
#===============================================
|
12
|
+
# Assignments
|
13
|
+
#===============================================
|
14
|
+
# Stub controller ability
|
15
|
+
let!(:ability) { stub_ability }
|
16
|
+
before { allow(ability).to receive(:can?).with(any_args).and_return(true) }
|
17
|
+
|
18
|
+
# Stub user and mnoe API calls
|
19
|
+
let(:user) { FactoryGirl.build(:user, :with_organizations) }
|
20
|
+
let(:organization) { user.organizations.first }
|
21
|
+
let(:audit_event) { FactoryGirl.build(:audit_event) }
|
22
|
+
|
23
|
+
before do
|
24
|
+
api_stub_for(get: "/users/#{user.id}", response: from_api(user))
|
25
|
+
api_stub_for(get: "/users/#{user.id}/organizations", response: from_api([organization]))
|
26
|
+
api_stub_for(get: "/organizations/#{organization.id}", response: from_api(organization))
|
27
|
+
api_stub_for(get: '/audit_events', response: from_api([audit_event]))
|
28
|
+
sign_in user
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'GET #index' do
|
32
|
+
subject { get :index, organization_id: organization.id }
|
33
|
+
|
34
|
+
it_behaves_like "jpi v1 protected action"
|
35
|
+
|
36
|
+
context 'sucess' do
|
37
|
+
it 'assigns @audit_events' do
|
38
|
+
subject
|
39
|
+
expect(assigns(:audit_events).to_a).to eq([audit_event])
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'renders the :index view' do
|
43
|
+
subject
|
44
|
+
expect(response).to render_template :index
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -63,9 +63,21 @@ module MnoEnterprise
|
|
63
63
|
hash
|
64
64
|
end
|
65
65
|
|
66
|
+
shared_examples "a user management action" do
|
67
|
+
context 'when Organization management is disabled' do
|
68
|
+
before { Settings.merge!(user_management: {enabled: false}) }
|
69
|
+
before { sign_in user }
|
70
|
+
after { Settings.reload! }
|
71
|
+
|
72
|
+
it { is_expected.to have_http_status(:forbidden) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
66
76
|
# Stub user retrieval
|
67
77
|
let!(:user) { build(:user, :with_deletion_request, :with_organizations, :kpi_enabled) }
|
68
78
|
before { api_stub_for(get: "/users/#{user.id}", response: from_api(user)) }
|
79
|
+
before { api_stub_for(get: "/users/#{user.id}/organizations?filter%5Baccount_frozen%5D=false", response: from_api(user.organizations)) }
|
80
|
+
|
69
81
|
|
70
82
|
describe "GET #show" do
|
71
83
|
subject { get :show }
|
@@ -103,6 +115,8 @@ module MnoEnterprise
|
|
103
115
|
|
104
116
|
subject { put :update, user: attrs }
|
105
117
|
|
118
|
+
it_behaves_like 'a user management action'
|
119
|
+
|
106
120
|
describe 'guest' do
|
107
121
|
before { subject }
|
108
122
|
it { expect(response).to_not be_success }
|
@@ -132,6 +146,8 @@ module MnoEnterprise
|
|
132
146
|
|
133
147
|
subject { put :update_password, user: attrs }
|
134
148
|
|
149
|
+
it_behaves_like 'a user management action'
|
150
|
+
|
135
151
|
describe 'guest' do
|
136
152
|
before { subject }
|
137
153
|
it { expect(response).to_not be_success }
|
@@ -24,7 +24,9 @@ module MnoEnterprise
|
|
24
24
|
before { allow_any_instance_of(MnoEnterprise::Impac::Dashboard).to receive(:owner).and_return(user) }
|
25
25
|
|
26
26
|
let(:kpi_targets) { { evolution: [{max: "20"}] } }
|
27
|
-
let(:
|
27
|
+
let(:settings) { {} }
|
28
|
+
let(:extra_params) { [] }
|
29
|
+
let(:kpi) { build(:impac_kpi, dashboard: dashboard, targets: kpi_targets, settings: settings, extra_params: extra_params) }
|
28
30
|
let(:kpi_hash) { from_api(kpi)[:data].except(:dashboard) }
|
29
31
|
|
30
32
|
let(:alert) { build(:impac_alert, kpi: kpi) }
|
@@ -56,7 +58,7 @@ module MnoEnterprise
|
|
56
58
|
before { allow(MnoEnterprise).to receive(:tenant_id).and_return(auth[:username]) }
|
57
59
|
before { allow(MnoEnterprise).to receive(:tenant_key).and_return(auth[:password]) }
|
58
60
|
|
59
|
-
it { subject; expect(response
|
61
|
+
it { subject; expect(response).to have_http_status(:ok) }
|
60
62
|
|
61
63
|
it "successfully discovers and customises available kpis" do
|
62
64
|
expect(MnoEnterprise::ImpacClient).to receive(:send_get)
|
@@ -75,131 +77,164 @@ module MnoEnterprise
|
|
75
77
|
end
|
76
78
|
|
77
79
|
describe 'POST #create' do
|
78
|
-
|
79
|
-
let (:kpi_targets) { {} }
|
80
|
+
shared_examples "create kpi action" do
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
82
|
+
it "creates the kpi" do
|
83
|
+
subject
|
84
|
+
expect(assigns(:kpi)).to eq(kpi)
|
85
|
+
end
|
89
86
|
|
90
|
-
|
87
|
+
context "when there are kpi targets" do
|
88
|
+
let(:kpi_targets) { { evolution: [{max: "20"}] } }
|
91
89
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
before do
|
91
|
+
api_stub_for(post: "/users/#{user.id}/alerts", response: from_api(alert))
|
92
|
+
api_stub_for(get: "/users/#{user.id}/alerts", response: from_api({}))
|
93
|
+
end
|
96
94
|
|
97
|
-
|
98
|
-
|
99
|
-
|
95
|
+
it "creates kpi alerts" do
|
96
|
+
subject
|
97
|
+
expect(assigns(:kpi).alerts).to eq([alert])
|
98
|
+
expect(response).to have_http_status(:ok)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it { subject; expect(response).to have_http_status(:ok) }
|
100
103
|
end
|
101
104
|
|
102
|
-
|
103
|
-
|
105
|
+
let (:kpi_targets) { {} }
|
106
|
+
|
107
|
+
context "a dashboard KPI" do
|
108
|
+
subject { post :create, dashboard_id: dashboard.id, kpi: kpi_hash }
|
104
109
|
|
105
110
|
before do
|
106
|
-
api_stub_for(
|
107
|
-
api_stub_for(
|
111
|
+
api_stub_for(get: "/dashboards/#{dashboard.id}", response: from_api(dashboard))
|
112
|
+
api_stub_for(post: "/dashboards/#{dashboard.id}/kpis", response: from_api(kpi))
|
113
|
+
api_stub_for(get: "/dashboards/#{dashboard.id}/kpis", response: from_api([]))
|
114
|
+
api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi)) # kpi.reload
|
115
|
+
# TODO: this call should not happen as alerts should be wrapped into the kpi object
|
116
|
+
api_stub_for(get: "/kpis/#{kpi.id}/alerts", response: from_api(alerts_hashes))
|
108
117
|
end
|
109
118
|
|
110
|
-
|
119
|
+
it_behaves_like "jpi v1 authorizable action"
|
120
|
+
|
121
|
+
it_behaves_like "create kpi action"
|
122
|
+
|
123
|
+
it ".dashboard retrieves the correct dashboard" do
|
111
124
|
subject
|
112
|
-
expect(assigns(:
|
113
|
-
expect(response.code).to eq('200')
|
125
|
+
expect(assigns(:dashboard)).to eq(dashboard)
|
114
126
|
end
|
115
127
|
end
|
116
128
|
|
117
|
-
|
118
|
-
|
129
|
+
context "a widget KPI" do
|
130
|
+
let(:widget) { build(:impac_widget) }
|
131
|
+
subject { post :create, dashboard_id: dashboard.id, kpi: kpi_hash.merge(widget_id: widget.id) }
|
119
132
|
|
120
|
-
|
121
|
-
|
122
|
-
|
133
|
+
before do
|
134
|
+
api_stub_for(get: "/widgets/#{widget.id}", response: from_api(widget))
|
135
|
+
api_stub_for(post: "/widgets/#{widget.id}/kpis", response: from_api(kpi))
|
136
|
+
api_stub_for(get: "/widgets/#{widget.id}/kpis", response: from_api([]))
|
137
|
+
api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi)) # kpi.reload
|
138
|
+
# TODO: this call should not happen as alerts should be wrapped into the kpi object
|
139
|
+
api_stub_for(get: "/kpis/#{kpi.id}/alerts", response: from_api(alerts_hashes))
|
140
|
+
end
|
123
141
|
|
124
|
-
|
142
|
+
it_behaves_like "jpi v1 authorizable action"
|
125
143
|
|
126
|
-
|
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
|
144
|
+
it_behaves_like "create kpi action"
|
131
145
|
|
132
|
-
|
146
|
+
it ".widget retrieves the correct widget" do
|
147
|
+
subject
|
148
|
+
expect(assigns(:widget)).to eq(widget)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
133
152
|
|
134
|
-
|
153
|
+
describe 'PUT #update' do
|
154
|
+
RSpec.shared_examples 'a kpi update action' do
|
155
|
+
it "updates the kpi" do
|
156
|
+
subject
|
157
|
+
expect(assigns(:kpi).element_watched).to eq('New Watchable')
|
158
|
+
expect(response).to have_http_status(:ok)
|
159
|
+
end
|
135
160
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
expect(response.code).to eq('200')
|
140
|
-
end
|
161
|
+
context "target set for the first time" do
|
162
|
+
let(:kpi_targets) { nil }
|
163
|
+
let(:params) { { targets: {evolution: [{max:'20'}]} } }
|
141
164
|
|
142
|
-
|
143
|
-
|
144
|
-
|
165
|
+
before do
|
166
|
+
api_stub_for(post: "/users/#{user.id}/alerts", response: from_api(alert))
|
167
|
+
api_stub_for(get: "/users/#{user.id}/alerts", response: from_api({}))
|
168
|
+
end
|
145
169
|
|
146
|
-
|
147
|
-
|
148
|
-
|
170
|
+
it "creates an alert" do
|
171
|
+
subject
|
172
|
+
expect(assigns(:kpi).alerts).to eq([alert])
|
173
|
+
expect(response).to have_http_status(:ok)
|
174
|
+
end
|
149
175
|
end
|
150
176
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
177
|
+
context "when targets have changed" do
|
178
|
+
let(:alert) { build(:impac_alert, kpi: kpi, sent: true) }
|
179
|
+
let(:params) { { targets: {evolution: [{max:'30'}]} } }
|
180
|
+
|
181
|
+
before { api_stub_for(put: "/alerts/#{alert.id}", response: from_api({})) }
|
182
|
+
|
183
|
+
it "updates the sent status of all the kpi's alerts" do
|
184
|
+
subject
|
185
|
+
expect(assigns(:kpi).alerts).to eq([alert])
|
186
|
+
expect(response).to have_http_status(:ok)
|
187
|
+
end
|
155
188
|
end
|
156
|
-
end
|
157
189
|
|
158
|
-
|
159
|
-
|
160
|
-
|
190
|
+
context "when no targets are given / targets are nil" do
|
191
|
+
let(:settings) { { currency: 'GBP' } }
|
192
|
+
let(:params) { { targets: nil } }
|
161
193
|
|
162
|
-
|
194
|
+
it "does not remove the kpi targets" do
|
195
|
+
subject
|
196
|
+
expect(assigns(:kpi).targets).to eq(kpi_targets.deep_stringify_keys)
|
197
|
+
expect(response).to have_http_status(:ok)
|
198
|
+
end
|
199
|
+
end
|
163
200
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
201
|
+
context "when no extra_params are given / extra_params are nil" do
|
202
|
+
let(:settings) { { currency: 'GBP' } }
|
203
|
+
let(:extra_params) { ['some-param'] }
|
204
|
+
let(:params) { { extra_params: nil } }
|
205
|
+
|
206
|
+
it "does not remove the kpi extra_params" do
|
207
|
+
subject
|
208
|
+
expect(assigns(:kpi).extra_params).to eq(['some-param'])
|
209
|
+
expect(response).to have_http_status(:ok)
|
210
|
+
end
|
168
211
|
end
|
169
212
|
end
|
170
213
|
|
171
|
-
|
172
|
-
|
173
|
-
let(:params) { { targets: {} } }
|
214
|
+
let(:kpi_hash) { from_api(kpi)[:data].except(:dashboard).merge(element_watched: 'New Watchable') }
|
215
|
+
let(:params) { {} }
|
174
216
|
|
175
|
-
|
217
|
+
subject { put :update, id: kpi.id, kpi: kpi_hash.merge(params) }
|
176
218
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
219
|
+
before do
|
220
|
+
api_stub_for(get: "/kpis/#{kpi.id}", response: from_api(kpi))
|
221
|
+
api_stub_for(put: "/kpis/#{kpi.id}", response: kpi_hash)
|
222
|
+
api_stub_for(get: "/kpis/#{kpi.id}/alerts", response: from_api(alerts_hashes))
|
181
223
|
end
|
182
224
|
|
183
|
-
|
184
|
-
let(:kpi) { build(:impac_kpi, dashboard: dashboard, targets: kpi_targets, settings: { currency: 'GBP' }) }
|
185
|
-
let(:params) { { targets: nil } }
|
225
|
+
before { kpi.save }
|
186
226
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
expect(response.code).to eq('200')
|
191
|
-
end
|
227
|
+
context "a dashboard KPI" do
|
228
|
+
it_behaves_like "jpi v1 authorizable action"
|
229
|
+
it_behaves_like "a kpi update action"
|
192
230
|
end
|
193
231
|
|
194
|
-
context "
|
195
|
-
let(:
|
196
|
-
let(:
|
232
|
+
context "a widget KPI" do
|
233
|
+
let(:widget) { build(:impac_widget) }
|
234
|
+
let(:kpi) { build(:impac_kpi, widget: widget, targets: kpi_targets, settings: settings, extra_params: extra_params) }
|
197
235
|
|
198
|
-
|
199
|
-
|
200
|
-
expect(assigns(:kpi).extra_params).to eq(['some-param'])
|
201
|
-
expect(response.code).to eq('200')
|
202
|
-
end
|
236
|
+
it_behaves_like "jpi v1 authorizable action"
|
237
|
+
it_behaves_like "a kpi update action"
|
203
238
|
end
|
204
239
|
end
|
205
240
|
|
@@ -211,7 +246,7 @@ module MnoEnterprise
|
|
211
246
|
|
212
247
|
it_behaves_like "jpi v1 authorizable action"
|
213
248
|
|
214
|
-
it { expect(response
|
249
|
+
it { expect(response).to have_http_status(:ok) }
|
215
250
|
end
|
216
251
|
end
|
217
252
|
end
|
@@ -31,13 +31,19 @@ module MnoEnterprise
|
|
31
31
|
'single_billing' => app.single_billing?,
|
32
32
|
'tiny_description' => app.tiny_description,
|
33
33
|
'description' => markdown(app.sanitized_description),
|
34
|
+
'known_limitations' => markdown(app.known_limitations),
|
35
|
+
'getting_started' => markdown(app.getting_started),
|
34
36
|
'testimonials' => app.testimonials,
|
35
37
|
'pictures' => app.pictures,
|
36
38
|
'pricing_plans' => app.pricing_plans,
|
37
39
|
'rank' => app.rank,
|
40
|
+
'support_url' => app.support_url,
|
41
|
+
'key_workflows' => app.key_workflows,
|
42
|
+
'key_features' => app.key_features,
|
38
43
|
'multi_instantiable' => app.multi_instantiable,
|
39
44
|
'subcategories' => app.subcategories,
|
40
45
|
'average_rating' => app.average_rating,
|
46
|
+
'add_on' => app.add_on?,
|
41
47
|
'running_instances_count' => app.running_instances_count
|
42
48
|
}
|
43
49
|
end
|
@@ -72,6 +78,8 @@ module MnoEnterprise
|
|
72
78
|
params: { filter: { 'nid.in' => MnoEnterprise.marketplace_listing } },
|
73
79
|
response: from_api([app])
|
74
80
|
)
|
81
|
+
# TODO: Shouldn't need to stub this
|
82
|
+
api_stub_for(get: "/apps/#{app.id}/shared_entities", response: from_api([]))
|
75
83
|
end
|
76
84
|
|
77
85
|
it { is_expected.to be_success }
|
@@ -86,6 +94,8 @@ module MnoEnterprise
|
|
86
94
|
before do
|
87
95
|
MnoEnterprise.marketplace_listing = nil
|
88
96
|
api_stub_for(get: '/apps', response: from_api([app]))
|
97
|
+
# TODO: Shouldn't need to stub this
|
98
|
+
api_stub_for(get: "/apps/#{app.id}/shared_entities", response: from_api([]))
|
89
99
|
end
|
90
100
|
|
91
101
|
it { is_expected.to be_success }
|
@@ -94,55 +104,92 @@ module MnoEnterprise
|
|
94
104
|
subject
|
95
105
|
expect(JSON.parse(response.body)).to eq(JSON.parse(hash_for_apps([app]).to_json))
|
96
106
|
end
|
97
|
-
end
|
98
|
-
end
|
99
107
|
|
100
|
-
|
101
|
-
|
102
|
-
|
108
|
+
context 'with multiple apps' do
|
109
|
+
let(:app1) { build(:app, rank: 5 ) }
|
110
|
+
let(:app2) { build(:app, rank: 0 ) }
|
111
|
+
|
112
|
+
before do
|
113
|
+
api_stub_for(get: '/apps', response: from_api([app1, app2]))
|
114
|
+
# TODO: Shouldn't need to stub this
|
115
|
+
api_stub_for(get: "/apps/#{app1.id}/shared_entities", response: from_api([]))
|
116
|
+
api_stub_for(get: "/apps/#{app2.id}/shared_entities", response: from_api([]))
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'returns the apps in the correct order' do
|
120
|
+
subject
|
121
|
+
expect(assigns(:apps)).to eq([app2, app1])
|
122
|
+
end
|
123
|
+
end
|
103
124
|
|
104
|
-
|
125
|
+
context 'when multiples apps and a nil rank' do
|
126
|
+
let(:app1) { build(:app, rank: 5 ) }
|
127
|
+
let(:app2) { build(:app, rank: 0 ) }
|
128
|
+
let(:app3) { build(:app, rank: nil ) }
|
129
|
+
|
130
|
+
before do
|
131
|
+
api_stub_for(get: '/apps', response: from_api([app1, app3, app2]))
|
132
|
+
# TODO: Shouldn't need to stub this
|
133
|
+
api_stub_for(get: "/apps/#{app1.id}/shared_entities", response: from_api([]))
|
134
|
+
api_stub_for(get: "/apps/#{app2.id}/shared_entities", response: from_api([]))
|
135
|
+
api_stub_for(get: "/apps/#{app3.id}/shared_entities", response: from_api([]))
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'returns the apps in the correct order' do
|
139
|
+
subject
|
140
|
+
expect(assigns(:apps)).to eq([app2, app1, app3])
|
141
|
+
end
|
142
|
+
end
|
105
143
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
110
|
-
end
|
144
|
+
describe 'caching' do
|
145
|
+
context 'on the first request' do
|
146
|
+
it { is_expected.to have_http_status(:ok) }
|
111
147
|
|
112
|
-
|
113
|
-
|
148
|
+
it 'sets the correct cache headers' do
|
149
|
+
subject
|
150
|
+
header = response.headers['Last-Modified']
|
114
151
|
|
115
|
-
|
116
|
-
let(:app1) { build(:app, rank: 5 ) }
|
117
|
-
let(:app2) { build(:app, rank: 0 ) }
|
152
|
+
expect(header).to be_present
|
118
153
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
154
|
+
# Parse and serialise to get correct format and avoid ms difference
|
155
|
+
expect(Time.rfc822(header).in_time_zone.to_s).to eq(app.updated_at.to_s)
|
156
|
+
end
|
157
|
+
end
|
123
158
|
|
124
|
-
|
159
|
+
context 'on a subsequent request' do
|
125
160
|
|
126
|
-
|
127
|
-
|
128
|
-
|
161
|
+
before do
|
162
|
+
request.env['HTTP_IF_MODIFIED_SINCE'] = last_modified.rfc2822
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'if it is not stale' do
|
166
|
+
# Can't be based on the previous request due to parsing and rounding issues with ms
|
167
|
+
let(:last_modified) { app.updated_at + 10.minutes }
|
168
|
+
it { is_expected.to have_http_status(:not_modified) }
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'if it is stale' do
|
172
|
+
let(:last_modified) { app.updated_at - 10.minutes }
|
173
|
+
it { is_expected.to have_http_status(:ok) }
|
174
|
+
end
|
175
|
+
end
|
129
176
|
end
|
130
177
|
end
|
178
|
+
end
|
131
179
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
180
|
+
describe 'GET #show' do
|
181
|
+
before do
|
182
|
+
api_stub_for(get: "/apps/#{app.id}", response: from_api(app))
|
183
|
+
# TODO: Shouldn't need to stub this
|
184
|
+
api_stub_for(get: "/apps/#{app.id}/shared_entities", response: from_api([]))
|
185
|
+
end
|
186
|
+
subject { get :show, id: app.id }
|
136
187
|
|
137
|
-
|
138
|
-
MnoEnterprise.marketplace_listing = nil
|
139
|
-
api_stub_for(get: '/apps', response: from_api([app1,app3,app2]))
|
140
|
-
end
|
188
|
+
it { is_expected.to be_success }
|
141
189
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
end
|
190
|
+
it 'returns the right response' do
|
191
|
+
subject
|
192
|
+
expect(JSON.parse(response.body)).to eq(JSON.parse(hash_for_app(app).to_json))
|
146
193
|
end
|
147
194
|
end
|
148
195
|
end
|