Files
threshold-ui/addons/api/tests/unit/utils/sort-results-test.js
T
Lisbet Alvarez 738fa1f15f refactor: 💡 add custom sort to resources (#2860)
* refactor: 💡 add custom sort

* test: 💍 fix tests

* test: 💍 fix more tests

* refactor: 💡 use reusable sort function for name

* refactor: 💡 use sort util in all resources w/ optional name

* Add missing copyright headers

* test: 💍 fix broken tests & add tests for new util

* refactor: 💡 add name custom sort to users

* test: 💍 fix import in tests

* refactor: 💡 add custom name sort to scopes

* test: 💍 pr feedback on util test cases

* refactor: 💡 move sort function into object (pr feedback)
2025-06-05 11:00:25 -07:00

489 lines
15 KiB
JavaScript

/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/
import { assert, module, test } from 'qunit';
import { sortResults } from 'api/utils/sort-results';
import { faker } from '@faker-js/faker';
import { setupTest } from 'ember-qunit';
function createJsonApiMockRecord(id, type, attributes) {
return {
id,
type,
attributes,
};
}
module('Unit | Utility | sortResults', function (hooks) {
setupTest(hooks);
module('Defaults', function () {
test("throws an error when an attribute is not id, created_time or defined as a schema attribute, even when it exists on the record's attribute object", function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
name: 'Result 01',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
name: 'Result 02',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
name: 'Result 03',
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
]);
const querySort = { attribute: 'name' };
// Note: `name` is not defined as a schema attribute but exists on the record
const schema = { attributes: new Map() };
schema.attributes.set('date', { type: 'date' });
assert.throws(
() => sortResults(shuffledResults, { querySort, schema }),
/Error: The attribute "name" does not map to the model definition of type "target". Supported sortable attributes are 'id', 'created_time', or 'date'/,
);
});
test('throws an error when results do not contain a valid sort direction', function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
name: 'Result 01',
});
const querySort = {
attribute: 'name',
direction: 'invalid sort direction',
};
const schema = { attributes: new Map() };
schema.attributes.set('name', { type: 'string' });
assert.throws(
() => sortResults([result01], { querySort, schema }),
/Error: Invalid sort direction/,
);
});
test('when passing no querySort, sorts using default created_time, descending order and string sorting', async function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
created_time: '2021',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
created_time: '2022',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
created_time: '2023',
});
const result04 = createJsonApiMockRecord('id_04', 'target', {
created_time: '2024',
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySort = {};
const schema = { attributes: new Map() };
schema.attributes.set('created_time', { type: 'string' });
const sortedResults = sortResults(shuffledResults, {
querySort,
schema,
});
assert.deepEqual(
sortedResults.map(({ attributes: { created_time } }) => created_time),
['2024', '2023', '2022', '2021'],
);
});
test('when sorting by id, without being on the results attributes it sorts as expected ', function () {
const result01 = createJsonApiMockRecord('id_01', 'target', {
name: 'Result 01',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
name: 'Result 02',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
name: 'Result 03',
});
const result04 = createJsonApiMockRecord('id_04', 'target', {
name: 'Result 04',
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySort = { attribute: 'id' };
const schema = { attributes: new Map() };
schema.attributes.set('id', { type: 'string' });
const sortedResults = sortResults(shuffledResults, { querySort, schema });
assert.deepEqual(
sortedResults.map(({ id }) => id),
['id_01', 'id_02', 'id_03', 'id_04'],
);
});
});
module('string sorting', function () {
test('it sorts by ascending (default) `name` using string sorting', async function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
name: 'Result 01',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
name: 'Result 02',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
name: 'Result 03',
});
const result04 = createJsonApiMockRecord('id_04', 'target', {
name: 'Result 04',
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySort = { attribute: 'name' };
const schema = { attributes: new Map() };
schema.attributes.set('name', { type: 'string' });
const sortedResults = sortResults(shuffledResults, { querySort, schema });
assert.deepEqual(
sortedResults.map(({ attributes: { name } }) => name),
['Result 01', 'Result 02', 'Result 03', 'Result 04'],
);
});
test('it sorts by ascending then descending `name` using string sorting', async function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
name: 'Result 01',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
name: 'Result 02',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
name: 'Result 03',
});
const result04 = createJsonApiMockRecord('id_04', 'target', {
name: 'Result 04',
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySortAsc = { attribute: 'name', direction: 'asc' };
const querySortDesc = { attribute: 'name', direction: 'desc' };
const schema = { attributes: new Map() };
schema.attributes.set('name', { type: 'string' });
const sortedResultsAsc = sortResults(shuffledResults, {
querySort: querySortAsc,
schema,
});
const sortedResultsDesc = sortResults(shuffledResults, {
querySort: querySortDesc,
schema,
});
assert.deepEqual(
sortedResultsAsc.map(({ attributes: { name } }) => name),
['Result 01', 'Result 02', 'Result 03', 'Result 04'],
);
assert.deepEqual(
sortedResultsDesc.map(({ attributes: { name } }) => name),
['Result 04', 'Result 03', 'Result 02', 'Result 01'],
);
});
});
module('date sorting', function () {
test('it sorts by ascending (default) `date` using date sorting', function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
date: '2021',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
date: '2022',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
date: '2023',
});
const result04 = createJsonApiMockRecord('id_04', 'target', {
date: '2024',
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySort = { attribute: 'date' };
const schema = { attributes: new Map() };
schema.attributes.set('date', { type: 'date' });
const sortedResults = sortResults(shuffledResults, { querySort, schema });
assert.deepEqual(
sortedResults.map(({ attributes: { date } }) => date),
['2021', '2022', '2023', '2024'],
);
});
test('it sorts by ascending then descending `date` using date sorting', function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
date: '2021',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
date: '2022',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
date: '2023',
});
const result04 = createJsonApiMockRecord('id_04', 'target', {
date: '2024',
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySortAsc = { attribute: 'date', direction: 'asc' };
const querySortDesc = { attribute: 'date', direction: 'desc' };
const schema = { attributes: new Map() };
schema.attributes.set('date', { type: 'date' });
const sortedResultsAsc = sortResults(shuffledResults, {
querySort: querySortAsc,
schema,
});
const sortedResultsDesc = sortResults(shuffledResults, {
querySort: querySortDesc,
schema,
});
assert.deepEqual(
sortedResultsAsc.map(({ attributes: { date } }) => date),
['2021', '2022', '2023', '2024'],
);
assert.deepEqual(
sortedResultsDesc.map(({ attributes: { date } }) => date),
['2024', '2023', '2022', '2021'],
);
});
});
module('number sorting', function () {
test('it sorts by ascending (default) `sessions`', function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
sessions: 10,
});
const result02 = createJsonApiMockRecord('id_01', 'target', {
sessions: 200,
});
const result03 = createJsonApiMockRecord('id_01', 'target', {
sessions: 3333,
});
const result04 = createJsonApiMockRecord('id_01', 'target', {
sessions: 40444,
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySort = { attribute: 'sessions' };
const schema = { attributes: new Map() };
schema.attributes.set('sessions', { type: 'number' });
const sortedResults = sortResults(shuffledResults, { querySort, schema });
assert.deepEqual(
sortedResults.map(({ attributes: { sessions } }) => sessions),
[10, 200, 3333, 40444],
);
});
test('it sorts by ascending then descending `sessions`', function (assert) {
const result01 = createJsonApiMockRecord('id_01', 'target', {
sessions: 10,
});
const result02 = createJsonApiMockRecord('id_01', 'target', {
sessions: 200,
});
const result03 = createJsonApiMockRecord('id_01', 'target', {
sessions: 3333,
});
const result04 = createJsonApiMockRecord('id_01', 'target', {
sessions: 40444,
});
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySortAsc = { attribute: 'sessions', direction: 'asc' };
const querySortDesc = { attribute: 'sessions', direction: 'desc' };
const schema = { attributes: new Map() };
schema.attributes.set('sessions', { type: 'number' });
const sortedResultsAsc = sortResults(shuffledResults, {
querySort: querySortAsc,
schema,
});
const sortedResultsDesc = sortResults(shuffledResults, {
querySort: querySortDesc,
schema,
});
assert.deepEqual(
sortedResultsAsc.map(({ attributes: { sessions } }) => sessions),
[10, 200, 3333, 40444],
);
assert.deepEqual(
sortedResultsDesc.map(({ attributes: { sessions } }) => sessions),
[40444, 3333, 200, 10],
);
});
});
module('boolean sorting', function () {
test('it sorts by ascending (default) `active`', function (assert) {
const result01 = { attributes: { active: true } };
const result02 = { attributes: { active: false } };
const result03 = { attributes: { active: false } };
const result04 = { attributes: { active: true } };
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySort = { attribute: 'active' };
const schema = { attributes: new Map() };
schema.attributes.set('active', { type: 'boolean' });
const sortedResults = sortResults(shuffledResults, { querySort, schema });
assert.deepEqual(
sortedResults.map(({ attributes: { active } }) => active),
[false, false, true, true],
);
});
test('it sorts by ascending then descending `active`', function (assert) {
const result01 = { attributes: { active: true } };
const result02 = { attributes: { active: false } };
const result03 = { attributes: { active: false } };
const result04 = { attributes: { active: true } };
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
const querySortAsc = { attribute: 'active', direction: 'asc' };
const querySortDesc = { attribute: 'active', direction: 'desc' };
const schema = { attributes: new Map() };
schema.attributes.set('active', { type: 'boolean' });
const sortedResultsAsc = sortResults(shuffledResults, {
querySort: querySortAsc,
schema,
});
const sortedResultsDesc = sortResults(shuffledResults, {
querySort: querySortDesc,
schema,
});
assert.deepEqual(
sortedResultsAsc.map(({ attributes: { active } }) => active),
[false, false, true, true],
);
assert.deepEqual(
sortedResultsDesc.map(({ attributes: { active } }) => active),
[true, true, false, false],
);
});
});
module('custom function sorting', function () {
const result01 = createJsonApiMockRecord('id_01', 'target', {
name: 'target1',
});
const result02 = createJsonApiMockRecord('id_02', 'target', {
name: 'target2',
});
const result03 = createJsonApiMockRecord('id_03', 'target', {
name: 'target3',
});
const result04 = createJsonApiMockRecord('id_04', 'target', {
name: 'target4',
});
const sortFunction = (recordA, recordB) => {
const nameMap = {
target3: 'Alpha',
target4: 'Beta',
target1: 'Delta',
target2: 'Epsilon',
};
return String(nameMap[recordA.attributes.name]).localeCompare(
String(nameMap[recordB.attributes.name]),
);
};
const schema = { attributes: new Map() };
test.each(
'it sorts by `name` using custom sorting function',
{
'ascending (default)': {
querySort: { sortFunction },
expectedResults: ['target3', 'target4', 'target1', 'target2'],
},
descending: {
querySort: { sortFunction, direction: 'desc' },
expectedResults: ['target2', 'target1', 'target4', 'target3'],
},
ascending: {
querySort: { sortFunction, direction: 'asc' },
expectedResults: ['target3', 'target4', 'target1', 'target2'],
},
},
function (assert, input) {
const shuffledResults = faker.helpers.shuffle([
result01,
result02,
result03,
result04,
]);
schema.attributes.set('name', { type: 'string' });
const sortedResults = sortResults(shuffledResults, {
querySort: input.querySort,
schema,
});
assert.deepEqual(
sortedResults.map(({ attributes: { name } }) => name),
input.expectedResults,
);
},
);
});
});