-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added run-time validation of inputs in debug mode
Fixes #315
- Loading branch information
Showing
8 changed files
with
231 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { assert, ensureNever } from '../helpers/assertions'; | ||
|
||
import { SeriesMarker } from '../model/series-markers'; | ||
import { SeriesType } from '../model/series-options'; | ||
|
||
import { isFulfilledData, SeriesDataItemTypeMap, Time } from './data-consumer'; | ||
import { convertTime } from './data-layer'; | ||
|
||
export function checkItemsAreOrdered(data: readonly (SeriesMarker<Time> | SeriesDataItemTypeMap[SeriesType])[], allowDuplicates: boolean = false): void { | ||
if (process.env.NODE_ENV === 'production') { | ||
return; | ||
} | ||
|
||
if (data.length === 0) { | ||
return; | ||
} | ||
|
||
let prevTime = convertTime(data[0].time).timestamp; | ||
for (let i = 1; i < data.length; ++i) { | ||
const currentTime = convertTime(data[i].time).timestamp; | ||
const checkResult = allowDuplicates ? prevTime <= currentTime : prevTime < currentTime; | ||
assert(checkResult, `data must be asc ordered by time, index=${i}, time=${currentTime}, prev time=${prevTime}`); | ||
prevTime = currentTime; | ||
} | ||
} | ||
|
||
export function checkSeriesValuesType(type: SeriesType, data: readonly SeriesDataItemTypeMap[SeriesType][]): void { | ||
if (process.env.NODE_ENV === 'production') { | ||
return; | ||
} | ||
|
||
const checker = getChecker(type); | ||
for (const item of data) { | ||
checker(item); | ||
} | ||
} | ||
|
||
type Checker = (item: SeriesDataItemTypeMap[SeriesType]) => void; | ||
|
||
function getChecker(type: SeriesType): Checker { | ||
switch (type) { | ||
case 'Bar': | ||
case 'Candlestick': | ||
return checkBarItem.bind(null, type); | ||
|
||
case 'Area': | ||
case 'Line': | ||
case 'Histogram': | ||
return checkLineItem.bind(null, type); | ||
|
||
default: | ||
ensureNever(type); | ||
throw new Error(`unsupported series type ${type}`); | ||
} | ||
} | ||
|
||
function checkBarItem(type: 'Bar' | 'Candlestick', barItem: SeriesDataItemTypeMap[typeof type]): void { | ||
if (!isFulfilledData(barItem)) { | ||
return; | ||
} | ||
|
||
assert( | ||
// eslint-disable-next-line @typescript-eslint/tslint/config | ||
typeof barItem.open === 'number', | ||
`${type} series item data value of open must be a number, got=${typeof barItem.open}, value=${barItem.open}` | ||
); | ||
assert( | ||
// eslint-disable-next-line @typescript-eslint/tslint/config | ||
typeof barItem.high === 'number', | ||
`${type} series item data value of high must be a number, got=${typeof barItem.high}, value=${barItem.high}` | ||
); | ||
assert( | ||
// eslint-disable-next-line @typescript-eslint/tslint/config | ||
typeof barItem.low === 'number', | ||
`${type} series item data value of low must be a number, got=${typeof barItem.low}, value=${barItem.low}` | ||
); | ||
assert( | ||
// eslint-disable-next-line @typescript-eslint/tslint/config | ||
typeof barItem.close === 'number', | ||
`${type} series item data value of close must be a number, got=${typeof barItem.close}, value=${barItem.close}` | ||
); | ||
} | ||
|
||
function checkLineItem(type: 'Area' | 'Line' | 'Histogram', lineItem: SeriesDataItemTypeMap[typeof type]): void { | ||
if (!isFulfilledData(lineItem)) { | ||
return; | ||
} | ||
|
||
assert( | ||
// eslint-disable-next-line @typescript-eslint/tslint/config | ||
typeof lineItem.value === 'number', | ||
`${type} series item data value must be a number, got=${typeof lineItem.value}, value=${lineItem.value}`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
function runTestCase(container) { | ||
try { | ||
LightweightCharts.createChart('non-existed-id'); | ||
console.assert(false, 'should fail if passed container id does not exist'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
const chart = LightweightCharts.createChart(container); | ||
const lineSeries = chart.addLineSeries(); | ||
const barSeries = chart.addBarSeries(); | ||
|
||
try { | ||
lineSeries.setData([ | ||
{ time: 1 }, | ||
{ time: 0, value: 0 }, | ||
]); | ||
|
||
console.assert(false, 'should fail if series data is not ordered'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
try { | ||
lineSeries.setMarkers([ | ||
{ time: 1 }, | ||
{ time: 0, value: 0 }, | ||
]); | ||
|
||
console.assert(false, 'should fail if series markers is not ordered'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
try { | ||
lineSeries.setData([ | ||
{ time: 0 }, | ||
{ time: 0, value: 0 }, | ||
{ time: 1, value: 1 }, | ||
]); | ||
|
||
console.assert(false, 'should fail if series data has duplicates'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
try { | ||
lineSeries.setData([ | ||
{ time: 0, value: '0' }, | ||
]); | ||
|
||
console.assert(false, 'should fail if series data item value type is not number'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
try { | ||
barSeries.setData([ | ||
{ time: 0, open: 0, high: '1', low: 0, close: '0' }, | ||
]); | ||
|
||
console.assert(false, 'should fail if series data item value type is not numbers'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
try { | ||
lineSeries.setData([ | ||
{ time: '0' }, | ||
]); | ||
|
||
console.assert(false, 'should fail if series data item has invalid time'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
try { | ||
lineSeries.setData([ | ||
{ time: '2020-1-1' }, | ||
]); | ||
|
||
console.assert(false, 'should fail if series data item has invalid business day string format'); | ||
} catch (e) { | ||
// passed | ||
} | ||
|
||
// should pass - several markers could be on the same bar | ||
lineSeries.setMarkers([ | ||
{ | ||
color: 'green', | ||
position: 'belowBar', | ||
shape: 'arrowDown', | ||
time: 0, | ||
}, | ||
{ | ||
color: 'green', | ||
position: 'aboveBar', | ||
shape: 'arrowUp', | ||
time: 0, | ||
}, | ||
]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters