DefinitelyTyped/d3-array/d3-array-tests.ts
denis f928cdd8f3 Make d3-array work with stirctNullChecks
Add tslint.json
Set strictNullChecks to true
Changes variables names in tests
Add accessors functions in tests
Add tests for mean, median, quantile, sum, deviation, variance and scan
Add undefined to Primitive type
Remove useless declarations (number extends Numeric)
Add unions of undefined where needed
Improve permute with keyof
2017-02-07 12:36:59 +01:00

504 lines
19 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Typescript definition tests for d3/d3-array module
*
* Note: These tests are intended to test the definitions only
* in the sense of typing and call signature consistency. They
* are not intended as functional tests.
*/
import * as d3Array from 'd3-array';
import { scaleTime } from 'd3-scale';
import { timeYear } from 'd3-time';
// -----------------------------------------------------------------------------
// Preparatory Steps
// -----------------------------------------------------------------------------
class NumCoercible {
public a: number;
constructor(a: number) {
this.a = a;
}
public valueOf() {
return this.a;
}
}
class MixedObject {
public num: number;
public str: string;
public numeric: NumCoercible;
public date: Date;
constructor(a: number, date: Date) {
this.num = a;
this.str = a.toString();
this.numeric = new NumCoercible(a);
this.date = date;
}
}
let num: number;
let date: Date;
let numOrUndefined: number | undefined;
let strOrUndefined: string | undefined;
let numericOrUndefined: NumCoercible | undefined;
let dateOrUndefined: Date | undefined;
let numOrUndefinedExtent: [number, number] | [undefined, undefined];
let strOrUndefinedExtent: [string, string] | [undefined, undefined];
let numericOrUndefinedExtent: [NumCoercible, NumCoercible] | [undefined, undefined];
let dateMixedOrUndefined: [Date , Date] | [undefined, undefined];
let mixedOrUndefinedExtent: [d3Array.Primitive | NumCoercible, d3Array.Primitive | NumCoercible] | [undefined, undefined];
let dateOrUndefinedExtent: [Date, Date] | [undefined, undefined];
let numbersArray = [10, 20, 30, 40, 50];
let numbersOrUndefinedArray = [10, 20, undefined, 40, 50];
let stringyNumbersArray = ['10', '20', '30', '40', '50'];
let numericArray = [new NumCoercible(10), new NumCoercible(20), new NumCoercible(30), new NumCoercible(40), new NumCoercible(50)];
let dateArray = [new Date(2016, 6, 1), new Date(2016, 7, 30), new Date(2015, 3, 15)];
let mixedObjectArray = [
new MixedObject(10, new Date(2016, 6, 1)),
new MixedObject(20, new Date(2016, 7, 30)),
new MixedObject(30, new Date(2015, 3, 15)),
new MixedObject(40, new Date(2014, 3, 15)),
new MixedObject(50, new Date(2017, 4, 15))
];
let mixedObjectOrUndefinedArray = [...mixedObjectArray, undefined]
function accessorMixedObjectToNum(datum: MixedObject, index: number, array: Array<MixedObject>): number {
return datum.num;
}
function accessorMixedObjectToStr(datum: MixedObject, index: number, array: Array<MixedObject>): string {
return datum.str;
}
function accessorMixedObjectToNumeric(datum: MixedObject, index: number, array: Array<MixedObject>): NumCoercible {
return datum.numeric;
}
function accessorMixedObjectToDate(datum: MixedObject, index: number, array: Array<MixedObject>): Date {
return datum.date;
}
function accessorMixedObjectToNumOrUndefined(datum: MixedObject | undefined, index: number, array: Array<MixedObject | undefined>): number | undefined {
return datum ? datum.num : undefined;
}
// -----------------------------------------------------------------------------
// Test Statistics
// -----------------------------------------------------------------------------
// max() -----------------------------------------------------------------------
// without accessors
numOrUndefined = d3Array.max(numbersArray);
strOrUndefined = d3Array.max(stringyNumbersArray);
numericOrUndefined = d3Array.max(numericArray);
dateOrUndefined = d3Array.max(dateArray);
// with accessors
numOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNum);
strOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToStr);
numericOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToNumeric);
dateOrUndefined = d3Array.max(mixedObjectArray, accessorMixedObjectToDate);
// min() -----------------------------------------------------------------------
// without accessors
numOrUndefined = d3Array.min(numbersArray);
strOrUndefined = d3Array.min(stringyNumbersArray);
numericOrUndefined = d3Array.min(numericArray);
dateOrUndefined = d3Array.min(dateArray);
// with accessors
numOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNum);
strOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToStr);
numericOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToNumeric);
dateOrUndefined = d3Array.min(mixedObjectArray, accessorMixedObjectToDate);
// extent() --------------------------------------------------------------------
// without accessors
numOrUndefinedExtent = d3Array.extent(numbersArray);
strOrUndefinedExtent = d3Array.extent(stringyNumbersArray);
numericOrUndefinedExtent = d3Array.extent(numericArray);
dateOrUndefinedExtent = d3Array.extent(dateArray);
// with accessors
numOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNum);
strOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToStr);
mixedOrUndefinedExtent = d3Array.extent(mixedObjectArray, accessorMixedObjectToNumeric);
dateMixedOrUndefined = d3Array.extent(mixedObjectArray, accessorMixedObjectToDate);
// mean() ----------------------------------------------------------------------
numOrUndefined = d3Array.mean(numbersArray);
numOrUndefined = d3Array.mean(numericArray);
numOrUndefined = d3Array.mean(numbersOrUndefinedArray);
numOrUndefined = d3Array.mean(mixedObjectArray, accessorMixedObjectToNum);
numOrUndefined = d3Array.mean(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined);
// median() --------------------------------------------------------------------
numOrUndefined = d3Array.median(numbersArray);
numOrUndefined = d3Array.median(numericArray);
numOrUndefined = d3Array.median(numbersOrUndefinedArray);
numOrUndefined = d3Array.median(mixedObjectArray, accessorMixedObjectToNum);
numOrUndefined = d3Array.median(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined);
// quantile() ------------------------------------------------------------------
numOrUndefined = d3Array.quantile(numbersArray, 0.5);
numOrUndefined = d3Array.quantile(numericArray, 0.5);
numOrUndefined = d3Array.quantile(numbersOrUndefinedArray, 0.5);
numOrUndefined = d3Array.quantile(mixedObjectArray, 0.5, accessorMixedObjectToNum);
numOrUndefined = d3Array.quantile(mixedObjectOrUndefinedArray, 0.5, accessorMixedObjectToNumOrUndefined);
// sum() -----------------------------------------------------------------------
numOrUndefined = d3Array.sum(numbersArray);
numOrUndefined = d3Array.sum(numericArray);
numOrUndefined = d3Array.sum(numbersOrUndefinedArray);
numOrUndefined = d3Array.sum(mixedObjectArray, accessorMixedObjectToNum);
numOrUndefined = d3Array.sum(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined);
// deviation() -----------------------------------------------------------------
numOrUndefined = d3Array.deviation(numbersArray);
numOrUndefined = d3Array.deviation(numericArray);
numOrUndefined = d3Array.deviation(numbersOrUndefinedArray);
numOrUndefined = d3Array.deviation(mixedObjectArray, accessorMixedObjectToNum);
numOrUndefined = d3Array.deviation(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined);
// variance() ------------------------------------------------------------------
numOrUndefined = d3Array.variance(numbersArray);
numOrUndefined = d3Array.variance(numericArray);
numOrUndefined = d3Array.variance(numbersOrUndefinedArray);
numOrUndefined = d3Array.variance(mixedObjectArray, accessorMixedObjectToNum);
numOrUndefined = d3Array.variance(mixedObjectOrUndefinedArray, accessorMixedObjectToNumOrUndefined);
// -----------------------------------------------------------------------------
// Test Searching Arrays
// -----------------------------------------------------------------------------
// scan() ----------------------------------------------------------------------
numOrUndefined = d3Array.scan(numbersArray)
numOrUndefined = d3Array.scan(mixedObjectArray, function (a, b) {
let aElem: MixedObject = a;
let bElem: MixedObject = b;
return a.num - b.num;
});
numOrUndefined = d3Array.scan(mixedObjectOrUndefinedArray, function (a, b) {
let aElem: MixedObject | undefined = a;
let bElem: MixedObject | undefined = b;
return a && b ? a.num - b.num : NaN;
});
// bisectLeft() ----------------------------------------------------------------
num = d3Array.bisectLeft([0, 2, 3, 4, 7, 8], 4);
num = d3Array.bisectLeft([0, 2, 3, 4, 7, 8], 4, 1);
num = d3Array.bisectLeft([0, 2, 3, 4, 7, 8], 4, 1, 4);
num = d3Array.bisectLeft(['0', '2', '3', '4', '7', '8'], '21');
num = d3Array.bisectLeft(['0', '2', '3', '4', '7', '8'], '21', 1);
num = d3Array.bisectLeft(['0', '2', '3', '4', '7', '8'], '21', 1, 4);
num = d3Array.bisectLeft([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1));
num = d3Array.bisectLeft([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1), 1);
num = d3Array.bisectLeft([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1), 1, 2);
// bisectRight() ---------------------------------------------------------------
num = d3Array.bisectRight([0, 2, 3, 4, 7, 8], 4);
num = d3Array.bisectRight([0, 2, 3, 4, 7, 8], 4, 1);
num = d3Array.bisectRight([0, 2, 3, 4, 7, 8], 4, 1, 4);
num = d3Array.bisectRight(['0', '2', '3', '4', '7', '8'], '21');
num = d3Array.bisectRight(['0', '2', '3', '4', '7', '8'], '21', 1);
num = d3Array.bisectRight(['0', '2', '3', '4', '7', '8'], '21', 1, 4);
num = d3Array.bisectRight([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1));
num = d3Array.bisectRight([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1), 1);
num = d3Array.bisectRight([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1), 1, 2);
// bisect() --------------------------------------------------------------------
num = d3Array.bisect([0, 2, 3, 4, 7, 8], 4);
num = d3Array.bisect([0, 2, 3, 4, 7, 8], 4, 1);
num = d3Array.bisect([0, 2, 3, 4, 7, 8], 4, 1, 4);
num = d3Array.bisect(['0', '2', '3', '4', '7', '8'], '21');
num = d3Array.bisect(['0', '2', '3', '4', '7', '8'], '21', 1);
num = d3Array.bisect(['0', '2', '3', '4', '7', '8'], '21', 1, 4);
num = d3Array.bisect([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1));
num = d3Array.bisect([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1), 1);
num = d3Array.bisect([new Date(2010, 1, 1), new Date(2011, 1, 1), new Date(2012, 1, 1), new Date(2013, 1, 1)], new Date(2011, 2, 1), 1, 2);
// bisector() ------------------------------------------------------------------
mixedObjectArray.sort(function (a, b) { return a.date.valueOf() - b.date.valueOf(); });
let mixedObjectDateBisectorObject: d3Array.Bisector<MixedObject, Date>;
// define using accessor
mixedObjectDateBisectorObject = d3Array.bisector<MixedObject, Date>(function (el) {
return el.date;
});
// define using comparator
mixedObjectDateBisectorObject = d3Array.bisector<MixedObject, Date>(function (el, x) {
return el.date.valueOf() - x.valueOf();
});
// bisect left
num = mixedObjectDateBisectorObject.left(mixedObjectArray, new Date(2015, 3, 14));
num = mixedObjectDateBisectorObject.left(mixedObjectArray, new Date(2015, 3, 14), 1);
num = mixedObjectDateBisectorObject.left(mixedObjectArray, new Date(2015, 3, 14), 3, 4);
// bisect right
num = mixedObjectDateBisectorObject.right(mixedObjectArray, new Date(2015, 3, 14));
num = mixedObjectDateBisectorObject.right(mixedObjectArray, new Date(2015, 3, 14), 1);
num = mixedObjectDateBisectorObject.right(mixedObjectArray, new Date(2015, 3, 14), 3, 4);
// ascending() -----------------------------------------------------------------
num = d3Array.ascending(undefined, 20);
num = d3Array.ascending(10, 20);
num = d3Array.ascending('10', '20');
num = d3Array.ascending(new Date(2016, 6, 13), new Date(2016, 6, 14));
// descending() ----------------------------------------------------------------
num = d3Array.descending(undefined, 20);
num = d3Array.descending(10, 20);
num = d3Array.descending('10', '20');
num = d3Array.descending(new Date(2016, 6, 13), new Date(2016, 6, 14));
// -----------------------------------------------------------------------------
// Test Transforming Arrays
// -----------------------------------------------------------------------------
// merge() ---------------------------------------------------------------------
let testArrays: MixedObject[][] = [
[
new MixedObject(10, new Date(2016, 6, 1)),
new MixedObject(20, new Date(2016, 7, 30)),
new MixedObject(30, new Date(2015, 3, 15)),
new MixedObject(40, new Date(2014, 3, 15)),
new MixedObject(50, new Date(2017, 4, 15))
],
[
new MixedObject(40, new Date(2016, 3, 1)),
new MixedObject(50, new Date(2016, 9, 30)),
]
];
let mergedArray: MixedObject[];
mergedArray = d3Array.merge(testArrays); // inferred type
mergedArray = d3Array.merge<MixedObject>(testArrays); // explicit type
// mergedArray = d3Array.merge<MixedObject>([[10, 40, 30], [15, 30]]); // fails, type mismatch
// pairs() ---------------------------------------------------------------------
let pairs: Array<[MixedObject, MixedObject]>;
pairs = d3Array.pairs(mergedArray);
// permute() -------------------------------------------------------------------
// getting a permutation of array elements
mergedArray = d3Array.permute(mergedArray, [1, 0, 2, 5, 3, 4, 6]);
// Getting an ordered array with object properties
let testObject = {
val: 10,
name: 'Test',
when: new Date(),
more: [10, 30, 40]
};
let x: Array<number | string | Date | number[]> = d3Array.permute(testObject, ['name', 'val', 'when', 'more']);
// range() ---------------------------------------------------------------------
numbersArray = d3Array.range(10);
numbersArray = d3Array.range(1, 10);
numbersArray = d3Array.range(1, 10, 0.5);
// shuffle() -------------------------------------------------------------------
mergedArray = d3Array.shuffle(mergedArray);
mergedArray = d3Array.shuffle(mergedArray, 1);
mergedArray = d3Array.shuffle(mergedArray, 1, 3);
// ticks() ---------------------------------------------------------------------
numbersArray = d3Array.ticks(1, 10, 5);
// tickStep() ------------------------------------------------------------------
numbersArray = d3Array.tickStep(1, 10, 5);
// transpose() -----------------------------------------------------------------
testArrays = d3Array.transpose([
[
new MixedObject(10, new Date(2016, 6, 1)),
new MixedObject(50, new Date(2017, 4, 15))
],
[
new MixedObject(40, new Date(2016, 3, 1)),
new MixedObject(50, new Date(2016, 9, 30)),
]
]);
// zip() -----------------------------------------------------------------------
testArrays = d3Array.zip(
[
new MixedObject(10, new Date(2016, 6, 1)),
new MixedObject(20, new Date(2016, 7, 30)),
new MixedObject(30, new Date(2015, 3, 15)),
new MixedObject(40, new Date(2014, 3, 15)),
new MixedObject(50, new Date(2017, 4, 15))
],
[
new MixedObject(40, new Date(2016, 3, 1)),
new MixedObject(50, new Date(2016, 9, 30)),
]
);
// -----------------------------------------------------------------------------
// Test Histogram
// -----------------------------------------------------------------------------
let tScale = scaleTime();
// Create histogram generator ==================================================
let defaultHistogram: d3Array.HistogramGenerator<number, number>;
defaultHistogram = d3Array.histogram();
let testHistogram: d3Array.HistogramGenerator<MixedObject, Date>;
testHistogram = d3Array.histogram<MixedObject, Date>();
// Configure histogram generator ===============================================
// value(...) ------------------------------------------------------------------
testHistogram = testHistogram.value(function (d, i, data) {
let datum: MixedObject = d; // d is of type MixedObject
let index: number = i; // i is number
let array: MixedObject[] = data; // data is of type MixedObject[]
return datum.date;
});
let valueAccessorFn: (d: MixedObject, i: number, data: MixedObject[]) => Date;
valueAccessorFn = testHistogram.value();
// domain(...) -----------------------------------------------------------------
// test with array
testHistogram = testHistogram.domain([new Date(2014, 3, 15), new Date(2017, 4, 15)]);
// usage with scale domain:
let domain = tScale.domain();
testHistogram = testHistogram.domain([domain[0], domain[domain.length]]);
// testHistogram = testHistogram.domain(tScale.domain()); // fails, as scale domain is an array with possibly more than the two elements expected by histogram
// use with accessor function
testHistogram = testHistogram.domain(function (values) {
return [values[0], values[values.length]];
});
// get current domain accessor function
let domainAccessorFn: (values: Date[]) => [Date, Date];
domainAccessorFn = testHistogram.domain();
// thresholds(...) -------------------------------------------------------------
// with count constant
defaultHistogram = defaultHistogram.thresholds(3);
// with threshold count generator
defaultHistogram = defaultHistogram.thresholds(d3Array.thresholdScott);
// with thresholds value array
testHistogram = testHistogram.thresholds([new Date(2015, 11, 15), new Date(2016, 6, 1), new Date(2016, 8, 30)]);
// with thresholds value array accessors
testHistogram = testHistogram.thresholds(function (values: Date[], min: Date, max: Date) {
let thresholds: Date[];
thresholds = [values[0], values[2], values[4]];
return thresholds;
});
testHistogram = testHistogram.thresholds(tScale.ticks(timeYear));
// Use histogram generator =====================================================
let defaultBins: Array<d3Array.Bin<number, number>>;
defaultBins = defaultHistogram([-1, 0, 1, 1, 3, 20, 234]);
let defaultBin: d3Array.Bin<number, number>;
defaultBin = defaultBins[0];
num = defaultBin.length; // defaultBin is array
num = defaultBin[0]; // with element type number
num = defaultBin.x0; // bin lower bound is number
num = defaultBin.x1; // bin upper bound is number
let testBins: Array<d3Array.Bin<MixedObject, Date>>;
testBins = testHistogram(mixedObjectArray);
let testBin: d3Array.Bin<MixedObject, Date>;
testBin = testBins[0];
num = testBin.length; // defaultBin is array
let mixedObject: MixedObject = testBin[0]; // with element type MixedObject
date = testBin.x0; // bin lower bound is Date
date = testBin.x1; // bin upper bound is Date
// Histogram Tresholds =========================================================
num = d3Array.thresholdFreedmanDiaconis([-1, 0, 1, 1, 3, 20, 234], -1, 234);
num = d3Array.thresholdScott([-1, 0, 1, 1, 3, 20, 234], -1, 234);
num = d3Array.thresholdSturges([-1, 0, 1, 1, 3, 20, 234]);