blob: 38b0263f912af3e001de64578478956e73220c77 [file] [log] [blame]
import { assert } from 'chai';
import { FrontendDescription } from '../json';
import {
columnSortFunctions,
down, SortHistory, SortSelection, up,
} from './index';
describe('SortSelection', () => {
describe('toggleDirection', () => {
it('toggles up to down', () => {
const s = new SortSelection(1, down);
s.toggleDirection();
assert.equal(up, s.directionMultiplier());
s.toggleDirection();
assert.equal(down, s.directionMultiplier());
});
});
it('encodes correctly', () => {
const s = new SortSelection(1, down);
assert.equal(s.encode(), 'd1');
});
it('decodes correctly', () => {
const s = SortSelection.decode('u12');
assert.equal(s.dir, up);
assert.equal(s.column, 12);
});
it('handles invalid input to decode', () => {
const s = SortSelection.decode('');
assert.equal(s.dir, down);
assert.equal(s.column, 0);
});
});
describe('SortHistory', () => {
const columnSorters: columnSortFunctions<FrontendDescription> = [
() => 0,
() => 0,
];
describe('selectColumnToSortOn', () => {
it('updates sort history', () => {
const sh = new SortHistory(columnSorters);
assert.equal(sh.history[0].column, 0);
assert.equal(sh.history[0].dir, up);
assert.equal(sh.history[1].column, 1);
assert.equal(sh.history[1].dir, up);
sh.selectColumnToSortOn(1);
assert.equal(sh.history[0].column, 1);
assert.equal(sh.history[0].dir, down);
assert.equal(sh.history[1].column, 0);
assert.equal(sh.history[1].dir, up);
});
});
describe('encode', () => {
it('reflects default history', () => {
const sh = new SortHistory(columnSorters);
assert.equal(sh.encode(), 'u0-u1');
});
it('reflects updated history', () => {
const sh = new SortHistory(columnSorters);
sh.selectColumnToSortOn(1);
assert.equal(sh.encode(), 'd1-u0');
});
});
describe('decode', () => {
it('mirrors encode', () => {
const sh = new SortHistory(columnSorters);
sh.selectColumnToSortOn(1);
const hydrated = new SortHistory(columnSorters);
hydrated.decode(sh.encode());
assert.equal(hydrated.encode(), sh.encode());
});
it('is robust to garbage input', () => {
const hydrated = new SortHistory(columnSorters);
hydrated.decode('u1-d0-some garbage value');
assert.equal(hydrated.encode(), 'u0-u1', 'The decode value was invalid, so stick with the default value of SortHistory.history.');
});
});
describe('compare', () => {
// Start with a base FrontendDescription;
const desc1: FrontendDescription = {
Mode: 'available',
AttachedDevice: 'nodevice',
Annotation: {
Message: 'Requested powercycle for "skia-e-linux-101"',
User: 'jcgregorio@google.com',
Timestamp: '2022-02-15T19:40:45.192013Z',
},
Note: {
Message: '',
User: '',
Timestamp: '0001-01-01T00:00:00Z',
},
Version: '2022-02-09T13_06_42Z-jcgregorio-7605d80-clean',
PowerCycle: false,
PowerCycleState: 'available',
LastUpdated: '2022-02-26T16:40:38.008347Z',
Battery: 0,
Temperature: {},
RunningSwarmingTask: false,
LaunchedSwarming: true,
DeviceUptime: 0,
SSHUserIP: '',
Dimensions: {
id: [
'linux-101',
],
},
};
// Now create desc2 based on its differences from desc1.
const desc2 = Object.assign({}, desc1, {
AttachedDevice: 'ios',
PowerCycle: true,
Battery: 100,
Dimensions: {
id: [
'linux-102',
],
},
});
// Now create desc3 based on its differences from desc1.
const desc3 = Object.assign({}, desc1, {
AttachedDevice: 'adb',
Battery: 50,
Dimensions: {
id: [
'linux-103',
],
},
});
// Sort functions for different clumns, i.e. values in FrontendDescription.
const sortByAttachDevice = (a: FrontendDescription, b: FrontendDescription): number => a.AttachedDevice.localeCompare(b.AttachedDevice);
const sortByBattery = (a: FrontendDescription, b: FrontendDescription): number => a.Battery - b.Battery;
const sortByPowerCycle = (a: FrontendDescription, b: FrontendDescription): number => {
if (a.PowerCycle === b.PowerCycle) {
return 0;
}
if (a.PowerCycle) {
return 1;
}
return -1;
};
it('sorts', () => {
const descriptions: FrontendDescription[] = [
desc1, desc2, desc3,
];
const sh = new SortHistory<FrontendDescription>([
sortByAttachDevice,
sortByBattery,
sortByPowerCycle,
]);
// Sort in the default order.
descriptions.sort(sh.compare.bind(sh));
assert.equal(sh.encode(), 'u0-u1-u2');
assert.deepEqual(['adb', 'ios', 'nodevice'], descriptions.map((d: FrontendDescription): string => d.AttachedDevice));
assert.deepEqual([50, 100, 0], descriptions.map((d: FrontendDescription): number => d.Battery));
assert.deepEqual([false, true, false], descriptions.map((d: FrontendDescription): boolean => d.PowerCycle));
// Now sort with col 1 (Battery), descending.
sh.selectColumnToSortOn(1);
assert.equal(sh.encode(), 'd1-u0-u2');
descriptions.sort(sh.compare.bind(sh));
assert.deepEqual(['ios', 'adb', 'nodevice'], descriptions.map((d: FrontendDescription): string => d.AttachedDevice));
assert.deepEqual([100, 50, 0], descriptions.map((d: FrontendDescription): number => d.Battery));
assert.deepEqual([true, false, false], descriptions.map((d: FrontendDescription): boolean => d.PowerCycle));
// Now sort with col 2 (PowerCycle) descending and col 1 (Battery) ascending.
sh.selectColumnToSortOn(1);
sh.selectColumnToSortOn(2);
assert.equal(sh.encode(), 'd2-u1-u0');
descriptions.sort(sh.compare.bind(sh));
assert.deepEqual(['ios', 'nodevice', 'adb'], descriptions.map((d: FrontendDescription): string => d.AttachedDevice));
// This shows Battery was sorted ascending when PowerCycle values were the same.
assert.deepEqual([100, 0, 50], descriptions.map((d: FrontendDescription): number => d.Battery));
assert.deepEqual([true, false, false], descriptions.map((d: FrontendDescription): boolean => d.PowerCycle));
});
});
});