vault/ui/tests/unit/services/pagination-test.js
claire bontempo 1fbbf9d76b
UI: Ember-data upgrade 5.3.2 prep: use custom service instead of extending ember-data store (#28695)
* rename store to pagination, remove store extension

* initial update of service test

* remove superfluous helper

* replace store with pagination service in main app

* update kmip engine syntax

* add pagination to kmip engine

* update to pagination in config-ui engine

* update sync engine to use pagination service

* use pagination service in kv engine

* use pagination service in ldap engine

* use pagination in pki engine

* update renaming clearDataset functions

* link to jira VAULT-31721

* remove comment
2024-10-17 10:00:57 -07:00

289 lines
9.2 KiB
JavaScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { keyForCache } from 'vault/services/pagination';
import { dasherize } from '@ember/string';
import clamp from 'vault/utils/clamp';
import config from 'vault/config/environment';
import Sinon from 'sinon';
const { DEFAULT_PAGE_SIZE } = config.APP;
module('Unit | Service | pagination', function (hooks) {
setupTest(hooks);
hooks.beforeEach(function () {
this.pagination = this.owner.lookup('service:pagination');
this.store = this.owner.lookup('service:store');
});
test('pagination.setLazyCacheForModel', function (assert) {
const modelName = 'someModel';
const key = {
id: '',
backend: 'database',
responsePath: 'data.keys',
page: 1,
pageFilter: null,
size: 15,
};
const value = {
response: {
request_id: '1eb6473c-8df0-924e-1c8d-e016a6420aee',
lease_id: '',
renewable: false,
lease_duration: 0,
data: {
keys: null,
},
wrap_info: null,
warnings: null,
auth: null,
mount_type: 'database',
backend: 'database',
},
dataset: ['connection', 'connection2'],
};
this.pagination.setLazyCacheForModel(modelName, key, value);
const cacheEntry = this.pagination.lazyCaches.get(dasherize(modelName));
const actual = Object.fromEntries(cacheEntry); // convert from Map to Object for assertion
const expected = { '{"backend":"database","id":""}': value };
assert.propEqual(actual, expected, 'model name is dasherized and can be retrieved from lazyCache');
});
test('keyForCache', function (assert) {
const query = { id: 1 };
const queryWithSize = { id: 1, size: 1 };
assert.deepEqual(keyForCache(query), JSON.stringify(query), 'generated the correct cache key');
assert.deepEqual(keyForCache(queryWithSize), JSON.stringify(query), 'excludes size from query cache');
});
test('clamp', function (assert) {
assert.strictEqual(clamp('foo', 0, 100), 0, 'returns the min if passed a non-number');
assert.strictEqual(clamp(0, 1, 100), 1, 'returns the min when passed number is less than the min');
assert.strictEqual(clamp(200, 1, 100), 100, 'returns the max passed number is greater than the max');
assert.strictEqual(clamp(50, 1, 100), 50, 'returns the passed number when it is in range');
});
test('pagination.storeDataset', function (assert) {
const arr = ['one', 'two'];
const query = { id: 1 };
this.pagination.storeDataset('data', query, {}, arr);
assert.deepEqual(
this.pagination.getDataset('data', query).dataset,
arr,
'it stores the array as .dataset'
);
assert.deepEqual(
this.pagination.getDataset('data', query).response,
{},
'it stores the response as .response'
);
assert.ok(this.pagination.get('lazyCaches').has('data'), 'it stores model map');
assert.ok(
this.pagination.get('lazyCaches').get('data').has(keyForCache(query)),
'it stores data on the model map'
);
});
test('pagination.clearDataset with a prefix', function (assert) {
const arr = ['one', 'two'];
const arr2 = ['one', 'two', 'three', 'four'];
this.pagination.storeDataset('data', { id: 1 }, {}, arr);
this.pagination.storeDataset('transit-key', { id: 2 }, {}, arr2);
assert.strictEqual(this.pagination.get('lazyCaches').size, 2, 'it stores both keys');
this.pagination.clearDataset('transit-key');
assert.strictEqual(this.pagination.get('lazyCaches').size, 1, 'deletes one key');
assert.notOk(this.pagination.get('lazyCaches').has('transit-key'), 'cache is no longer stored');
});
test('pagination.clearDataset with no args clears entire cache', function (assert) {
const arr = ['one', 'two'];
const arr2 = ['one', 'two', 'three', 'four'];
this.pagination.storeDataset('data', { id: 1 }, {}, arr);
this.pagination.storeDataset('transit-key', { id: 2 }, {}, arr2);
assert.strictEqual(this.pagination.get('lazyCaches').size, 2, 'it stores both keys');
this.pagination.clearDataset();
assert.strictEqual(this.pagination.get('lazyCaches').size, 0, 'deletes all of the keys');
assert.notOk(this.pagination.get('lazyCaches').has('transit-key'), 'first cache key is no longer stored');
assert.notOk(this.pagination.get('lazyCaches').has('data'), 'second cache key is no longer stored');
});
test('pagination.getDataset', function (assert) {
const arr = ['one', 'two'];
this.pagination.storeDataset('data', { id: 1 }, {}, arr);
assert.deepEqual(this.pagination.getDataset('data', { id: 1 }), { response: {}, dataset: arr });
});
test('pagination.constructResponse', function (assert) {
const arr = ['one', 'two', 'three', 'fifteen', 'twelve'];
this.pagination.storeDataset('data', { id: 1 }, {}, arr);
assert.deepEqual(
this.pagination.constructResponse('data', {
id: 1,
pageFilter: 't',
page: 1,
size: 3,
responsePath: 'data',
}),
{
data: ['two', 'three', 'fifteen'],
meta: {
currentPage: 1,
lastPage: 2,
nextPage: 2,
prevPage: 1,
total: 5,
filteredTotal: 4,
pageSize: 3,
},
},
'it returns filtered results'
);
});
test('pagination.fetchPage', async function (assert) {
const keys = ['zero', 'one', 'two', 'three', 'four', 'five', 'six'];
const data = {
data: {
keys,
},
};
const pageSize = 2;
const query = {
size: pageSize,
page: 1,
responsePath: 'data.keys',
};
this.pagination.storeDataset('transit-key', query, data, keys);
let result;
result = await this.pagination.fetchPage('transit-key', query);
assert.strictEqual(result.get('length'), pageSize, 'returns the correct number of items');
assert.deepEqual(
result.map((r) => r.id),
keys.slice(0, pageSize),
'returns the first page of items'
);
assert.deepEqual(
result.get('meta'),
{
nextPage: 2,
prevPage: 1,
currentPage: 1,
lastPage: 4,
total: 7,
filteredTotal: 7,
pageSize: 2,
},
'returns correct meta values'
);
result = await this.pagination.fetchPage('transit-key', {
size: pageSize,
page: 3,
responsePath: 'data.keys',
});
const pageThreeEnd = 3 * pageSize;
const pageThreeStart = pageThreeEnd - pageSize;
assert.deepEqual(
result.map((r) => r.id),
keys.slice(pageThreeStart, pageThreeEnd),
'returns the third page of items'
);
result = await this.pagination.fetchPage('transit-key', {
size: pageSize,
page: 99,
responsePath: 'data.keys',
});
assert.deepEqual(
result.map((r) => r.id),
keys.slice(keys.length - 1),
'returns the last page when the page value is beyond the of bounds'
);
result = await this.pagination.fetchPage('transit-key', {
size: pageSize,
page: 0,
responsePath: 'data.keys',
});
assert.deepEqual(
result.map((r) => r.id),
keys.slice(0, pageSize),
'returns the first page when page value is under the bounds'
);
});
test('pagination.lazyPaginatedQuery', async function (assert) {
const response = {
data: ['foo'],
};
let queryArgs;
const adapterForStub = () => {
return {
query(store, modelName, query) {
queryArgs = query;
return Promise.resolve(response);
},
};
};
Sinon.stub(this.store, 'adapterFor').callsFake(adapterForStub);
// stub fetchPage because we test it separately
Sinon.stub(this.pagination, 'fetchPage').callsFake(() => {});
const query = { page: 1, size: 1, responsePath: 'data' };
await this.pagination.lazyPaginatedQuery('transit-key', query);
assert.deepEqual(
this.pagination.getDataset('transit-key', query),
{ response: { data: null }, dataset: ['foo'] },
'stores returned dataset'
);
await this.pagination.lazyPaginatedQuery('secret', { page: 1, responsePath: 'data' });
assert.strictEqual(queryArgs.size, DEFAULT_PAGE_SIZE, 'calls query with DEFAULT_PAGE_SIZE');
assert.throws(
() => {
this.pagination.lazyPaginatedQuery('transit-key', {});
},
/responsePath is required/,
'requires responsePath'
);
assert.throws(
() => {
this.pagination.lazyPaginatedQuery('transit-key', { responsePath: 'foo' });
},
/page is required/,
'requires page'
);
});
test('pagination.filterData', async function (assert) {
const dataset = [
{ id: 'foo', name: 'Foo', type: 'test' },
{ id: 'bar', name: 'Bar', type: 'test' },
{ id: 'bar-2', name: 'Bar', type: null },
];
const defaultFiltering = this.pagination.filterData('foo', dataset);
assert.deepEqual(defaultFiltering, [{ id: 'foo', name: 'Foo', type: 'test' }]);
const filter = (data) => {
return data.filter((d) => d.name === 'Bar' && d.type === 'test');
};
const customFiltering = this.pagination.filterData(filter, dataset);
assert.deepEqual(customFiltering, [{ id: 'bar', name: 'Bar', type: 'test' }]);
});
});