-
Notifications
You must be signed in to change notification settings - Fork 4.1k
/
client-history-test.js
362 lines (341 loc) · 18 KB
/
client-history-test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
import { module, test } from 'qunit';
import { visit, currentURL, click, settled, find } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
import Pretender from 'pretender';
import authPage from 'vault/tests/pages/auth';
import { addMonths, format, formatRFC3339, startOfMonth, subMonths } from 'date-fns';
import { create } from 'ember-cli-page-object';
import { clickTrigger } from 'ember-power-select/test-support/helpers';
import ss from 'vault/tests/pages/components/search-select';
import {
CHART_ELEMENTS,
generateActivityResponse,
generateConfigResponse,
generateLicenseResponse,
SELECTORS,
sendResponse,
} from '../helpers/clients';
const searchSelect = create(ss);
module('Acceptance | clients history tab', function (hooks) {
setupApplicationTest(hooks);
hooks.beforeEach(function () {
return authPage.login();
});
hooks.afterEach(function () {
this.server.shutdown();
});
test('shows warning when config off, no data, queries available', async function (assert) {
const licenseStart = startOfMonth(subMonths(new Date(), 6));
const licenseEnd = addMonths(new Date(), 6);
const license = generateLicenseResponse(licenseStart, licenseEnd);
const config = generateConfigResponse({ enabled: 'default-disable' });
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(license));
this.get('/v1/sys/internal/counters/activity', () => sendResponse(null, 204));
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () => sendResponse({ keys: [] }));
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/feature-flags', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history');
assert.dom(SELECTORS.historyActiveTab).hasText('History', 'history tab is active');
assert.dom('[data-test-tracking-disabled] .message-title').hasText('Tracking is disabled');
assert.dom(SELECTORS.emptyStateTitle).hasText('No data received');
assert.dom(SELECTORS.filterBar).doesNotExist('Shows filter bar to search previous dates');
assert.dom(SELECTORS.usageStats).doesNotExist('No usage stats');
});
test('shows warning when config off, no data, queries unavailable', async function (assert) {
const licenseStart = startOfMonth(subMonths(new Date(), 6));
const licenseEnd = addMonths(new Date(), 6);
const license = generateLicenseResponse(licenseStart, licenseEnd);
const config = generateConfigResponse({ enabled: 'default-disable', queries_available: false });
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(license));
this.get('/v1/sys/internal/counters/activity', () => sendResponse(null, 204));
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () => sendResponse({ keys: [] }));
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history');
assert.dom(SELECTORS.historyActiveTab).hasText('History', 'history tab is active');
assert.dom(SELECTORS.emptyStateTitle).hasText('Data tracking is disabled');
assert.dom(SELECTORS.filterBar).doesNotExist('Filter bar is hidden when no data available');
});
test('shows empty state when config on and no queries', async function (assert) {
const licenseStart = startOfMonth(subMonths(new Date(), 6));
const licenseEnd = addMonths(new Date(), 6);
const license = generateLicenseResponse(licenseStart, licenseEnd);
const config = generateConfigResponse({ queries_available: false });
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(license));
this.get('/v1/sys/internal/counters/activity', () => sendResponse(null, 204));
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () => sendResponse({ keys: [] }));
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough);
});
// History Tab
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history');
assert.dom(SELECTORS.historyActiveTab).hasText('History', 'history tab is active');
assert.dom(SELECTORS.emptyStateTitle).hasText('No monthly history');
assert.dom(SELECTORS.filterBar).doesNotExist('Does not show filter bar');
});
test('visiting history tab config on and data with mounts', async function (assert) {
assert.expect(25);
const licenseStart = startOfMonth(subMonths(new Date(), 6));
const licenseEnd = addMonths(new Date(), 6);
const lastMonth = addMonths(new Date(), -1);
const license = generateLicenseResponse(licenseStart, licenseEnd);
const config = generateConfigResponse();
const activity = generateActivityResponse(5, licenseStart, lastMonth);
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(license));
this.get('/v1/sys/internal/counters/activity', () => sendResponse(activity));
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () => sendResponse({ keys: [] }));
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history');
assert
.dom(SELECTORS.dateDisplay)
.hasText(format(licenseStart, 'MMMM yyyy'), 'billing start month is correctly parsed from license');
assert
.dom(SELECTORS.rangeDropdown)
.hasText(
`${format(licenseStart, 'MMMM yyyy')} - ${format(lastMonth, 'MMMM yyyy')}`,
'Date range shows dates correctly parsed activity response'
);
assert.dom('[data-test-stat-text-container]').exists({ count: 3 }, '3 stat texts exist');
const { by_namespace } = activity.data;
const { clients, entity_clients, non_entity_clients } = activity.data.total;
assert
.dom('[data-test-stat-text="total-clients"] .stat-value')
.hasText(clients.toString(), 'total clients stat is correct');
assert
.dom('[data-test-stat-text="entity-clients"] .stat-value')
.hasText(entity_clients.toString(), 'entity clients stat is correct');
assert
.dom('[data-test-stat-text="non-entity-clients"] .stat-value')
.hasText(non_entity_clients.toString(), 'non-entity clients stat is correct');
assert.dom('[data-test-clients-attribution]').exists('Shows attribution area');
assert.dom('[data-test-top-attribution]').includesText('Top namespace');
// TODO CMB - add assertion so double charts show for single historical month
// TODO and check for empty state there
// assert
// .dom('[data-test-chart-container="new-clients"] [data-test-empty-state-subtext]')
// .includesText(
// 'There are no new clients for this namespace during this time period.',
// 'Shows empty state if no new client counts'
// );
// check chart displays correct elements and values
for (const key in CHART_ELEMENTS) {
let namespaceNumber = by_namespace.length < 10 ? by_namespace.length : 10;
let group = find(CHART_ELEMENTS[key]);
let elementArray = Array.from(group.children);
assert.equal(elementArray.length, namespaceNumber, `renders correct number of ${key}`);
if (key === 'totalValues') {
elementArray.forEach((element, i) => {
assert.equal(element.innerHTML, `${by_namespace[i].counts.clients}`, 'displays correct value');
});
}
if (key === 'yLabels') {
elementArray.forEach((element, i) => {
assert
.dom(element.children[1])
.hasTextContaining(`${by_namespace[i].namespace_path}`, 'displays correct namespace label');
});
}
}
});
// flaky test -- does not consistently run the same number of assertions
// refactor before using assert.expect
test('filters correctly on history with full data', async function (assert) {
/* eslint qunit/require-expect: "warn" */
// assert.expect(44);
const licenseStart = startOfMonth(subMonths(new Date(), 6));
const licenseEnd = addMonths(new Date(), 6);
const lastMonth = addMonths(new Date(), -1);
const config = generateConfigResponse();
const activity = generateActivityResponse(5, licenseStart, lastMonth);
const license = generateLicenseResponse(licenseStart, licenseEnd);
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(license));
this.get('/v1/sys/internal/counters/activity', () => sendResponse(activity));
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () => sendResponse({ keys: [] }));
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history', 'clients/history URL is correct');
assert.dom(SELECTORS.historyActiveTab).hasText('History', 'history tab is active');
assert.dom(SELECTORS.usageStats).exists('usage stats block exists');
assert.dom('[data-test-stat-text-container]').exists({ count: 3 }, '3 stat texts exist');
const { total, by_namespace } = activity.data;
// FILTER BY NAMESPACE
await clickTrigger();
await searchSelect.options.objectAt(0).click();
await settled();
assert.ok(true, 'Filter by first namespace');
assert.dom('[data-test-stat-text="total-clients"] .stat-value').hasText('15');
assert.dom('[data-test-stat-text="entity-clients"] .stat-value').hasText('5');
assert.dom('[data-test-stat-text="non-entity-clients"] .stat-value').hasText('10');
assert.dom('[data-test-top-attribution]').includesText('Top auth method');
// check chart displays correct elements and values
for (const key in CHART_ELEMENTS) {
const { mounts } = by_namespace[0];
let mountNumber = mounts.length < 10 ? mounts.length : 10;
let group = find(CHART_ELEMENTS[key]);
let elementArray = Array.from(group.children);
assert.equal(elementArray.length, mountNumber, `renders correct number of ${key}`);
if (key === 'totalValues') {
elementArray.forEach((element, i) => {
assert.equal(element.innerHTML, `${mounts[i].counts.clients}`, 'displays correct value');
});
}
if (key === 'yLabels') {
elementArray.forEach((element, i) => {
assert
.dom(element.children[1])
.hasTextContaining(`${mounts[i].mount_path}`, 'displays correct auth label');
});
}
}
// FILTER BY AUTH METHOD
await clickTrigger();
await searchSelect.options.objectAt(0).click();
await settled();
assert.ok(true, 'Filter by first auth method');
assert.dom('[data-test-stat-text="total-clients"] .stat-value').hasText('5');
assert.dom('[data-test-stat-text="entity-clients"] .stat-value').hasText('3');
assert.dom('[data-test-stat-text="non-entity-clients"] .stat-value').hasText('2');
assert.dom(SELECTORS.attributionBlock).doesNotExist('Does not show attribution block');
await click('#namespace-search-select [data-test-selected-list-button="delete"]');
assert.ok(true, 'Remove namespace filter without first removing auth method filter');
assert.dom('[data-test-top-attribution]').includesText('Top namespace');
assert
.dom('[data-test-stat-text="total-clients"] .stat-value')
.hasText(total.clients.toString(), 'total clients stat is back to unfiltered value');
});
test('shows warning if upgrade happened within license period', async function (assert) {
const licenseStart = startOfMonth(subMonths(new Date(), 6));
const licenseEnd = addMonths(new Date(), 6);
const lastMonth = addMonths(new Date(), -1);
const config = generateConfigResponse();
const activity = generateActivityResponse(5, licenseStart, lastMonth);
const license = generateLicenseResponse(licenseStart, licenseEnd);
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(license));
this.get('/v1/sys/internal/counters/activity', () => sendResponse(activity));
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () =>
sendResponse({
data: {
keys: ['1.9.0'],
key_info: {
'1.9.0': {
previous_version: null,
timestamp_installed: formatRFC3339(addMonths(new Date(), -2)),
},
},
},
})
);
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history', 'clients/history URL is correct');
assert.dom(SELECTORS.historyActiveTab).hasText('History', 'history tab is active');
assert.dom('[data-test-alert-banner="alert"]').includesText('Vault was upgraded');
});
test('Shows empty if license start date is current month', async function (assert) {
const licenseStart = new Date();
const licenseEnd = addMonths(new Date(), 12);
const config = generateConfigResponse();
const license = generateLicenseResponse(licenseStart, licenseEnd);
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(license));
this.get('/v1/sys/internal/counters/activity', () => this.passthrough);
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () =>
sendResponse({
keys: [],
})
);
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history', 'clients/history URL is correct');
assert.dom(SELECTORS.emptyStateTitle).hasText('No data for this billing period');
assert
.dom(SELECTORS.dateDisplay)
.hasText(format(licenseStart, 'MMMM yyyy'), 'Shows license date, gives ability to edit');
assert.dom(SELECTORS.monthDropdown).exists('Dropdown exists to select month');
assert.dom(SELECTORS.yearDropdown).exists('Dropdown exists to select year');
});
test('shows correct interface if no permissions on license', async function (assert) {
const config = generateConfigResponse();
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(null, 403));
this.get('/v1/sys/internal/counters/config', () => sendResponse(config));
this.get('/v1/sys/version-history', () => sendResponse({ keys: [] }));
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history', 'clients/history URL is correct');
assert.dom(SELECTORS.historyActiveTab).hasText('History', 'history tab is active');
// Message changes depending on ent or OSS
assert.dom(SELECTORS.emptyStateTitle).exists('Empty state exists');
assert.dom(SELECTORS.monthDropdown).exists('Dropdown exists to select month');
assert.dom(SELECTORS.yearDropdown).exists('Dropdown exists to select year');
});
test('shows error template if permissions denied querying activity response with no data', async function (assert) {
this.server = new Pretender(function () {
this.get('/v1/sys/license/status', () => sendResponse(null, 403));
this.get('/v1/sys/version-history', () => sendResponse(null, 403));
this.get('/v1/sys/internal/counters/config', () => sendResponse(null, 403));
this.get('/v1/sys/internal/counters/activity', () => sendResponse(null, 403));
this.get('/v1/sys/health', this.passthrough);
this.get('/v1/sys/seal-status', this.passthrough);
this.post('/v1/sys/capabilities-self', this.passthrough);
this.get('/v1/sys/internal/ui/feature-flags', this.passthrough);
});
await visit('/vault/clients/history');
assert.equal(currentURL(), '/vault/clients/history', 'clients/history URL is correct');
assert
.dom(SELECTORS.emptyStateTitle)
.includesText('start date found', 'Empty state shows no billing start date');
await click(SELECTORS.monthDropdown);
await click(this.element.querySelector('[data-test-month-list] button:not([disabled])'));
await click(SELECTORS.yearDropdown);
await click(this.element.querySelector('[data-test-year-list] button:not([disabled])'));
await click(SELECTORS.dateDropdownSubmit);
assert
.dom(SELECTORS.emptyStateTitle)
.hasText('You are not authorized', 'Empty state displays not authorized message');
});
});