scale.time.tests.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. // Time scale tests
  2. describe('Time scale tests', function() {
  3. var chartInstance;
  4. beforeEach(function() {
  5. window.addDefaultMatchers(jasmine);
  6. // Need a time matcher for getValueFromPixel
  7. jasmine.addMatchers({
  8. toBeCloseToTime: function() {
  9. return {
  10. compare: function(actual, expected) {
  11. var result = false;
  12. var diff = actual.diff(expected.value, expected.unit, true);
  13. result = Math.abs(diff) < (expected.threshold !== undefined ? expected.threshold : 0.5);
  14. return {
  15. pass: result
  16. };
  17. }
  18. }
  19. }
  20. });
  21. });
  22. afterEach(function() {
  23. if (chartInstance)
  24. {
  25. releaseChart(chartInstance);
  26. }
  27. });
  28. it('Should load moment.js as a dependency', function() {
  29. expect(window.moment).not.toBe(undefined);
  30. });
  31. it('Should register the constructor with the scale service', function() {
  32. var Constructor = Chart.scaleService.getScaleConstructor('time');
  33. expect(Constructor).not.toBe(undefined);
  34. expect(typeof Constructor).toBe('function');
  35. });
  36. it('Should have the correct default config', function() {
  37. var defaultConfig = Chart.scaleService.getScaleDefaults('time');
  38. expect(defaultConfig).toEqual({
  39. display: true,
  40. gridLines: {
  41. color: "rgba(0, 0, 0, 0.1)",
  42. drawBorder: true,
  43. drawOnChartArea: true,
  44. drawTicks: true,
  45. tickMarkLength: 10,
  46. lineWidth: 1,
  47. offsetGridLines: false,
  48. display: true,
  49. zeroLineColor: "rgba(0,0,0,0.25)",
  50. zeroLineWidth: 1
  51. },
  52. position: "bottom",
  53. scaleLabel: {
  54. labelString: '',
  55. display: false
  56. },
  57. ticks: {
  58. beginAtZero: false,
  59. minRotation: 0,
  60. maxRotation: 50,
  61. mirror: false,
  62. padding: 10,
  63. reverse: false,
  64. display: true,
  65. callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below,
  66. autoSkip: false,
  67. autoSkipPadding: 0,
  68. labelOffset: 0
  69. },
  70. time: {
  71. parser: false,
  72. format: false,
  73. unit: false,
  74. round: false,
  75. isoWeekday: false,
  76. displayFormat: false,
  77. displayFormats: {
  78. 'millisecond': 'h:mm:ss.SSS a', // 11:20:01.123 AM
  79. 'second': 'h:mm:ss a', // 11:20:01 AM
  80. 'minute': 'h:mm:ss a', // 11:20:01 AM
  81. 'hour': 'MMM D, hA', // Sept 4, 5PM
  82. 'day': 'll', // Sep 4 2015
  83. 'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
  84. 'month': 'MMM YYYY', // Sept 2015
  85. 'quarter': '[Q]Q - YYYY', // Q3
  86. 'year': 'YYYY' // 2015
  87. }
  88. }
  89. });
  90. // Is this actually a function
  91. expect(defaultConfig.ticks.callback).toEqual(jasmine.any(Function));
  92. });
  93. it('should build ticks using days', function() {
  94. var scaleID = 'myScale';
  95. var mockData = {
  96. labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00", "2015-01-03T22:00:00", "2015-01-05T23:00:00", "2015-01-07T03:00", "2015-01-08T10:00", "2015-01-10T12:00"], // days
  97. };
  98. var mockContext = window.createMockContext();
  99. var Constructor = Chart.scaleService.getScaleConstructor('time');
  100. var scale = new Constructor({
  101. ctx: mockContext,
  102. options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
  103. chart: {
  104. data: mockData
  105. },
  106. id: scaleID
  107. });
  108. //scale.buildTicks();
  109. scale.update(400, 50);
  110. // Counts down because the lines are drawn top to bottom
  111. expect(scale.ticks).toEqual([ 'Dec 28, 2014', 'Jan 4, 2015', 'Jan 11, 2015' ]);
  112. });
  113. it('should build ticks using date objects', function() {
  114. // Helper to build date objects
  115. function newDateFromRef(days) {
  116. return moment('01/01/2015 12:00', 'DD/MM/YYYY HH:mm').add(days, 'd').toDate();
  117. }
  118. var scaleID = 'myScale';
  119. var mockData = {
  120. labels: [newDateFromRef(0), newDateFromRef(1), newDateFromRef(2), newDateFromRef(4), newDateFromRef(6), newDateFromRef(7), newDateFromRef(9)], // days
  121. };
  122. var mockContext = window.createMockContext();
  123. var Constructor = Chart.scaleService.getScaleConstructor('time');
  124. var scale = new Constructor({
  125. ctx: mockContext,
  126. options: Chart.scaleService.getScaleDefaults('time'), // use default config for scale
  127. chart: {
  128. data: mockData
  129. },
  130. id: scaleID
  131. });
  132. scale.update(400, 50);
  133. // Counts down because the lines are drawn top to bottom
  134. expect(scale.ticks).toEqual([ 'Dec 28, 2014', 'Jan 4, 2015', 'Jan 11, 2015' ]);
  135. });
  136. it('should build ticks when the data is xy points', function() {
  137. // Helper to build date objects
  138. function newDateFromRef(days) {
  139. return moment('01/01/2015 12:00', 'DD/MM/YYYY HH:mm').add(days, 'd').toDate();
  140. }
  141. chartInstance = window.acquireChart({
  142. type: 'line',
  143. data: {
  144. datasets: [{
  145. xAxisID: 'xScale0',
  146. yAxisID: 'yScale0',
  147. data: [{
  148. x: newDateFromRef(0),
  149. y: 1
  150. }, {
  151. x: newDateFromRef(1),
  152. y: 10
  153. }, {
  154. x: newDateFromRef(2),
  155. y: 0
  156. }, {
  157. x: newDateFromRef(4),
  158. y: 5
  159. }, {
  160. x: newDateFromRef(6),
  161. y: 77
  162. }, {
  163. x: newDateFromRef(7),
  164. y: 9
  165. }, {
  166. x: newDateFromRef(9),
  167. y: 5
  168. }]
  169. }],
  170. },
  171. options: {
  172. scales: {
  173. xAxes: [{
  174. id: 'xScale0',
  175. type: 'time',
  176. position: 'bottom'
  177. }],
  178. yAxes: [{
  179. id: 'yScale0',
  180. type: 'linear'
  181. }]
  182. }
  183. }
  184. });
  185. // Counts down because the lines are drawn top to bottom
  186. var xScale = chartInstance.scales.xScale0;
  187. expect(xScale.ticks).toEqual([ 'Jan 1, 2015', 'Jan 3, 2015', 'Jan 5, 2015', 'Jan 7, 2015', 'Jan 9, 2015', 'Jan 11, 2015' ]);
  188. });
  189. it('should allow custom time parsers', function() {
  190. chartInstance = window.acquireChart({
  191. type: 'line',
  192. data: {
  193. datasets: [{
  194. xAxisID: 'xScale0',
  195. yAxisID: 'yScale0',
  196. data: [{
  197. x: 375068900,
  198. y: 1
  199. }]
  200. }],
  201. },
  202. options: {
  203. scales: {
  204. xAxes: [{
  205. id: 'xScale0',
  206. type: 'time',
  207. position: 'bottom',
  208. time: {
  209. unit: 'day',
  210. round: true,
  211. parser: function customTimeParser(label) {
  212. return moment.unix(label);
  213. }
  214. }
  215. }],
  216. yAxes: [{
  217. id: 'yScale0',
  218. type: 'linear'
  219. }]
  220. }
  221. }
  222. });
  223. // Counts down because the lines are drawn top to bottom
  224. var xScale = chartInstance.scales.xScale0;
  225. // Counts down because the lines are drawn top to bottom
  226. expect(xScale.ticks[0]).toEqualOneOf(['Nov 19, 1981', 'Nov 20, 1981', 'Nov 21, 1981']); // handle time zone changes
  227. expect(xScale.ticks[1]).toEqualOneOf(['Nov 19, 1981', 'Nov 20, 1981', 'Nov 21, 1981']); // handle time zone changes
  228. });
  229. it('should build ticks using the config unit', function() {
  230. var scaleID = 'myScale';
  231. var mockData = {
  232. labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00"], // days
  233. };
  234. var mockContext = window.createMockContext();
  235. var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
  236. config.time.unit = 'hour';
  237. var Constructor = Chart.scaleService.getScaleConstructor('time');
  238. var scale = new Constructor({
  239. ctx: mockContext,
  240. options: config, // use default config for scale
  241. chart: {
  242. data: mockData
  243. },
  244. id: scaleID
  245. });
  246. //scale.buildTicks();
  247. scale.update(400, 50);
  248. expect(scale.ticks).toEqual(['Jan 1, 8PM', 'Jan 1, 9PM', 'Jan 1, 10PM', 'Jan 1, 11PM', 'Jan 2, 12AM', 'Jan 2, 1AM', 'Jan 2, 2AM', 'Jan 2, 3AM', 'Jan 2, 4AM', 'Jan 2, 5AM', 'Jan 2, 6AM', 'Jan 2, 7AM', 'Jan 2, 8AM', 'Jan 2, 9AM', 'Jan 2, 10AM', 'Jan 2, 11AM', 'Jan 2, 12PM', 'Jan 2, 1PM', 'Jan 2, 2PM', 'Jan 2, 3PM', 'Jan 2, 4PM', 'Jan 2, 5PM', 'Jan 2, 6PM', 'Jan 2, 7PM', 'Jan 2, 8PM', 'Jan 2, 9PM']);
  249. });
  250. it('should build ticks using the config diff', function() {
  251. var scaleID = 'myScale';
  252. var mockData = {
  253. labels: ["2015-01-01T20:00:00", "2015-02-02T21:00:00", "2015-02-21T01:00:00"], // days
  254. };
  255. var mockContext = window.createMockContext();
  256. var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
  257. config.time.unit = 'week';
  258. config.time.round = 'week';
  259. var Constructor = Chart.scaleService.getScaleConstructor('time');
  260. var scale = new Constructor({
  261. ctx: mockContext,
  262. options: config, // use default config for scale
  263. chart: {
  264. data: mockData
  265. },
  266. id: scaleID
  267. });
  268. //scale.buildTicks();
  269. scale.update(400, 50);
  270. // last date is feb 15 because we round to start of week
  271. expect(scale.ticks).toEqual(['Dec 28, 2014', 'Jan 4, 2015', 'Jan 11, 2015', 'Jan 18, 2015', 'Jan 25, 2015', 'Feb 1, 2015', 'Feb 8, 2015', 'Feb 15, 2015']);
  272. });
  273. it('Should use the min and max options', function() {
  274. var scaleID = 'myScale';
  275. var mockData = {
  276. labels: ["2015-01-01T20:00:00", "2015-01-02T20:00:00", "2015-01-03T20:00:00"], // days
  277. };
  278. var mockContext = window.createMockContext();
  279. var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
  280. config.time.min = "2015-01-01T04:00:00";
  281. config.time.max = "2015-01-05T06:00:00"
  282. var Constructor = Chart.scaleService.getScaleConstructor('time');
  283. var scale = new Constructor({
  284. ctx: mockContext,
  285. options: config, // use default config for scale
  286. chart: {
  287. data: mockData
  288. },
  289. id: scaleID
  290. });
  291. scale.update(400, 50);
  292. expect(scale.ticks).toEqual([ 'Jan 1, 2015', 'Jan 5, 2015' ]);
  293. });
  294. it('Should use the isoWeekday option', function() {
  295. var scaleID = 'myScale';
  296. var mockData = {
  297. labels: [
  298. "2015-01-01T20:00:00", // Thursday
  299. "2015-01-02T20:00:00", // Friday
  300. "2015-01-03T20:00:00" // Saturday
  301. ]
  302. };
  303. var mockContext = window.createMockContext();
  304. var config = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
  305. config.time.unit = 'week';
  306. // Wednesday
  307. config.time.isoWeekday = 3;
  308. var Constructor = Chart.scaleService.getScaleConstructor('time');
  309. var scale = new Constructor({
  310. ctx: mockContext,
  311. options: config, // use default config for scale
  312. chart: {
  313. data: mockData
  314. },
  315. id: scaleID
  316. });
  317. scale.update(400, 50);
  318. expect(scale.ticks).toEqual([ 'Dec 31, 2014', 'Jan 7, 2015' ]);
  319. });
  320. it('should get the correct pixel for a value', function() {
  321. chartInstance = window.acquireChart({
  322. type: 'line',
  323. data: {
  324. datasets: [{
  325. xAxisID: 'xScale0',
  326. yAxisID: 'yScale0',
  327. data: []
  328. }],
  329. labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00", "2015-01-03T22:00:00", "2015-01-05T23:00:00", "2015-01-07T03:00", "2015-01-08T10:00", "2015-01-10T12:00"], // days
  330. },
  331. options: {
  332. scales: {
  333. xAxes: [{
  334. id: 'xScale0',
  335. type: 'time',
  336. position: 'bottom'
  337. }],
  338. yAxes: [{
  339. id: 'yScale0',
  340. type: 'linear',
  341. position: 'left'
  342. }]
  343. }
  344. }
  345. });
  346. var xScale = chartInstance.scales.xScale0;
  347. expect(xScale.getPixelForValue('', 0, 0)).toBeCloseToPixel(78);
  348. expect(xScale.getPixelForValue('', 6, 0)).toBeCloseToPixel(452);
  349. expect(xScale.getValueForPixel(78)).toBeCloseToTime({
  350. value: moment(chartInstance.data.labels[0]),
  351. unit: 'hour',
  352. threshold: 0.75
  353. });
  354. expect(xScale.getValueForPixel(452)).toBeCloseToTime({
  355. value: moment(chartInstance.data.labels[6]),
  356. unit: 'hour'
  357. });
  358. });
  359. it('should get the correct label for a data value', function() {
  360. chartInstance = window.acquireChart({
  361. type: 'line',
  362. data: {
  363. datasets: [{
  364. xAxisID: 'xScale0',
  365. yAxisID: 'yScale0',
  366. data: []
  367. }],
  368. labels: ["2015-01-01T20:00:00", "2015-01-02T21:00:00", "2015-01-03T22:00:00", "2015-01-05T23:00:00", "2015-01-07T03:00", "2015-01-08T10:00", "2015-01-10T12:00"], // days
  369. },
  370. options: {
  371. scales: {
  372. xAxes: [{
  373. id: 'xScale0',
  374. type: 'time',
  375. position: 'bottom'
  376. }],
  377. yAxes: [{
  378. id: 'yScale0',
  379. type: 'linear',
  380. position: 'left'
  381. }]
  382. }
  383. }
  384. });
  385. var xScale = chartInstance.scales.xScale0;
  386. expect(xScale.getLabelForIndex(0, 0)).toBe('2015-01-01T20:00:00');
  387. expect(xScale.getLabelForIndex(6, 0)).toBe('2015-01-10T12:00');
  388. });
  389. });