blob: 14fbbf73ed28d762c44409e0909d65e5ff002758 [file] [log] [blame]
import { assert } from 'chai';
import { Description } 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<Description> = [() => 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 Description;
const desc1: Description = {
MaintenanceMode: '',
Recovering: '',
IsQuarantined: false,
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'],
},
RecoveryStart: '2022-02-26T16:40:38.008347Z',
SuppliedDimensions: {},
TaskStarted: '2022-02-26T16:40:38.008347Z',
};
// 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 Description.
const sortByAttachDevice = (a: Description, b: Description): number =>
a.AttachedDevice.localeCompare(b.AttachedDevice);
const sortByBattery = (a: Description, b: Description): number =>
a.Battery - b.Battery;
const sortByPowerCycle = (a: Description, b: Description): number => {
if (a.PowerCycle === b.PowerCycle) {
return 0;
}
if (a.PowerCycle) {
return 1;
}
return -1;
};
it('sorts', () => {
const descriptions: Description[] = [desc1, desc2, desc3];
const sh = new SortHistory<Description>([
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: Description): string => d.AttachedDevice)
);
assert.deepEqual(
[50, 100, 0],
descriptions.map((d: Description): number => d.Battery)
);
assert.deepEqual(
[false, true, false],
descriptions.map((d: Description): 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: Description): string => d.AttachedDevice)
);
assert.deepEqual(
[100, 50, 0],
descriptions.map((d: Description): number => d.Battery)
);
assert.deepEqual(
[true, false, false],
descriptions.map((d: Description): 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: Description): string => d.AttachedDevice)
);
// This shows Battery was sorted ascending when PowerCycle values were the same.
assert.deepEqual(
[100, 0, 50],
descriptions.map((d: Description): number => d.Battery)
);
assert.deepEqual(
[true, false, false],
descriptions.map((d: Description): boolean => d.PowerCycle)
);
});
});
});