scale.time.tests.js 11 KB

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