mno-enterprise-api 3.2.1 → 3.3.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.
- 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
|