diff --git a/chai-json-schema/index.d.ts b/chai-json-schema/index.d.ts index e3e4934c76..e66e2c96af 100644 --- a/chai-json-schema/index.d.ts +++ b/chai-json-schema/index.d.ts @@ -6,19 +6,19 @@ // // -declare namespace Chai { - export interface Assert { - jsonSchema(value: any, schema: any, msg?: string): void; - notJsonSchema(value: any, schema: any, msg?: string): void; - } +declare global { + namespace Chai { + export interface Assert { + jsonSchema(value: any, schema: any, msg?: string): void; + notJsonSchema(value: any, schema: any, msg?: string): void; + } - export interface LanguageChains { - jsonSchema(schema: any, msg?: string): void; + export interface LanguageChains { + jsonSchema(schema: any, msg?: string): void; + } } } -declare module "chai-json-schema" { - function chaiJsonSchema(chai: any, utils: any): void; - namespace chaiJsonSchema {} - export = chaiJsonSchema; -} +declare function chaiJsonSchema(chai: any, utils: any): void; +declare namespace chaiJsonSchema { } +export = chaiJsonSchema; diff --git a/chai-json-schema/tslint.json b/chai-json-schema/tslint.json index 83a03ce890..377cc837d4 100644 --- a/chai-json-schema/tslint.json +++ b/chai-json-schema/tslint.json @@ -1,5 +1 @@ -{ "extends": "../tslint.json", - "rules": { - "no-single-declare-module": false - } -} +{ "extends": "../tslint.json" } diff --git a/d3-selection/d3-selection-tests.ts b/d3-selection/d3-selection-tests.ts index b1f776c442..042fba622a 100644 --- a/d3-selection/d3-selection-tests.ts +++ b/d3-selection/d3-selection-tests.ts @@ -846,60 +846,43 @@ newDiv2 = body.append(function (d, i, g) { // without insert<...> typing returned selection has group element of type BaseType let newParagraph: d3Selection.Selection; newParagraph = body.insert('p', 'p.second-paragraph'); +newParagraph = body.insert('p'); + +// Two arguments; the first can be string, selection , or a + +const typeValueFunction = function ( + this: HTMLBodyElement, + d: BodyDatum, + i: number, + g: HTMLBodyElement[] | d3Selection.ArrayLike +) { + return this.ownerDocument.createElement('p'); // this-type HTMLParagraphElement +} + +const beforeValueFunction = function ( + this: HTMLBodyElement, + d: BodyDatum, + i: number, + g: HTMLBodyElement[] | d3Selection.ArrayLike +) { + return this.children[0]; +} let newParagraph2: d3Selection.Selection; + +// 2 args, with 3 possibilities each, makes 9 possible combinations: newParagraph2 = body.insert('p', 'p.second-paragraph'); +newParagraph2 = body.insert('p', beforeValueFunction); +newParagraph2 = body.insert('p'); newParagraph2 = body.insert(d3Selection.creator('p'), 'p.second-paragraph'); -newParagraph2 = body.insert(function (d, i, g) { - let that: HTMLBodyElement = this; - // let that2: SVGElement = this; // fails, type mismatch - let datum: BodyDatum = d; - let index: number = i; - let group: HTMLBodyElement[] | d3Selection.ArrayLike = g; - console.log('Body element foo property: ', d.foo); // data of type BodyDatum - return this.ownerDocument.createElement('p'); // this-type HTMLParagraphElement -}, 'p.second-paragraph'); +newParagraph2 = body.insert(d3Selection.creator('p'), beforeValueFunction); +newParagraph2 = body.insert(d3Selection.creator('p')); -// newParagraph2 = body.insert(function(d) { -// return this.ownerDocument.createElement('a'); // fails, HTMLParagraphElement expected by type parameter, HTMLAnchorElement returned -// }, 'p.second-paragraph'); +newParagraph2 = body.insert(typeValueFunction, 'p.second-paragraph'); +newParagraph2 = body.insert(typeValueFunction, beforeValueFunction); +newParagraph2 = body.insert(typeValueFunction); -// newParagraph2 = body.insert(function(d) { -// return this.ownerDocument.createElement('a'); // fails, HTMLParagraphElement expected by type inference, HTMLAnchorElement returned -// }, 'p.second-paragraph'); - -newParagraph2 = body.insert(d3Selection.creator('p'), function (d, i, g) { - let that: HTMLBodyElement = this; - // let that2: SVGElement = this; // fails, type mismatch - let datum: BodyDatum = d; - let index: number = i; - let group: HTMLBodyElement[] | d3Selection.ArrayLike = g; - console.log('Body element foo property: ', d.foo); // data of type BodyDatum - return this.children[0]; // this type HTMLBodyElement -}); - -newParagraph2 = body.insert( - // type - function (d, i, g) { - let that: HTMLBodyElement = this; - // let that2: SVGElement = this; // fails, type mismatch - let datum: BodyDatum = d; - let index: number = i; - let group: HTMLBodyElement[] | d3Selection.ArrayLike = g; - console.log('Body element foo property: ', d.foo); // data of type BodyDatum - return this.ownerDocument.createElement('p'); // this-type HTMLParagraphElement - }, - // before - function (d, i, g) { - let that: HTMLBodyElement = this; - // let that2: SVGElement = this; // fails, type mismatch - let datum: BodyDatum = d; - let index: number = i; - let group: HTMLBodyElement[] | d3Selection.ArrayLike = g; - console.log('Body element foo property: ', d.foo); // data of type BodyDatum - return this.children[0]; // this type HTMLBodyElement - }); // sort(...) ----------------------------------------------------------------------------- diff --git a/d3-selection/index.d.ts b/d3-selection/index.d.ts index 65703f66ff..1d0ab9472c 100644 --- a/d3-selection/index.d.ts +++ b/d3-selection/index.d.ts @@ -519,7 +519,7 @@ interface Selection( type: string | ValueFn, - before: string | ValueFn + before?: string | ValueFn ): Selection; /** diff --git a/googlemaps/google.maps-tests.ts b/googlemaps/google.maps-tests.ts index fd4e10f6e6..0be531a89f 100644 --- a/googlemaps/google.maps-tests.ts +++ b/googlemaps/google.maps-tests.ts @@ -141,19 +141,102 @@ var mapTypeStyle: google.maps.MapTypeStyle ={ stylers: [], }; -// https://developers.google.com/maps/documentation/javascript/adding-a-google-map -function initMap() { - var uluru = {lat: -25.363, lng: 131.044}; +// https://developers.google.com/maps/documentation/javascript/markers +function initMap1() { + var myLatLng = {lat: -25.363, lng: 131.044}; + var map = new google.maps.Map(document.getElementById('map'), { zoom: 4, - center: uluru + center: myLatLng }); + var marker = new google.maps.Marker({ - position: uluru, + position: myLatLng, + map: map, + title: 'Hello World!' + }); +} + +var myLatlng = new google.maps.LatLng(-25.363882,131.044922); +var mapOptions = { + zoom: 4, + center: myLatlng +} +var map = new google.maps.Map(document.getElementById("map"), mapOptions); + +var marker = new google.maps.Marker({ + position: myLatlng, + title:"Hello World!" +}); + +// To add the marker to the map, call setMap(); +marker.setMap(map); + +marker.setMap(null); + +// The following example creates a marker in Stockholm, Sweden using a DROP +// animation. Clicking on the marker will toggle the animation between a BOUNCE +// animation and no animation. + +var marker: google.maps.Marker; + +function initMap2() { + var map = new google.maps.Map(document.getElementById('map'), { + zoom: 13, + center: {lat: 59.325, lng: 18.070} + }); + + marker = new google.maps.Marker({ + map: map, + draggable: true, + animation: google.maps.Animation.DROP, + position: {lat: 59.327, lng: 18.067} + }); + marker.addListener('click', toggleBounce); +} + +function toggleBounce() { + if (marker.getAnimation() !== null) { + marker.setAnimation(null); + } else { + marker.setAnimation(google.maps.Animation.BOUNCE); + } +} + +// In the following example, markers appear when the user clicks on the map. +// Each marker is labeled with a single alphabetical character. +var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; +var labelIndex = 0; + +function initialize() { + var bangalore = { lat: 12.97, lng: 77.59 }; + var map = new google.maps.Map(document.getElementById('map'), { + zoom: 12, + center: bangalore + }); + + // This event listener calls addMarker() when the map is clicked. + google.maps.event.addListener(map, 'click', function(event: any) { + addMarker(event.latLng, map); + }); + + // Add a marker at the center of the map. + addMarker(bangalore, map); +} + +// Adds a marker to the map. +function addMarker(location: google.maps.LatLngLiteral, map: google.maps.Map) { + // Add the marker at the clicked location, and add the next-available label + // from the array of alphabetical characters. + var marker = new google.maps.Marker({ + position: location, + label: labels[labelIndex++ % labels.length], map: map }); } +google.maps.event.addDomListener(window, 'load', initialize); + /***** OverlayView *****/ // https://developers.google.com/maps/documentation/javascript/customoverlays var div = document.createElement('div'); @@ -183,4 +266,4 @@ var rectangle = new google.maps.Rectangle({ east: -116.234, west: -116.251 } -}); \ No newline at end of file +}); diff --git a/googlemaps/index.d.ts b/googlemaps/index.d.ts index f19480f034..fefca3ea89 100644 --- a/googlemaps/index.d.ts +++ b/googlemaps/index.d.ts @@ -1,6 +1,6 @@ // Type definitions for Google Maps JavaScript API 3.25 // Project: https://developers.google.com/maps/ -// Definitions by: Folia A/S , Chris Wrench , Kiarash Ghiaseddin +// Definitions by: Folia A/S , Chris Wrench , Kiarash Ghiaseddin , Grant Hutchins // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /* @@ -30,7 +30,7 @@ THE SOFTWARE. declare namespace google.maps { /***** Map *****/ export class Map extends MVCObject { - constructor(mapDiv: Element, opts?: MapOptions); + constructor(mapDiv: Element|null, opts?: MapOptions); fitBounds(bounds: LatLngBounds|LatLngBoundsLiteral): void; getBounds(): LatLngBounds; getCenter(): LatLng; @@ -536,14 +536,14 @@ declare namespace google.maps { getTitle(): string; getVisible(): boolean; getZIndex(): number; - setAnimation(animation: Animation): void; + setAnimation(animation: Animation|null): void; setAttribution(attribution: Attribution): void; setClickable(flag: boolean): void; setCursor(cursor: string): void; setDraggable(flag: boolean): void; setIcon(icon: string|Icon|Symbol): void; setLabel(label: string|MarkerLabel): void; - setMap(map: Map|StreetViewPanorama): void; + setMap(map: Map|StreetViewPanorama|null): void; setOpacity(opacity: number): void; setOptions(options: MarkerOptions): void; setPlace(place: Place): void; diff --git a/googlemaps/tsconfig.json b/googlemaps/tsconfig.json index dc12fbf795..0382e30210 100644 --- a/googlemaps/tsconfig.json +++ b/googlemaps/tsconfig.json @@ -4,7 +4,7 @@ "target": "es6", "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" @@ -17,4 +17,4 @@ "index.d.ts", "google.maps-tests.ts" ] -} \ No newline at end of file +} diff --git a/js-quantities/index.d.ts b/js-quantities/index.d.ts index a2e3c2d96c..5d4a8df304 100644 --- a/js-quantities/index.d.ts +++ b/js-quantities/index.d.ts @@ -1,79 +1,73 @@ -// Type definitions for JS-quantities +// Type definitions for JS-quantities 1.6 // Project: http://gentooboontoo.github.io/js-quantities/ -// Definitions by: William Comartin +// Definitions by: William Rummler // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -declare var Qty: QtyModule.QtyStatic; - -declare namespace QtyModule { - interface QtyStatic { - (value: string): Qty; - (value: number): Qty; - (value: number, unit: string): Qty; - (value: Qty): Qty; - } - - interface Qty { - version: string; - - scalar: number; - baseScalar: number; - - parse(value: string): Qty; - - swiftConverter(srcUnits:string, dstUnits:string): (value:number) => number; - - getkinds(): string[]; - - getUnits(kind:string): string[]; - - getAliases(unitName:string): string[]; - - formatter(scalar:number, units:string):string; - - toFloat(): number; - - isUnitless(): boolean; - - isCompatible(other:string|Qty): boolean; - - isInverse(other:string|Qty): boolean - - kind(): string; - - isBase(): boolean; - - toBase(): Qty; +declare const Qty: Qty.Type; +declare interface Qty { + readonly numerator: string[]; + readonly denominator: string[]; + readonly scalar: number; + readonly baseScalar: number; + readonly initValue: string; units(): string; - - eq(other:Qty): boolean; - lt(other:Qty): boolean; - lte(other:Qty): boolean; - gt(other:Qty): boolean; - gte(other:Qty): boolean; - - toPrec(precQuantity: Qty|string|number): Qty; - - toString(targetUnitsOrMaxDecimalsOrPrec?:number|string|Qty, maxDecimals?: number): string; - - format(targetUnits?:string, formatter?:(scalar:number, units:string) => string): string; - - compareTo(other:Qty|string): number; - - same(other: Qty): boolean; - + isCompatible(value: Qty.UnitSource): boolean; + kind(): string; + isUnitless(): boolean; + isBase(): boolean; + toBase(): Qty; + toFloat(): number; + to(value: Qty.UnitSource): Qty; inverse(): Qty; + eq(value: Qty.UnitSource): boolean; + same(value: Qty.UnitSource): boolean; + lt(value: Qty.UnitSource): boolean; + lte(value: Qty.UnitSource): boolean; + gt(value: Qty.UnitSource): boolean; + gte(value: Qty.UnitSource): boolean; + compareTo(value: Qty): Qty.ComparisonResult; + add(value: Qty.Source): Qty; + sub(value: Qty.Source): Qty; + mul(value: Qty.Source): Qty; + div(value: Qty.Source): Qty; + toPrec(value: Qty.Source): Qty; + toString(valueOrPrecision?: Qty.Source): string; + toString(value: string, precision: number): string; + format(formatter?: Qty.Formatter): string; + format(value: string, formatter?: Qty.Formatter): string; +} - isDegrees(): boolean; +declare namespace Qty { - isTemperature(): boolean; + interface Type { + (value: Source): Qty; + (value: number, unit: string): Qty; + new (value: Source): Qty; + new (value: number, unit: string): Qty; + parse(value: string): Qty; + getKinds(): string[]; + getUnits(kind?: string): string[]; + getAliases(unit: string): string[]; + swiftConverter(sourceUnit: string, targetUnit: string): Converter; + formatter: Formatter; + readonly Error: any; + mulSafe(n1: number, n2: number): number; + divSafe(n1: number, n2: number): number; + } - to(other:string|Qty): Qty; + interface Converter { + (sourceValue: number): number; + (sourceValues: number[]): number[]; + } - add(other:string|Qty): Qty; - sub(other:string|Qty): Qty; - mul(other:number|string|Qty): Qty; - div(other:number|string|Qty): Qty; - } -} \ No newline at end of file + type Formatter = (scalar: number, unit: string) => string; + + type ComparisonResult = -1 | 0 | 1; + + type Source = UnitSource | number; + + type UnitSource = Qty | string; +} + +export default Qty; diff --git a/js-quantities/js-quantities-tests.ts b/js-quantities/js-quantities-tests.ts index c09867634a..b1916bb626 100644 --- a/js-quantities/js-quantities-tests.ts +++ b/js-quantities/js-quantities-tests.ts @@ -1,7 +1,1502 @@ -var Val1 = Qty('1 m') +import "../jasmine"; +import Qty from "."; -var Val2 = Qty(1); +// From project readme -var Val3 = Qty(1, 'm'); +let qty: Qty; -var Val4 = Qty(Val1); \ No newline at end of file +qty = new Qty('23 ft'); // constructor +qty = Qty('23 ft'); // factory + +qty = new Qty(124, 'cm'); // => 1.24 meter +qty = Qty(124, 'cm'); // => 1.24 meter + +qty = Qty('1m'); // => 1 meter +qty = Qty('m'); // => 1 meter (scalar defaults to 1) + +qty = Qty('1 N*m'); +qty = Qty('1 N m'); // * is optional + +qty = Qty('1 m/s'); + +qty = Qty('1 m^2/s^2'); +qty = Qty('1 m^2 s^-2'); // negative powers +qty = Qty('1 m2 s-2'); // ^ is optional + +qty = Qty('1 m^2 kg^2 J^2/s^2 A'); + +qty = Qty('1.5'); // unitless quantity +qty = Qty(1.5); // number as initializing value + +qty = Qty('1 attoparsec/microfortnight'); + +let qtyCopy: Qty; + +qtyCopy = Qty(qty); // quantity could be copied when used as initializing value + +Qty.parse('1 m'); // => 1 meter +Qty.parse('foo'); // => null + +Qty.getKinds(); // => Array of names of every well-known kind of units + +Qty.getUnits('currency'); // => [ 'dollar', 'cents' ] +// Or all alphabetically sorted +Qty.getUnits(); // => [ 'acre','Ah','ampere','AMU','angstrom'] + +Qty.getAliases('m'); // => [ 'm', 'meter', 'meters', 'metre', 'metres' ] + +const qty1 = Qty('1m'); +const qty2 = Qty('2m'); + +qty1.isCompatible(qty2); // => true or false + +qty.kind(); // => 'length', 'area', etc... + +qty.isUnitless(); // => true or false +qty.isBase(); // => true if quantity is represented with base units + +qty.toBase(); // converts to SI units (10 cm => 0.1 m) (new instance) + +qty.toFloat(); // returns scalar of unitless quantity (otherwise throws error) + +qty.to('m'); // converts quantity to meter if compatible or throws an error (new instance) +qty1.to(qty2); // converts quantity to same unit of qty2 if compatible or throws an error (new instance) + +qty.inverse(); // converts quantity to its inverse ('100 m/s' => '.01 s/m') +// Inverses can be used, but there is no special checking to +// rename the units +Qty('10ohm').inverse(); // '.1/ohm' (not '.1S', although they are equivalent) +// however, the 'to' command will convert between inverses also +Qty('10ohm').to('S'); // '.1S' + +var convert = Qty.swiftConverter('m/h', 'ft/s'); // Configures converter + +// Converting single value +var converted = convert(2500); // => 2.278.. + +// Converting large array of values +var convertedSerie = convert([2500, 5000]); // => [2.278.., 4.556.., ...] + +qty1.eq(qty2); // => true if both quantities are equal (1m == 100cm => true) +qty1.same(qty2); // => true if both quantities are same (1m == 100cm => false) +qty1.lt(qty2); // => true if qty1 is stricty less than qty2 +qty1.lte(qty2); // => true if qty1 is less than or equal to qty2 +qty1.gt(qty2); // => true if qty1 is stricty greater than qty2 +qty1.gte(qty2); // => true if qty1 is greater than or equal to qty2 + +qty1.compareTo(qty2); // => -1 if qty1 < qty2, => 0 if qty1 == qty2, => 1 if qty1 > qty2 + +qty = Qty('5.17 ft'); +qty.toPrec('ft'); // => 5 ft +qty.toPrec('0.5 ft'); // => 5 ft +qty.toPrec('0.25 ft'); // => 5.25 ft +qty.toPrec('0.1 ft'); // => 5.2 ft +qty.toPrec('0.05 ft'); // => 5.15 ft +qty.toPrec('0.01 ft'); // => 5.17 ft +qty.toPrec('0.00001 ft'); // => 5.17 ft +qty.toPrec('2 ft'); // => 6 ft +qty.toPrec('2'); // => 6 ft + +qty = Qty('6.3782 m'); +qty.toPrec('dm'); // => 6.4 m +qty.toPrec('cm'); // => 6.38 m +qty.toPrec('mm'); // => 6.378 m +qty.toPrec('5 cm'); // => 6.4 m +qty.toPrec('10 m'); // => 10 m +qty.toPrec(0.1); // => 6.3 m + +qty = Qty('1.146 MPa'); +qty.toPrec('0.1 bar'); // => 1.15 MPa + +qty = Qty('1.146 MPa'); +qty.toString(); // => '1.146 MPa' + +qty = Qty('1.146 MPa'); +qty.toString('bar'); // => '11.46 bar' +qty.to('bar').toString(); // => '11.46 bar' + +qty = Qty('1.146 MPa'); +qty.toPrec(0.1).toString(); // => '1.1 MPa' +qty.to('bar').toPrec(0.1).toString(); // => '11.5 bar' + +qty = Qty('1.1234 m'); +qty.format(); // same units, default formatter => '1.234 m' +qty.format('cm'); // converted to 'cm', default formatter => '123.45 cm' + +var configurableRoundingFormatter = function (maxDecimals: number) { + return function (scalar: number, units: string) { + var pow = Math.pow(10, maxDecimals); + var rounded = Math.round(scalar * pow) / pow; + + return rounded + ' ' + units; + }; +}; + +qty = Qty('1.1234 m'); + +// same units, custom formatter => '1.12 m' +qty.format(configurableRoundingFormatter(2)); + +// convert to 'cm', custom formatter => '123.4 cm' +qty.format('cm', configurableRoundingFormatter(1)); + +Qty.formatter = configurableRoundingFormatter(2); +qty = Qty('1.1234 m'); +qty.format(); // same units, current default formatter => '1.12 m' + +Qty('37 tempC').to('tempF'); // => 98.6 tempF + +let scalar: number = 42; + +Qty('100 tempC').add('10 degC'); // 110 tempC +Qty('100 tempC').sub('10 degC'); // 90 tempC +Qty('100 tempC').add('50 tempC'); // throws error +Qty('100 tempC').sub('50 tempC'); // 50 degC +Qty('50 tempC').sub('100 tempC'); // -50 degC +Qty('100 tempC').mul(scalar); // 100*scalar tempC +Qty('100 tempC').div(scalar); // 100/scalar tempC +Qty('100 tempC').mul(qty); // throws error +Qty('100 tempC').div(qty); // throws error +Qty('100 tempC*unit'); // throws error +Qty('100 tempC/unit'); // throws error +Qty('100 unit/tempC'); // throws error +Qty('100 tempC').inverse(); // throws error + +Qty('100 tempC').to('degC'); // => 100 degC + +Qty('100 degC').to('tempC'); // => -173.15 tempC + +Qty('0 tempC').add('100 degC'); // => 100 tempC + +try { + // code triggering an error inside JS-quantities +} catch (e) { + if (e instanceof Qty.Error) { + // ... + } else { + // ... + } +} + +// From project spec + +describe("js-quantities", function () { + "use strict"; + + describe("initialization", function () { + it("should create unit only", function () { + var qty = Qty("m"); + expect(qty.numerator).toEqual([""]); + expect(qty.scalar).toBe(1); + }); + + it("should create unitless", function () { + var qty = Qty("1"); + expect(qty.toFloat()).toBe(1); + expect(qty.numerator).toEqual(["<1>"]); + expect(qty.denominator).toEqual(["<1>"]); + qty = Qty("1.5"); + expect(qty.toFloat()).toBe(1.5); + expect(qty.numerator).toEqual(["<1>"]); + expect(qty.denominator).toEqual(["<1>"]); + }); + + it("should create unitless from numbers", function () { + var qty = Qty(1.5); + expect(qty.toFloat()).toBe(1.5); + expect(qty.numerator).toEqual(["<1>"]); + expect(qty.denominator).toEqual(["<1>"]); + }); + + it("should create from numbers with explicit units", function () { + var qty = Qty(1.5, "m"); + expect(qty.scalar).toBe(1.5); + expect(qty.numerator).toEqual([""]); + expect(qty.denominator).toEqual(["<1>"]); + }); + + it("temperatures should have base unit in kelvin", function () { + var qty = Qty("1 tempK").toBase(); + expect(qty.scalar).toBe(1); + expect(qty.units()).toBe("tempK"); + + qty = Qty("1 tempR").toBase(); + expect(qty.scalar).toBe(5 / 9); + expect(qty.units()).toBe("tempK"); + + qty = Qty("0 tempC").toBase(); + expect(qty.scalar).toBe(273.15); + expect(qty.units()).toBe("tempK"); + + qty = Qty("0 tempF").toBase(); + expect(qty.scalar).toBeCloseTo(255.372, 3); + expect(qty.units()).toBe("tempK"); + }); + + it("temperature degrees should have base unit in kelvin", function () { + var qty = Qty("1 degK").toBase(); + expect(qty.scalar).toBe(1); + expect(qty.units()).toBe("degK"); + + qty = Qty("1 degR").toBase(); + expect(qty.scalar).toBe(5 / 9); + expect(qty.units()).toBe("degK"); + + qty = Qty("1 degC").toBase(); + expect(qty.scalar).toBe(1); + expect(qty.units()).toBe("degK"); + + qty = Qty("1 degF").toBase(); + expect(qty.scalar).toBe(5 / 9); + expect(qty.units()).toBe("degK"); + }); + + it("should not create temperatures below absolute zero", function () { + expect(function () { Qty("-1 tempK"); }).toThrow("Temperatures must not be less than absolute zero"); + expect(function () { Qty("-273.16 tempC"); }).toThrow("Temperatures must not be less than absolute zero"); + expect(function () { Qty("-459.68 tempF"); }).toThrow("Temperatures must not be less than absolute zero"); + expect(function () { Qty("-1 tempR"); }).toThrow("Temperatures must not be less than absolute zero"); + + var qty = Qty("1 tempK"); + expect(function () { qty.mul("-1"); }).toThrow("Temperatures must not be less than absolute zero"); + + qty = Qty("0 tempK"); + expect(function () { qty.sub("1 degK"); }).toThrow("Temperatures must not be less than absolute zero"); + + qty = Qty("-273.15 tempC"); + expect(function () { qty.sub("1 degC"); }).toThrow("Temperatures must not be less than absolute zero"); + + qty = Qty("-459.67 tempF"); + expect(function () { qty.sub("1 degF"); }).toThrow("Temperatures must not be less than absolute zero"); + + qty = Qty("0 tempR"); + expect(function () { qty.sub("1 degR"); }).toThrow("Temperatures must not be less than absolute zero"); + }); + + it("should create simple", function () { + var qty = Qty("1m"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual([""]); + expect(qty.denominator).toEqual(["<1>"]); + }); + + it("should create negative", function () { + var qty = Qty("-1m"); + expect(qty.scalar).toBe(-1); + expect(qty.numerator).toEqual([""]); + expect(qty.denominator).toEqual(["<1>"]); + }); + + it("should create compound", function () { + var qty = Qty("1 N*m"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["", ""]); + expect(qty.denominator).toEqual(["<1>"]); + }); + + it("should create pressure units in term of height of water", function () { + var qty = Qty("1 inH2O"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual([""]); + + qty = Qty("1 cmH2O"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual([""]); + }); + + it("should create with denominator", function () { + var qty = Qty("1 m/s"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual([""]); + expect(qty.denominator).toEqual([""]); + }); + + it("should create with denominator only", function () { + var qty = Qty("1 /s"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["<1>"]); + expect(qty.denominator).toEqual([""]); + + qty = Qty("1 1/s"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["<1>"]); + expect(qty.denominator).toEqual([""]); + + qty = Qty("1 s^-1"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["<1>"]); + expect(qty.denominator).toEqual([""]); + }); + + it("should create with powers", function () { + var qty = Qty("1 m^2/s^2"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["", ""]); + expect(qty.denominator).toEqual(["", ""]); + qty = Qty("1 m^2 kg^2 J^2/s^2"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["", "", "", "", "", ""]); + expect(qty.denominator).toEqual(["", ""]); + qty = Qty("1 m^2/s^2*J^3"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["", ""]); + expect(qty.denominator).toEqual(["", "", "", "", ""]); + }); + + it("should create with zero power", function () { + var qty = Qty("1 m^0"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["<1>"]); + expect(qty.denominator).toEqual(["<1>"]); + }); + + it("should create with negative powers", function () { + var qty = Qty("1 m^2 s^-2"); + expect(qty.scalar).toBe(1); + expect(qty.numerator).toEqual(["", ""]); + expect(qty.denominator).toEqual(["", ""]); + expect(qty.same(Qty("1 m^2/s^2"))).toBe(true); + }); + + it("should accept powers without ^ syntax (simple)", function () { + var qty1 = Qty("1 m2"); + var qty2 = Qty("1 m^2"); + expect(qty1.eq(qty2)).toBe(true); + }); + + it("should accept powers without ^ syntax (negative power)", function () { + var qty1 = Qty("1 m-2"); + var qty2 = Qty("1 m^-2"); + expect(qty1.eq(qty2)).toBe(true); + }); + + it("should accept powers without ^ syntax (compound)", function () { + var qty1 = Qty("1 m^2 kg^2 J^2/s^2"); + var qty2 = Qty("1 m2 kg2 J2/s2"); + expect(qty1.eq(qty2)).toBe(true); + }); + + it("should accept powers without ^ syntax (compound and negative power)", function () { + var qty1 = Qty("1 m^2 kg^2 J^2 s^-2"); + var qty2 = Qty("1 m2 kg2 J2 s-2"); + expect(qty1.eq(qty2)).toBe(true); + }); + + it("should throw 'Unit not recognized' error when initializing with an invalid unit", function () { + expect(function () { Qty("aa"); }).toThrow("Unit not recognized"); + expect(function () { Qty("m/aa"); }).toThrow("Unit not recognized"); + expect(function () { Qty("m-"); }).toThrow("Unit not recognized"); + expect(function () { Qty("N*m"); }).not.toThrow("Unit not recognized"); + // mm is millimeter, but mmm is not a valid unit + expect(function () { Qty("mmm"); }).toThrow("Unit not recognized"); + }); + + it("should accept empty string as unitless 1", function () { + expect(Qty("").same(Qty("1"))).toBe(true); + expect(Qty(" ").same(Qty("1"))).toBe(true); + }); + + it("should throw error when passing NaN", function () { + expect( + function () { Qty(NaN); } + ).toThrow("Only string, number or quantity accepted as single " + + "initialization value"); + }); + + it("should throw 'Unit not recognized' error when initializing with an invalid unit and a 0 exponent", function () { + expect(function () { Qty("3p0"); }).toThrow("Unit not recognized"); + expect(function () { Qty("3p-0"); }).toThrow("Unit not recognized"); + }); + + it("should set baseScalar", function () { + var qty = Qty("0.018 MPa"); + expect(qty.baseScalar).toBe(18000); + + qty = Qty("66 cm3"); + expect(qty.baseScalar).toBe(0.000066); + }); + + it("should keep init value as is", function () { + var initValue = " 66 cm3 "; + var qty = Qty(initValue); + + expect(qty.initValue).toEqual(initValue); + }); + + it("should allow whitespace-wrapped value", function () { + expect(function () { Qty(" 2 MPa "); }).not.toThrow(); + }); + + it("should allow whitespaces between sign and scalar", function () { + var qty = Qty("- 1m"); + + expect(qty.scalar).toEqual(-1); + expect(qty.units()).toEqual("m"); + }); + + it("should throw an error when parsing negative quantity " + + "with no scalar", function () { + expect(function () { Qty("-m"); }).toThrow("Unit not recognized"); + }); + }); + + describe("isCompatible", function () { + it("should return true with compatible quantities", function () { + var qty1 = Qty("1 m*kg/s"); + var qty2 = Qty("1 in*pound/min"); + expect(qty1.isCompatible(qty2)).toBe(true); + qty2 = Qty("1 in/min"); + expect(qty1.isCompatible(qty2)).toBe(false); + }); + + it("should return true with dimensionless quantities", function () { + var qty1 = Qty("1"); + var qty2 = Qty("2"); + expect(qty1.isCompatible(qty2)).toBe(true); + }); + }); + + describe("conversion", function () { + it("should convert to base units", function () { + var qty = Qty("100 cm"); + expect(qty.toBase().scalar).toBe(1); + expect(qty.toBase().units()).toBe("m"); + qty = Qty("10 cm"); + expect(qty.toBase().scalar).toBe(0.1); + expect(qty.toBase().units()).toBe("m"); + qty = Qty("0.3 mm^2 ms^-2"); + expect(qty.toBase().scalar).toBe(0.3); + expect(qty.toBase().units()).toBe("m2/s2"); + }); + + it("should convert to compatible units", function () { + var qty = Qty("10 cm"); + expect(qty.to("ft").scalar).toBe(Qty.divSafe(0.1, 0.3048)); + qty = Qty("2m^3"); + expect(qty.to("l").scalar).toBe(2000); + + qty = Qty("10 cm"); + expect(qty.to(Qty("m")).scalar).toBe(0.1); + expect(qty.to(Qty("20m")).scalar).toBe(0.1); + + qty = Qty("1 m3"); + expect(qty.to("cm3").scalar).toBe(1000000); + + qty = Qty("1 cm3"); + expect(qty.to("mm3").scalar).toBe(1000); + + qty = Qty("550 cm3"); + expect(qty.to("cm^3").scalar).toBe(550); + + qty = Qty("0.000773 m3"); + expect(qty.to("cm^3").scalar).toBe(773); + }); + + describe('percents', function () { + it("should convert from % to unitless", function () { + expect(Qty("10 %").to("").same(Qty("0.1"))).toBe(true); + }); + + it("should convert from unitless to %", function () { + expect(Qty("0.1").to("%").same(Qty("10 %"))).toBe(true); + }); + }); + + it("should convert temperatures to compatible units", function () { + var qty = Qty("0 tempK"); + expect(qty.to("tempC").scalar).toBe(-273.15); + + qty = Qty("0 tempF"); + expect(qty.to("tempK").scalar).toBeCloseTo(255.372, 3); + + qty = Qty("32 tempF"); + expect(qty.to("tempC").scalar).toBe(0); + + qty = Qty("0 tempC"); + expect(qty.to("tempF").scalar).toBeCloseTo(32, 10); + }); + + it("should convert temperature degrees to compatible units", function () { + var qty = Qty("0 degK"); + expect(qty.to("degC").scalar).toBe(0); + + qty = Qty("1 degK/s"); + expect(qty.to("degC/min").scalar).toBe(60); + + qty = Qty("100 cm/degF"); + expect(qty.to("m/degF").scalar).toBe(1); + + qty = Qty("10 degC"); + expect(qty.to("degF").scalar).toBe(18); + }); + + it("should convert temperature degrees to temperatures", function () { + // according to ruby-units, deg -> temp conversion adds the degress to 0 kelvin before converting + var qty = Qty("100 degC"); + expect(qty.to("tempC").scalar).toBeCloseTo(-173.15, 10); + + qty = Qty("273.15 degC"); + expect(qty.to("tempC").scalar).toBe(0); + + qty = Qty("460.67 degF"); + expect(qty.to("tempF").scalar).toBeCloseTo(1, 10); + }); + + it("should convert temperatures to temperature degrees", function () { + // according to ruby-units, temp -> deg conversion always uses the 0 relative degrees + var qty = Qty("100 tempC"); + expect(qty.to("degC").scalar).toBe(100); + + qty = Qty("0 tempK"); + expect(qty.to("degC").scalar).toBe(0); + + qty = Qty("0 tempF"); + expect(qty.to("degK").scalar).toBe(0); + + qty = Qty("18 tempF"); + expect(qty.to("degC").scalar).toBe(10); + + qty = Qty("10 tempC"); + expect(qty.to("degF").scalar).toBe(18); + }); + + it("should calculate inverses", function () { + var qty = Qty("1 ohm"); + var result = qty.to("siemens"); + expect(result.scalar).toBe(1); + expect(result.kind()).toBe("conductance"); + + qty = Qty("10 ohm"); + result = qty.to("siemens"); + expect(result.scalar).toBe(0.1); + expect(result.kind()).toBe("conductance"); + + qty = Qty("10 siemens"); + result = qty.to("ohm"); + expect(result.scalar).toBe(0.1); + expect(result.kind()).toBe("resistance"); + + qty = Qty("10 siemens"); + result = qty.inverse(); + expect(result.eq(".1 ohm")).toBe(true); + expect(result.kind()).toBe("resistance"); + + // cannot inverse a quantity with a 0 scalar + qty = Qty("0 ohm"); + expect(function () { qty.inverse(); }).toThrow("Divide by zero"); + + qty = Qty("10 ohm").inverse(); + result = qty.to("S"); + expect(result.scalar).toBe(0.1); + expect(result.kind()).toBe("conductance"); + + qty = Qty("12 in").inverse(); + // TODO: Swap toBeCloseTo with toBe once divSafe is fixed + expect(qty.to("ft").scalar).toBeCloseTo(1, 10); + }); + + it("should return itself if target units are the same", function () { + var qty = Qty("123 cm3"); + + expect(qty.to("cm3")).toBe(qty); + expect(qty.to("cm^3")).toBe(qty); + + qty = Qty("123 mcg"); + expect(qty.to("ug")).toBe(qty); + }); + + it("should be cached", function () { + var qty = Qty("100 m"), + converted = qty.to("ft"); + + expect(qty.to("ft") === converted).toBe(true); + }); + }); + + describe("comparison", function () { + it("should return true when comparing equal quantities", function () { + var qty1 = Qty("1cm"); + var qty2 = Qty("10mm"); + expect(qty1.eq(qty2)).toBe(true); + }); + + it("should compare compatible quantities", function () { + var qty1 = Qty("1cm"); + var qty2 = Qty("1mm"); + var qty3 = Qty("10mm"); + var qty4 = Qty("28A"); + expect(qty1.compareTo(qty2)).toBe(1); + expect(qty2.compareTo(qty1)).toBe(-1); + expect(qty1.compareTo(qty3)).toBe(0); + expect(function () { qty1.compareTo(qty4); }).toThrow("Incompatible units"); + + expect(qty1.lt(qty2)).toBe(false); + expect(qty1.lt(qty3)).toBe(false); + expect(qty1.lte(qty3)).toBe(true); + expect(qty1.gte(qty3)).toBe(true); + expect(qty1.gt(qty2)).toBe(true); + expect(qty2.gt(qty1)).toBe(false); + }); + + it("should compare identical quantities", function () { + var qty1 = Qty("1cm"); + var qty2 = Qty("1cm"); + var qty3 = Qty("10mm"); + expect(qty1.same(qty2)).toBe(true); + expect(qty1.same(qty3)).toBe(false); + }); + + it("should accept strings as parameter", function () { + var qty = Qty("1 cm"); + expect(qty.lt("0.5 cm")).toBe(false); + expect(qty.lte("1 cm")).toBe(true); + expect(qty.gte("3 mm")).toBe(true); + expect(qty.gt("5 m")).toBe(false); + }); + + }); + + describe("non-ASCII character", function () { + describe("µ", function () { + it("should be supported as prefix", function () { + // µ as greek letter + expect(Qty("1 \u03BCm").eq(Qty("1 um"))).toBe(true); + // µ as micro sign + expect(Qty("1 \u00B5m").eq(Qty("1 um"))).toBe(true); + }); + }); + + describe("Ω", function () { + it("should be accepted as unit for ohm", function () { + // Ω as greek letter + expect(Qty("1 \u03A9").eq(Qty("1 ohm"))).toBe(true); + // Ω as ohm sign + expect(Qty("1 \u2126").eq(Qty("1 ohm"))).toBe(true); + }); + }); + }); + + describe("math", function () { + + it("should add quantities", function () { + var qty1 = Qty("2.5m"); + var qty2 = Qty("3m"); + expect(qty1.add(qty2).scalar).toBe(5.5); + + expect(qty1.add("3m").scalar).toBe(5.5); + + qty2 = Qty("3cm"); + var result = qty1.add(qty2); + expect(result.scalar).toBe(2.53); + expect(result.units()).toBe("m"); + + result = qty2.add(qty1); + expect(result.scalar).toBe(253); + expect(result.units()).toBe("cm"); + + // make sure adding 2 of the same non-base units work + result = Qty("5cm").add("3cm"); + expect(result.scalar).toBe(8); + expect(result.units()).toBe("cm"); + }); + + it("should fail to add unlike quantities", function () { + var qty1 = Qty("3m"); + var qty2 = Qty("2s"); + expect(function () { qty1.add(qty2); }).toThrow("Incompatible units"); + expect(function () { qty2.add(qty1); }).toThrow("Incompatible units"); + }); + + it("should fail to add inverse quantities", function () { + var qty1 = Qty("10S"); + var qty2 = qty1.inverse(); + expect(function () { qty1.add(qty2); }).toThrow("Incompatible units"); + expect(function () { qty2.add(qty1); }).toThrow("Incompatible units"); + + qty1 = Qty("10S"); + qty2 = Qty("0.1ohm"); + expect(function () { qty1.add(qty2); }).toThrow("Incompatible units"); + expect(function () { qty2.add(qty1); }).toThrow("Incompatible units"); + }); + + it("should subtract quantities", function () { + var qty1 = Qty("2.5m"); + var qty2 = Qty("3m"); + expect(qty1.sub(qty2).scalar).toBe(-0.5); + + expect(qty1.sub("2m").scalar).toBe(0.5); + expect(qty1.sub("-2m").scalar).toBe(4.5); + + qty2 = Qty("3cm"); + var result = qty1.sub(qty2); + expect(result.scalar).toBe(2.47); + expect(result.units()).toBe("m"); + + result = qty2.sub(qty1); + expect(result.scalar).toBe(-247); + expect(result.units()).toBe("cm"); + }); + + it("should fail to subtract unlike quantities", function () { + var qty1 = Qty("3m"); + var qty2 = Qty("2s"); + expect(function () { qty1.sub(qty2); }).toThrow("Incompatible units"); + expect(function () { qty2.sub(qty1); }).toThrow("Incompatible units"); + }); + + it("should fail to subtract inverse quantities", function () { + var qty1 = Qty("10S"); + var qty2 = qty1.inverse(); + expect(function () { qty1.sub(qty2); }).toThrow("Incompatible units"); + expect(function () { qty2.sub(qty1); }).toThrow("Incompatible units"); + + qty1 = Qty("10S"); + qty2 = Qty("0.1ohm"); + expect(function () { qty1.sub(qty2); }).toThrow("Incompatible units"); + expect(function () { qty2.sub(qty1); }).toThrow("Incompatible units"); + }); + + it("should multiply quantities", function () { + var qty1 = Qty("2.5m"); + var qty2 = Qty("3m"); + var result = qty1.mul(qty2); + expect(result.scalar).toBe(7.5); + expect(result.units()).toBe("m2"); + expect(result.kind()).toBe("area"); + + qty2 = Qty("3cm"); + result = qty1.mul(qty2); + expect(result.scalar).toBe(0.075); + expect(result.units()).toBe("m2"); + + result = qty2.mul(qty1); + expect(result.scalar).toBe(750); + expect(result.units()).toBe("cm2"); + + result = qty1.mul(3.5); + expect(result.scalar).toBe(8.75); + expect(result.units()).toBe("m"); + + result = qty1.mul(0); + expect(result.scalar).toBe(0); + expect(result.units()).toBe("m"); + + result = qty1.mul(Qty("0m")); + expect(result.scalar).toBe(0); + expect(result.units()).toBe("m2"); + + qty2 = Qty("1.458 m"); + result = qty1.mul(qty2); + expect(result.scalar).toBe(3.645); + expect(result.units()).toBe("m2"); + }); + + it("should multiply unlike quantities", function () { + var qty1 = Qty("2.5 m"); + var qty2 = Qty("3 N"); + + var result = qty1.mul(qty2); + expect(result.scalar).toBe(7.5); + + qty1 = Qty("2.5 m^2"); + qty2 = Qty("3 kg/m^2"); + + result = qty1.mul(qty2); + expect(result.scalar).toBe(7.5); + expect(result.units()).toBe("kg"); + }); + + it("should multiply inverse quantities", function () { + var qty1 = Qty("10S"); + var qty2 = Qty(".5S").inverse(); // 2/S + var qty3 = qty1.inverse(); // .1/S + + var result = qty1.mul(qty2); + expect(result.scalar).toBe(20); + expect(result.isUnitless()).toBe(true); + expect(result.units()).toBe(""); + // swapping operands should give the same outcome + result = qty2.mul(qty1); + expect(result.scalar).toBe(20); + expect(result.isUnitless()).toBe(true); + expect(result.units()).toBe(""); + + result = qty1.mul(qty3); + expect(result.scalar).toBe(1); + expect(result.isUnitless()).toBe(true); + expect(result.units()).toBe(""); + // swapping operands should give the same outcome + result = qty3.mul(qty1); + expect(result.scalar).toBe(1); + expect(result.isUnitless()).toBe(true); + expect(result.units()).toBe(""); + }); + + it("should divide quantities", function () { + var qty1 = Qty("2.5m"); + var qty2 = Qty("3m"); + var qty3 = Qty("0m"); + + expect(function () { qty1.div(qty3); }).toThrow("Divide by zero"); + expect(function () { qty1.div(0); }).toThrow("Divide by zero"); + expect(qty3.div(qty1).scalar).toBe(0); + + var result = qty1.div(qty2); + expect(result.scalar).toBe(2.5 / 3); + expect(result.units()).toBe(""); + expect(result.kind()).toBe("unitless"); + + var qty4 = Qty("3cm"); + result = qty1.div(qty4); + expect(result.scalar).toBe(2.5 / 0.03); + expect(result.units()).toBe(""); + + result = qty4.div(qty1); + expect(result.scalar).toBe(0.012); + expect(result.units()).toBe(""); + + result = qty1.div(3.5); + expect(result.scalar).toBe(2.5 / 3.5); + expect(result.units()).toBe("m"); + }); + + it("should divide unlike quantities", function () { + var qty1 = Qty("7.5kg"); + var qty2 = Qty("2.5m^2"); + + var result = qty1.div(qty2); + expect(result.scalar).toBe(3); + expect(result.units()).toBe("kg/m2"); + }); + + it("should divide inverse quantities", function () { + var qty1 = Qty("10 S"); + var qty2 = Qty(".5 S").inverse(); // 2/S + var qty3 = qty1.inverse(); // .1/S + + var result = qty1.div(qty2); + expect(result.scalar).toBe(5); + expect(result.units()).toBe("S2"); + + result = qty2.div(qty1); + expect(result.scalar).toBe(0.2); + expect(result.units()).toBe("1/S2"); + + result = qty1.div(qty3); + expect(result.scalar).toBe(100); + expect(result.units()).toBe("S2"); + + result = qty3.div(qty1); + expect(result.scalar).toBe(0.01); + expect(result.units()).toBe("1/S2"); + }); + + }); + + describe("math with temperatures", function () { + + it("should add temperature degrees", function () { + var qty = Qty("2degC"); + expect(qty.add("3degF").scalar).toBeCloseTo(11 / 3, 10); + expect(qty.add("-1degC").scalar).toBe(1); + + qty = Qty("2 degC"); + var result = qty.add("2 degF"); + expect(result.scalar).toBe(28 / 9); + expect(result.units()).toBe("degC"); + + qty = Qty("2degK"); + result = qty.add("3degC"); + expect(result.scalar).toBe(5); + expect(result.units()).toBe("degK"); + + qty = Qty("2degC"); + result = qty.add("2degK"); + expect(result.scalar).toBe(4); + expect(result.units()).toBe("degC"); + }); + + it("should not add two temperatures", function () { + var qty = Qty("2tempC"); + expect(function () { qty.add("1 tempF"); }).toThrow("Cannot add two temperatures"); + expect(function () { qty.add("1 tempC"); }).toThrow("Cannot add two temperatures"); + }); + + it("should add temperatures to degrees", function () { + var qty = Qty("2degC"); + var result = qty.add("3tempF"); + expect(result.scalar).toBe(33 / 5); + expect(result.units()).toBe("tempF"); + + result = qty.add("-1tempC"); + expect(result.scalar).toBe(1); + expect(result.units()).toBe("tempC"); + + qty = Qty("2 tempC"); + result = qty.add("2 degF"); + expect(result.scalar).toBe(28 / 9); + expect(result.units()).toBe("tempC"); + }); + + it("should subtract degrees from degrees", function () { + var qty = Qty("2degC"); + expect(qty.sub("1.5degK").scalar).toBe(0.5); + expect(qty.sub("-2degC").scalar).toBe(4); + expect(qty.sub("1degF").scalar).toBe(2 - 5 / 9); + expect(qty.sub("-1degC").scalar).toBe(3); + + var result = qty.sub("degC"); + expect(result.scalar).toBe(1); + expect(result.units()).toBe("degC"); + }); + + it("should subtract degrees from temperatures", function () { + var qty = Qty("2tempC"); + expect(qty.sub("1.5degK").scalar).toBe(0.5); + expect(qty.sub("-2degC").scalar).toBe(4); + expect(qty.sub("1degF").scalar).toBe(2 - 5 / 9); + expect(qty.sub("-1degC").scalar).toBe(3); + + var result = qty.sub("degC"); + expect(result.scalar).toBe(1); + expect(result.units()).toBe("tempC"); + }); + + it("should subtract temperatures from temperatures", function () { + var qty = Qty("2tempC"); + + var result = qty.sub("1.5tempK"); + expect(result.scalar).toBe(273.65); + expect(result.units()).toBe("degC"); + + result = qty.sub("-2tempC"); + expect(result.scalar).toBe(4); + expect(result.units()).toBe("degC"); + + result = qty.sub("32tempF"); + expect(result.scalar).toBe(2); + expect(result.units()).toBe("degC"); + }); + + it("should not subtract temperatures from degrees", function () { + var qty = Qty("2degC"); + expect(function () { qty.sub("1 tempF"); }).toThrow("Cannot subtract a temperature from a differential degree unit"); + expect(function () { qty.sub("1 tempC"); }).toThrow("Cannot subtract a temperature from a differential degree unit"); + }); + + it("should multiply temperature degrees", function () { + var qty = Qty("2degF"); + var result = qty.mul(3); + expect(result.scalar).toBe(6); + expect(result.units()).toBe("degF"); + + result = qty.mul("3degF"); + expect(result.scalar).toBe(6); + expect(result.units()).toBe("degF2"); + + // TODO: Should we convert degrees ("2 degK" to "degC") before we do the math? + qty = Qty("2degC"); + result = qty.mul("2degK"); + expect(result.scalar).toBe(4); + expect(result.units()).toBe("degC*degK"); + + qty = Qty("2degC"); + result = qty.mul("degF"); + expect(result.scalar).toBe(2); + expect(result.units()).toBe("degC*degF"); + }); + + it("should not multiply temperatures except by scalar", function () { + var qty = Qty("2tempF"); + expect(function () { qty.mul("1 tempC"); }).toThrow("Cannot multiply by temperatures"); + expect(function () { qty.mul("1 degC"); }).toThrow("Cannot multiply by temperatures"); + expect(function () { Qty("1 tempC*s"); }).toThrow("Cannot multiply by temperatures"); + + var result = qty.mul(2); + expect(result.scalar).toBe(4); + expect(result.units()).toBe("tempF"); + + result = Qty("2").mul(qty); + expect(result.scalar).toBe(4); + expect(result.units()).toBe("tempF"); + }); + + it("should multiply temperature degrees with unlike quantities", function () { + var qty1 = Qty("2.5 degF"); + var qty2 = Qty("3 m"); + + var result = qty1.mul(qty2); + expect(result.scalar).toBe(7.5); + + qty1 = Qty("2.5 degF"); + qty2 = Qty("3 kg/degF"); + + result = qty1.mul(qty2); + expect(result.scalar).toBe(7.5); + expect(result.units()).toBe("kg"); + }); + + it("should divide temperature degrees with unlike quantities", function () { + var qty1 = Qty("7.5degF"); + var qty2 = Qty("2.5m^2"); + + var result = qty1.div(qty2); + expect(result.scalar).toBe(3); + expect(result.units()).toBe("degF/m2"); + }); + + it("should divide temperature degree quantities", function () { + var qty = Qty("2.5 degF"); + + expect(function () { qty.div("0 degF"); }).toThrow("Divide by zero"); + expect(function () { qty.div(0); }).toThrow("Divide by zero"); + expect(Qty("0 degF").div(qty).scalar).toBe(0); + expect(Qty("0 degF").div(qty).units()).toBe(""); + + var result = qty.div("3 degF"); + expect(result.scalar).toBe(2.5 / 3); + expect(result.units()).toBe(""); + expect(result.kind()).toBe("unitless"); + + result = qty.div(3); + expect(result.scalar).toBe(2.5 / 3); + expect(result.units()).toBe("degF"); + expect(result.kind()).toBe("temperature"); + + // TODO: Should we convert "2 degC" to "degF" before we do the math? + result = qty.div("2 degC"); + expect(result.scalar).toBe(1.25); + expect(result.units()).toBe("degF/degC"); + }); + + it("should not divide with temperatures except by scalar", function () { + expect(function () { Qty("tempF").div("1 tempC"); }).toThrow("Cannot divide with temperatures"); + expect(function () { Qty("tempF").div("1 degC"); }).toThrow("Cannot divide with temperatures"); + expect(function () { Qty("2").div("tempF"); }).toThrow("Cannot divide with temperatures"); + expect(function () { Qty("2 tempF/s"); }).toThrow("Cannot divide with temperatures"); + expect(function () { Qty("2 s/tempF"); }).toThrow("Cannot divide with temperatures"); + + // inverse is division: 1/x + expect(function () { Qty("tempF").inverse(); }).toThrow("Cannot divide with temperatures"); + + var result = Qty("4 tempF").div(2); + expect(result.scalar).toBe(2); + expect(result.units()).toBe("tempF"); + }); + + }); + + describe("errors", function () { + it("should be instance of Qty.Error", function () { + try { + Qty("aa"); + } catch (e) { + expect(e instanceof Qty.Error).toBeTruthy(); + } + }); + }); + + describe("utility methods", function () { + + it("should accept string as parameter for compatibility tests", function () { + var qty = Qty("1 mm"); + + expect(qty.isCompatible("2 mm")).toBe(true); + expect(qty.isCompatible("2 mm^3")).toBe(false); + }); + + it("should return kind", function () { + var qty = Qty("1 mm"); + expect(qty.kind()).toBe("length"); + + qty = Qty("1 N"); + expect(qty.kind()).toBe("force"); + }); + + it("should know if a quantity is in base units", function () { + var qty = Qty("100 cm"); + expect(qty.isBase()).toBe(false); + + qty = Qty("1m"); + expect(qty.isBase()).toBe(true); + }); + + it("should return unit part of quantities", function () { + var qty = Qty("1"); + expect(qty.units()).toBe(""); + qty = Qty("1 /s"); + expect(qty.units()).toBe("1/s"); + qty = Qty("100 cm"); + expect(qty.units()).toBe("cm"); + qty = Qty("100 cm/s"); + expect(qty.units()).toBe("cm/s"); + qty = Qty("1 cm^2"); + expect(qty.units()).toBe("cm2"); + qty = Qty("1 cm^2/s^2"); + expect(qty.units()).toBe("cm2/s2"); + qty = Qty("1 cm^2*J^3/s^2*A^2"); + expect(qty.units()).toBe("cm2*J3/s2*A2"); + }); + + }); + + describe("toString", function () { + it("should generate readable human output", function () { + var qty = Qty("2m"); + expect(qty.toString()).toBe("2 m"); + expect(qty.toString("cm")).toBe("200 cm"); + expect(qty.toString("km")).toBe("0.002 km"); + expect(function () { qty.toString("A"); }).toThrow("Incompatible units"); + + qty = Qty("24.5m/s"); + expect(qty.toString()).toBe("24.5 m/s"); + expect(function () { qty.toString("m"); }).toThrow("Incompatible units"); + expect(qty.toString("km/h")).toBe("88.2 km/h"); + + qty = Qty("254kg/m^2"); + expect(qty.toString()).toBe("254 kg/m2"); + + qty = Qty("2"); + expect(qty.toString()).toBe("2"); + }); + + it("should round readable human output when max decimals is specified", function () { + var qty = (Qty("2m")).div(3); + expect(qty.toString("cm", 2)).toBe("66.67 cm"); + + qty = Qty("2.8m"); + expect(qty.toString("m", 0)).toBe("3 m"); + expect(qty.toString("cm", 0)).toBe("280 cm"); + qty = Qty("2.818m"); + expect(qty.toString("cm", 0)).toBe("282 cm"); + }); + + it("should round to max decimals", function () { + var qty = (Qty("2.987654321 m")); + + expect(qty.toString(3)).toBe("2.988 m"); + expect(qty.toString(0)).toBe("3 m"); + }); + + it("should round according to precision passed as quantity", function () { + var qty = Qty("5.17 ft"); + + expect(qty.toString(Qty("ft"))).toBe("5 ft"); + expect(qty.toString(Qty("2 ft"))).toBe("6 ft"); + expect(qty.toString(Qty("0.5 ft"))).toBe("5 ft"); + expect(qty.toString(Qty("0.1 ft"))).toBe("5.2 ft"); + expect(qty.toString(Qty("0.05 ft"))).toBe("5.15 ft"); + expect(qty.toString(Qty("0.01 ft"))).toBe("5.17 ft"); + expect(qty.toString(Qty("0.0001 ft"))).toBe("5.17 ft"); + }); + + it("should return same output with successive calls", function () { + var qty = Qty("123 cm3"); + expect(qty.toString("cm3", 0)).toBe("123 cm3"); + expect(qty.toString("cm3", 0)).toBe("123 cm3"); + }); + + it("should return identical output when called with no parameters or same units", function () { + var qty = Qty("123 cm3"); + expect(qty.toString()).toBe(qty.toString("cm3")); + }); + + }); + + describe("format", function () { + describe("provided default formatter", function () { + it("should be applied to output", function () { + var qty = (Qty("2.987654321 m")); + + expect(qty.format()).toBe("2.987654321 m"); + }); + }); + + describe("custom formatter", function () { + var roundingFormatter = function (maxDecimals: number) { + return function (scalar: number, units: string) { + var pow = Math.pow(10, maxDecimals); + var rounded = Math.round(scalar * pow) / pow; + + return rounded + " " + units; + }; + }; + + it("should be applied to output", function () { + var qty = (Qty("2.987654321 m")); + + expect(qty.format(roundingFormatter(3))).toBe("2.988 m"); + expect(qty.format(roundingFormatter(0))).toBe("3 m"); + }); + + it("should be applied after conversion to target units", function () { + var qty = (Qty("2m")).div(3); + expect(qty.format("cm", roundingFormatter(2))).toBe("66.67 cm"); + + var intRoundingFormatter = roundingFormatter(0); + qty = Qty("2.8m"); + expect(qty.format("m", intRoundingFormatter)).toBe("3 m"); + expect(qty.format("cm", intRoundingFormatter)).toBe("280 cm"); + qty = Qty("2.818m"); + expect(qty.format("cm", intRoundingFormatter)).toBe("282 cm"); + }); + + describe("globally set as default formatter", function () { + var previousFormatter: Qty.Formatter; + + beforeEach(function () { + previousFormatter = Qty.formatter; + Qty.formatter = roundingFormatter(3); + }); + + afterEach(function () { + // Restore previous formatter + Qty.formatter = previousFormatter; + }); + + it("should be applied when no formatter is passed", function () { + var qty = (Qty("2.987654321 m")); + + expect(qty.format()).toBe("2.988 m"); + }); + }); + }); + }); + + describe("precision rounding", function () { + it("should round according to precision passed as quantity with same units", function () { + var qty = Qty("5.17 ft"); + + expect(qty.toPrec(Qty("ft")).toString()).toBe("5 ft"); + expect(qty.toPrec(Qty("2 ft")).toString()).toBe("6 ft"); + expect(qty.toPrec(Qty("10 ft")).toString()).toBe("10 ft"); + expect(qty.toPrec(Qty("0.5 ft")).toString()).toBe("5 ft"); + expect(qty.toPrec(Qty("0.1 ft")).toString()).toBe("5.2 ft"); + expect(qty.toPrec(Qty("0.05 ft")).toString()).toBe("5.15 ft"); + expect(qty.toPrec(Qty("0.01 ft")).toString()).toBe("5.17 ft"); + expect(qty.toPrec(Qty("0.0001 ft")).toString()).toBe("5.17 ft"); + expect(qty.toPrec(Qty("0.25 ft")).toString()).toBe("5.25 ft"); + }); + + it("should allow string as precision parameter", function () { + var qty = Qty("5.17 ft"); + + expect(qty.toPrec("ft").toString()).toBe("5 ft"); + expect(qty.toPrec("0.5 ft").toString()).toBe("5 ft"); + expect(qty.toPrec("0.05 ft").toString()).toBe("5.15 ft"); + }); + + it("should round according to precision passed as quantity with different prefixes", function () { + var qty = Qty("6.3782 m"); + + expect(qty.toPrec(Qty("dm")).toString()).toBe("6.4 m"); + expect(qty.toPrec(Qty("cm")).toString()).toBe("6.38 m"); + expect(qty.toPrec(Qty("mm")).toString()).toBe("6.378 m"); + + expect(qty.toPrec(Qty("5 cm")).toString()).toBe("6.4 m"); + }); + + it("should round according to precision passed as quantity with different compatible units", function () { + var qty = Qty("1.146 MPa"); + expect(qty.toPrec(Qty("0.1 bar")).toString()).toBe("1.15 MPa"); + expect(qty.toPrec(Qty("0.01 MPa")).toString()).toBe("1.15 MPa"); + expect(qty.toPrec(Qty("dbar")).toString()).toBe("1.15 MPa"); + + // Tests below are mainly a safety net because not sure if there is + // any usefulness to do things like that + qty = Qty("5.171234568 ft"); + expect(qty.toPrec(Qty("m")).toString()).toBe("6.561679790026248 ft"); + expect(qty.toPrec(Qty("dm")).toString()).toBe("5.249343832020998 ft"); + expect(qty.toPrec(Qty("cm")).toString()).toBe("5.183727034120736 ft"); + expect(qty.toPrec(Qty("mm")).toString()).toBe("5.170603674540684 ft"); + }); + }); + + describe("mulSafe", function () { + it("should multiply while trying to avoid numerical errors", function () { + expect(Qty.mulSafe(0.1, 0.1)).toBe(0.01); + expect(Qty.mulSafe(1e-11, 123.456789)).toBe(1.23456789e-9); + expect(Qty.mulSafe(6e-12, 100000)).toBe(6e-7); + }); + }); + + describe("divSafe", function () { + it("should divide while trying to avoid numerical errors", function () { + expect(Qty.divSafe(0.000773, 0.000001)).toBe(773); + // TODO uncomment and fix + //expect(Qty.divSafe(24.5, 0.2777777777777778)).toBe(88.2); + }); + }); + + describe("Qty.parse", function () { + it("should not throw if parsed argument is a string", function () { + expect(function () { Qty.parse("foo"); }).not.toThrow("Argument should be a string"); + }); + + it("should return parsed quantity when passing a valid quantity", function () { + expect((Qty.parse("2.5 m") instanceof Qty)).toBe(true); + }); + + it("should return null when passing an invalid quantity", function () { + expect(Qty.parse("aa")).toBeNull(); + }); + }); + + describe("Qty.swiftConverter", function () { + it("should return a function", function () { + expect(typeof Qty.swiftConverter("m/h", "ft/s")).toBe("function"); + }); + + it("should throw when passing incompatible units", function () { + expect(function () { Qty.swiftConverter("m", "s"); }).toThrow("Incompatible units"); + }); + + describe("converter", function () { + describe("single value", function () { + it("should convert value", function () { + // TODO Same test but with m/h -> ft/s triggers rounding issue + // (For the sake of speed, converter does not check and fix rounding issues) + var converter = Qty.swiftConverter("m/h", "m/s"); + + expect(converter(2500)).toEqual(Qty("2500 m/h").to("m/s").scalar); + }); + + it("should returned value unchanged when units are identical", function () { + var converter = Qty.swiftConverter("m/h", "m/h"); + + expect(converter(2500)).toEqual(2500); + }); + + it("should convert temperatures", function () { + var converter = Qty.swiftConverter("tempF", "tempC"); + + expect(converter(32)).toEqual(0); + }); + + it("should convert degrees", function () { + var converter = Qty.swiftConverter("degC", "degF"); + + expect(converter(10)).toEqual(18); + }); + }); + + describe("array of values", function () { + it("should be converted", function () { + var converter = Qty.swiftConverter("MPa", "bar"), + values = [250, 10, 15], + expected = [2500, 100, 150]; + + expect(converter(values)).toEqual(expected); + }); + }); + }); + }); + + describe("Qty.getKinds", function () { + it("should return an array of kind names", function () { + expect(Qty.getKinds()).toContain("resistance"); + }); + + it("should not contain duplicate kind names", function () { + var kinds = Qty.getKinds(); + var map: { [key: string]: number } = {}; + kinds.forEach(function (kind) { + map[kind] = 1; + }); + expect(kinds.length).toEqual(Object.keys(map).length); + }); + }); + + describe("Qty.getUnits", function () { + it("should return an array of units of kind", function () { + expect(Qty.getUnits("currency")).toContain("dollar"); + }); + it("should return an array of all units without arg", function () { + expect(Qty.getUnits()).toContain("sievert"); + }); + it("should throw unknown kind", function () { + expect(function () { Qty.getUnits('bogusKind'); }).toThrow("Kind not recognized"); + }); + }); + + describe("Qty.getAliases", function () { + it("should return array of alternative names for unit", function () { + expect(Qty.getAliases("m")).toContain("meter"); + expect(Qty.getAliases("meter")).toContain("metre"); + expect(Qty.getAliases("N")).toContain("newton"); + }); + }); + + describe("information", function () { + describe("bits and bytes", function () { + it("should have 'information' as kind", function () { + expect(Qty("3 b").kind()).toBe("information"); + expect(Qty("5 B").kind()).toBe("information"); + }); + + it("could be pluralized", function () { + expect(Qty("3 bits").eq(Qty("3 b"))).toBe(true); + expect(Qty("5 bytes").eq(Qty("5 B"))).toBe(true); + }); + }); + + describe("rate", function () { + it("should accept bps and Bps aliases", function () { + expect(Qty("3 bps").eq(Qty("3 b/s"))).toBe(true); + expect(Qty("5 Bps").eq(Qty("5 B/s"))).toBe(true); + }); + + it("should be parsed when prefixed", function () { + expect(Qty("3 kbps").eq(Qty("3 kb/s"))).toBe(true); + expect(Qty("5 MBps").eq(Qty("5 MB/s"))).toBe(true); + }); + + it("should have 'information_rate' as kind", function () { + expect(Qty("3 bps").kind()).toBe("information_rate"); + expect(Qty("5 Bps").kind()).toBe("information_rate"); + }); + }); + }); + + describe("non regression tests", function () { + describe("Wh (#38)", function () { + it("should be parsed", function () { + expect(Qty("Wh").eq(Qty("3600 J"))).toBe(true); + }); + + it("should be parsed when prefixed", function () { + expect(Qty("kWh").eq(Qty("1000 Wh"))).toBe(true); + }); + }); + + describe("Ah (#25)", function () { + it("should be parsed", function () { + expect(Qty("Ah").eq(Qty("3600 C"))).toBe(true); + }); + + it("should be parsed when prefixed", function () { + expect(Qty("mAh").eq(Qty("3.6 C"))).toBe(true); + }); + }); + + describe("Farad (#67)", function () { + it('should be equal to its definition', function () { + expect(Qty("1 F").eq(Qty("1 C").div(Qty("1 V")))).toBe(true); + }); + + it('should not be defined as base unit', function () { + var qty = Qty("F"); + + expect(qty.isBase()).toBe(false); + expect(qty.toBase().units()).toEqual("s4*A2/m2*kg"); + }); + + it('should be parsed when prefixed', function () { + var qty = Qty("100 nF"); + + expect(qty.eq(Qty("100 F").div(1e9))).toBe(true); + expect(qty.baseScalar).toEqual(1e-7); + }); + }); + }); +}); diff --git a/js-quantities/tsconfig.json b/js-quantities/tsconfig.json index 8c2a810060..c41d2d2197 100644 --- a/js-quantities/tsconfig.json +++ b/js-quantities/tsconfig.json @@ -4,7 +4,7 @@ "target": "es6", "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" @@ -17,4 +17,4 @@ "index.d.ts", "js-quantities-tests.ts" ] -} \ No newline at end of file +} diff --git a/js-quantities/tslint.json b/js-quantities/tslint.json new file mode 100644 index 0000000000..f9e30021f4 --- /dev/null +++ b/js-quantities/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "../tslint.json" +} diff --git a/memoizee/index.d.ts b/memoizee/index.d.ts new file mode 100644 index 0000000000..456641dc59 --- /dev/null +++ b/memoizee/index.d.ts @@ -0,0 +1,29 @@ +// Type definitions for memoizee 0.4 +// Project: https://github.com/medikoo/memoizee +// Definitions by: Juan Picado +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare namespace memoizee { + interface Options { + length?: number; + maxAge?: number; + max?: number; + preFetch?: number | true; + promise?: boolean; + dispose?: (value: any) => void; + async?: boolean; + primitive?: boolean; + normalizer?: (value: any) => void; + resolvers?: Array<(arg: any) => any>; + } + + interface Memoized { + delete: F; + clear: F & (() => void); + } +} + +// tslint:disable:forbidden-types +declare function memoizee(f: F, options?: memoizee.Options): F & memoizee.Memoized; + +export = memoizee; diff --git a/memoizee/memoizee-tests.ts b/memoizee/memoizee-tests.ts new file mode 100644 index 0000000000..e8e73a2d6a --- /dev/null +++ b/memoizee/memoizee-tests.ts @@ -0,0 +1,61 @@ +import memoize = require('memoizee'); + +var fn = function (one: string, two?: number, three?: any) { /* ... */ }; + +let memoized = memoize(fn); +memoized('foo', 3, 'bar'); +memoized('foo', 3, 'bar'); +memoized = memoize(fn, { length: 2 }); +memoized('foo'); +memoized('foo', undefined); +memoized('foo', 3, {}); +memoized('foo', 3, 13); +memoized('foo', undefined); +memoized('foo', undefined); +memoized('foo', 3, {}); +memoized('foo', 3, 13); +memoized('foo', 3, 13); +memoized = memoize(fn, { primitive: true }); +memoized('/path/one'); +memoized('/path/one'); +memoized = memoize(fn, { dispose: function (value:number) { /*…*/ } }); +var foo3 = memoized('foo', 3); +var bar7 = memoized('bar', 7); +memoized.clear('foo', 3); // Dispose called with foo3 value +memoized.clear('bar', 7); // Dispose called with bar7 value +memoized.delete('foo', 0); +var mFn = memoize(function (hash:any) { + // body of memoized function +}, { normalizer: function (args:any) { + // args is arguments object as accessible in memoized function + return JSON.stringify(args[0]); +} }); + +mFn({ foo: 'bar' }); + +memoized = memoize(fn, { length: 2, resolvers: [String, Boolean] }); +memoized(String(12), [1,2,3].length); +memoized("12", Number(true)); +memoized(String({ toString: function () { return "12"; } }), Number({})); + +{ + var afn = function (a:number, b:number) { + return new Promise(function (res) { res(a + b); }); + }; + let memoized = memoize(afn, { promise: true }); + memoized(3, 7); + memoized(3, 7); +} + +memoized = memoize(fn, { maxAge: 1000, preFetch: 0.6 }); + +memoized('foo', 3); +memoized('foo', 3); + +setTimeout(function () { + memoized('foo', 3); +}, 500); + +setTimeout(function () { + memoized('foo', 3); +}, 1300); diff --git a/memoizee/tsconfig.json b/memoizee/tsconfig.json new file mode 100644 index 0000000000..c2ccff1cab --- /dev/null +++ b/memoizee/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "memoizee-tests.ts" + ] +} diff --git a/memoizee/tslint.json b/memoizee/tslint.json new file mode 100644 index 0000000000..2221e40e4a --- /dev/null +++ b/memoizee/tslint.json @@ -0,0 +1 @@ +{ "extends": "../tslint.json" } \ No newline at end of file diff --git a/react-intl/index.d.ts b/react-intl/index.d.ts index 80a2372e12..e0d9d3f623 100644 --- a/react-intl/index.d.ts +++ b/react-intl/index.d.ts @@ -1,6 +1,6 @@ // Type definitions for react-intl 2.2.0 // Project: http://formatjs.io/react/ -// Definitions by: Bruno Grieder , Christian Droulers , Fedor Nezhivoi +// Definitions by: Bruno Grieder , Christian Droulers , Fedor Nezhivoi , Till Wolff // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /// @@ -13,7 +13,7 @@ declare namespace ReactIntl { pluralRuleFunction?: (n: number, ord: boolean) => string; } - function injectIntl(component: React.ComponentClass | React.StatelessComponent): React.ComponentClass; + function injectIntl | React.StatelessComponent>(component: T): T; function addLocaleData(data: Locale[] | Locale): void; @@ -45,6 +45,10 @@ declare namespace ReactIntl { formatHTMLMessage: (messageDescriptor: FormattedMessage.MessageDescriptor, values?: Object) => string; } + interface InjectedIntlProps { + intl?: InjectedIntl + } + namespace IntlComponent { interface DateTimeFormatProps { /* diff --git a/react-intl/react-intl-tests.tsx b/react-intl/react-intl-tests.tsx index cd484c17b4..160a37bc0f 100644 --- a/react-intl/react-intl-tests.tsx +++ b/react-intl/react-intl-tests.tsx @@ -9,20 +9,20 @@ import * as React from "react" import * as reactMixin from "react-mixin" import { -IntlProvider, -InjectedIntl, -addLocaleData, -hasLocaleData, -injectIntl, -intlShape, -defineMessages, -FormattedRelative, -FormattedMessage, -FormattedHTMLMessage, -FormattedNumber, -FormattedPlural, -FormattedDate, -FormattedTime + IntlProvider, + InjectedIntl, + addLocaleData, + hasLocaleData, + injectIntl, + intlShape, + defineMessages, + FormattedRelative, + FormattedMessage, + FormattedHTMLMessage, + FormattedNumber, + FormattedPlural, + FormattedDate, + FormattedTime } from "react-intl" import reactIntlEn = require("react-intl/locale-data/en"); @@ -31,7 +31,8 @@ addLocaleData(reactIntlEn); console.log(hasLocaleData("en")); interface SomeComponentProps { - intl: InjectedIntl + className: string, + intl?: InjectedIntl } class SomeComponent extends React.Component { @@ -47,14 +48,14 @@ class SomeComponent extends React.Component { const formattedPlural = intl.formatPlural(1, { one: "hai!" }); const formattedMessage = intl.formatMessage({ id: "hello", defaultMessage: "Hello {name}!" }, { name: "Roger" }); const formattedHTMLMessage = intl.formatHTMLMessage({ id: "hello", defaultMessage: "Hello {name}!" }, { name: "Roger" }); - return
+ return
+ initialNow={new Date()} /> { many="haiku" /> { timeZoneName="short" /> { {(formattedNum: string) => ( {formattedNum} - ) } - -
+ )} + +
} } @@ -159,9 +160,9 @@ class TestApp extends React.Component<{}, {}> { "hello": "Hello, {name}!" }; return ( - - - + + + ); } } diff --git a/stripe/index.d.ts b/stripe/index.d.ts index 2f8c895298..fdfa1db96e 100644 --- a/stripe/index.d.ts +++ b/stripe/index.d.ts @@ -1,8 +1,10 @@ -// Type definitions for stripe +// Type definitions for stripe 0.0 // Project: https://stripe.com/ // Definitions by: Andy Hawkins , Eric J. Smith , Amrit Kahlon , Adam Cmiel // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +declare const Stripe: StripeStatic; + interface StripeStatic { applePay: StripeApplePay; setPublishableKey(key: string): void; @@ -49,6 +51,8 @@ interface StripeError { param?: string; } +type StripeCardDataBrand = 'Visa' | 'American Express' | 'MasterCard' | 'Discover JCB' | 'Diners Club' | 'Unknown'; + interface StripeCardData { object: string; last4: string; @@ -62,18 +66,17 @@ interface StripeCardData { address_state?: string; address_zip?: string; address_country?: string; + brand?: StripeCardDataBrand; createToken(data: StripeTokenData, responseHandler: (status: number, response: StripeTokenResponse) => void): void; } -interface StripeBankAccount -{ - createToken(params: StripeBankTokenParams, stripeResponseHandler: (status:number, response: StripeBankTokenResponse) => void): void; +interface StripeBankAccount { + createToken(params: StripeBankTokenParams, stripeResponseHandler: (status: number, response: StripeBankTokenResponse) => void): void; validateRoutingNumber(routingNumber: number | string, countryCode: string): boolean; validateAccountNumber(accountNumber: number | string, countryCode: string): boolean; } -interface StripeBankTokenParams -{ +interface StripeBankTokenParams { country: string; currency: string; account_number: number | string; @@ -82,8 +85,7 @@ interface StripeBankTokenParams account_holder_type: string; } -interface StripeBankTokenResponse -{ +interface StripeBankTokenResponse { id: string; bank_account: { country: string; @@ -100,13 +102,7 @@ interface StripeBankTokenResponse error?: StripeError; } -declare var Stripe: StripeStatic; -declare module "Stripe" { - export = StripeStatic; -} - -interface StripeApplePay -{ +interface StripeApplePay { checkAvailability(resopnseHandler: (result: boolean) => void): void; buildSession(data: StripeApplePayPaymentRequest, onSuccessHandler: (result: StripeApplePaySessionResult, completion: ((value: any) => void)) => void, @@ -117,8 +113,7 @@ type StripeApplePayBillingContactField = 'postalAddress' | 'name'; type StripeApplePayShippingContactField = StripeApplePayBillingContactField | 'phone' | 'email'; type StripeApplePayShipping = 'shipping' | 'delivery' | 'storePickup' | 'servicePickup'; -interface StripeApplePayPaymentRequest -{ +interface StripeApplePayPaymentRequest { billingContact: StripeApplePayPaymentContact; countryCode: string; currencyCode: string; @@ -132,30 +127,26 @@ interface StripeApplePayPaymentRequest } // https://developer.apple.com/reference/applepayjs/1916082-applepay_js_data_types -interface StripeApplePayLineItem -{ +interface StripeApplePayLineItem { type: 'pending' | 'final'; label: string; amount: number; } -interface StripeApplePaySessionResult -{ +interface StripeApplePaySessionResult { token: StripeTokenResponse; shippingContact?: StripeApplePayPaymentContact; shippingMethod?: StripeApplePayShippingMethod; } -interface StripeApplePayShippingMethod -{ +interface StripeApplePayShippingMethod { label: string; detail: string; amount: number; identifier: string; } -interface StripeApplePayPaymentContact -{ +interface StripeApplePayPaymentContact { emailAddress: string; phoneNumber: string; givenName: string; @@ -166,3 +157,7 @@ interface StripeApplePayPaymentContact postalCode: string; countryCode: string; } + +// The Stripe client side APIs are not made available to package managers for direct installation. +// As explained compliance reasons. Source: https://github.com/stripe/stripe-node/blob/master/README.md#these-are-serverside-bindings-only +// A release date versioning schema is used to version these APIs. diff --git a/stripe/stripe-tests.ts b/stripe/stripe-tests.ts new file mode 100644 index 0000000000..44aa09d216 --- /dev/null +++ b/stripe/stripe-tests.ts @@ -0,0 +1,25 @@ +function success(card: StripeCardData) { + console.log(card.brand && card.brand.toString()); +} + +const cardNumber = '4242424242424242'; + +const isValid = Stripe.validateCardNumber(cardNumber); +if (isValid) { + const tokenData: StripeTokenData = { + number: cardNumber, + exp_month: 1, + exp_year: 2100, + cvc: '111' + }; + Stripe.card.createToken(tokenData, (status, response) => { + if (response.error) { + console.error(response.error.message); + if (response.error.param) { + console.error(response.error.param); + } + } else { + success(response.card); + } + }); +} diff --git a/stripe/tsconfig.json b/stripe/tsconfig.json index cdcaca971c..7c33ab65c5 100644 --- a/stripe/tsconfig.json +++ b/stripe/tsconfig.json @@ -4,7 +4,7 @@ "target": "es6", "noImplicitAny": true, "noImplicitThis": true, - "strictNullChecks": false, + "strictNullChecks": true, "baseUrl": "../", "typeRoots": [ "../" @@ -14,6 +14,7 @@ "forceConsistentCasingInFileNames": true }, "files": [ - "index.d.ts" + "index.d.ts", + "stripe-tests.ts" ] -} \ No newline at end of file +} diff --git a/stripe/tslint.json b/stripe/tslint.json new file mode 100644 index 0000000000..f9e30021f4 --- /dev/null +++ b/stripe/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "../tslint.json" +}