scale.radialLinear.tests.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Tests for the radial linear scale used by the polar area and radar charts
  2. describe('Test the radial linear scale', function() {
  3. describe('auto', jasmine.fixture.specs('scale.radialLinear'));
  4. it('Should register the constructor with the scale service', function() {
  5. var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
  6. expect(Constructor).not.toBe(undefined);
  7. expect(typeof Constructor).toBe('function');
  8. });
  9. it('Should have the correct default config', function() {
  10. var defaultConfig = Chart.scaleService.getScaleDefaults('radialLinear');
  11. expect(defaultConfig).toEqual({
  12. angleLines: {
  13. display: true,
  14. color: 'rgba(0,0,0,0.1)',
  15. lineWidth: 1,
  16. borderDash: [],
  17. borderDashOffset: 0.0
  18. },
  19. animate: true,
  20. display: true,
  21. gridLines: {
  22. circular: false,
  23. color: 'rgba(0,0,0,0.1)',
  24. drawBorder: true,
  25. drawOnChartArea: true,
  26. drawTicks: true,
  27. tickMarkLength: 10,
  28. lineWidth: 1,
  29. offsetGridLines: false,
  30. display: true,
  31. zeroLineColor: 'rgba(0,0,0,0.25)',
  32. zeroLineWidth: 1,
  33. zeroLineBorderDash: [],
  34. zeroLineBorderDashOffset: 0.0,
  35. borderDash: [],
  36. borderDashOffset: 0.0
  37. },
  38. pointLabels: {
  39. display: true,
  40. fontSize: 10,
  41. callback: defaultConfig.pointLabels.callback, // make this nicer, then check explicitly below
  42. },
  43. position: 'chartArea',
  44. offset: false,
  45. scaleLabel: Chart.defaults.scale.scaleLabel,
  46. ticks: {
  47. backdropColor: 'rgba(255,255,255,0.75)',
  48. backdropPaddingY: 2,
  49. backdropPaddingX: 2,
  50. beginAtZero: false,
  51. minRotation: 0,
  52. maxRotation: 50,
  53. mirror: false,
  54. padding: 0,
  55. reverse: false,
  56. showLabelBackdrop: true,
  57. display: true,
  58. callback: defaultConfig.ticks.callback, // make this nicer, then check explicitly below
  59. autoSkip: true,
  60. autoSkipPadding: 0,
  61. labelOffset: 0,
  62. minor: {},
  63. major: {},
  64. },
  65. });
  66. // Is this actually a function
  67. expect(defaultConfig.ticks.callback).toEqual(jasmine.any(Function));
  68. expect(defaultConfig.pointLabels.callback).toEqual(jasmine.any(Function));
  69. });
  70. it('Should correctly determine the max & min data values', function() {
  71. var chart = window.acquireChart({
  72. type: 'radar',
  73. data: {
  74. datasets: [{
  75. data: [10, 5, 0, -5, 78, -100]
  76. }, {
  77. data: [150]
  78. }],
  79. labels: ['label1', 'label2', 'label3', 'label4', 'label5', 'label6']
  80. },
  81. options: {
  82. scales: {}
  83. }
  84. });
  85. expect(chart.scale.min).toBe(-100);
  86. expect(chart.scale.max).toBe(150);
  87. });
  88. it('Should correctly determine the max & min of string data values', function() {
  89. var chart = window.acquireChart({
  90. type: 'radar',
  91. data: {
  92. datasets: [{
  93. data: ['10', '5', '0', '-5', '78', '-100']
  94. }, {
  95. data: ['150']
  96. }],
  97. labels: ['label1', 'label2', 'label3', 'label4', 'label5', 'label6']
  98. },
  99. options: {
  100. scales: {}
  101. }
  102. });
  103. expect(chart.scale.min).toBe(-100);
  104. expect(chart.scale.max).toBe(150);
  105. });
  106. it('Should correctly determine the max & min data values when there are hidden datasets', function() {
  107. var chart = window.acquireChart({
  108. type: 'radar',
  109. data: {
  110. datasets: [{
  111. data: ['10', '5', '0', '-5', '78', '-100']
  112. }, {
  113. data: ['150']
  114. }, {
  115. data: [1000],
  116. hidden: true
  117. }],
  118. labels: ['label1', 'label2', 'label3', 'label4', 'label5', 'label6']
  119. },
  120. options: {
  121. scales: {}
  122. }
  123. });
  124. expect(chart.scale.min).toBe(-100);
  125. expect(chart.scale.max).toBe(150);
  126. });
  127. it('Should correctly determine the max & min data values when there is NaN data', function() {
  128. var chart = window.acquireChart({
  129. type: 'radar',
  130. data: {
  131. datasets: [{
  132. data: [50, 60, NaN, 70, null, undefined, Infinity, -Infinity]
  133. }],
  134. labels: ['label1', 'label2', 'label3', 'label4', 'label5', 'label6', 'label7', 'label8']
  135. },
  136. options: {
  137. scales: {}
  138. }
  139. });
  140. expect(chart.scale.min).toBe(50);
  141. expect(chart.scale.max).toBe(70);
  142. });
  143. it('Should ensure that the scale has a max and min that are not equal', function() {
  144. var scaleID = 'myScale';
  145. var mockData = {
  146. datasets: [],
  147. labels: []
  148. };
  149. var mockContext = window.createMockContext();
  150. var Constructor = Chart.scaleService.getScaleConstructor('radialLinear');
  151. var scale = new Constructor({
  152. ctx: mockContext,
  153. options: Chart.scaleService.getScaleDefaults('radialLinear'), // use default config for scale
  154. chart: {
  155. data: mockData
  156. },
  157. id: scaleID,
  158. });
  159. scale.update(200, 300);
  160. expect(scale.min).toBe(-1);
  161. expect(scale.max).toBe(1);
  162. });
  163. it('Should use the suggestedMin and suggestedMax options', function() {
  164. var chart = window.acquireChart({
  165. type: 'radar',
  166. data: {
  167. datasets: [{
  168. data: [1, 1, 1, 2, 1, 0]
  169. }],
  170. labels: ['label1', 'label2', 'label3', 'label4', 'label5', 'label6']
  171. },
  172. options: {
  173. scale: {
  174. ticks: {
  175. suggestedMin: -10,
  176. suggestedMax: 10
  177. }
  178. }
  179. }
  180. });
  181. expect(chart.scale.min).toBe(-10);
  182. expect(chart.scale.max).toBe(10);
  183. });
  184. it('Should use the min and max options', function() {
  185. var chart = window.acquireChart({
  186. type: 'radar',
  187. data: {
  188. datasets: [{
  189. data: [1, 1, 1, 2, 1, 0]
  190. }],
  191. labels: ['label1', 'label2', 'label3', 'label4', 'label5', 'label6']
  192. },
  193. options: {
  194. scale: {
  195. ticks: {
  196. min: -1010,
  197. max: 1010
  198. }
  199. }
  200. }
  201. });
  202. expect(chart.scale.min).toBe(-1010);
  203. expect(chart.scale.max).toBe(1010);
  204. expect(chart.scale.ticks).toEqual(['-1010', '-1000', '-500', '0', '500', '1000', '1010']);
  205. });
  206. it('should forcibly include 0 in the range if the beginAtZero option is used', function() {
  207. var chart = window.acquireChart({
  208. type: 'radar',
  209. data: {
  210. datasets: [{
  211. data: [20, 30, 40, 50]
  212. }],
  213. labels: ['label1', 'label2', 'label3', 'label4']
  214. },
  215. options: {
  216. scale: {
  217. ticks: {
  218. beginAtZero: false
  219. }
  220. }
  221. }
  222. });
  223. expect(chart.scale.ticks).toEqual(['20', '25', '30', '35', '40', '45', '50']);
  224. chart.scale.options.ticks.beginAtZero = true;
  225. chart.update();
  226. expect(chart.scale.ticks).toEqual(['0', '5', '10', '15', '20', '25', '30', '35', '40', '45', '50']);
  227. chart.data.datasets[0].data = [-20, -30, -40, -50];
  228. chart.update();
  229. expect(chart.scale.ticks).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']);
  230. chart.scale.options.ticks.beginAtZero = false;
  231. chart.update();
  232. expect(chart.scale.ticks).toEqual(['-50', '-45', '-40', '-35', '-30', '-25', '-20']);
  233. });
  234. it('Should generate tick marks in the correct order in reversed mode', function() {
  235. var chart = window.acquireChart({
  236. type: 'radar',
  237. data: {
  238. datasets: [{
  239. data: [10, 5, 0, 25, 78]
  240. }],
  241. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  242. },
  243. options: {
  244. scale: {
  245. ticks: {
  246. reverse: true
  247. }
  248. }
  249. }
  250. });
  251. expect(chart.scale.ticks).toEqual(['80', '70', '60', '50', '40', '30', '20', '10', '0']);
  252. expect(chart.scale.start).toBe(80);
  253. expect(chart.scale.end).toBe(0);
  254. });
  255. it('Should correctly limit the maximum number of ticks', function() {
  256. var chart = window.acquireChart({
  257. type: 'radar',
  258. data: {
  259. labels: ['label1', 'label2', 'label3'],
  260. datasets: [{
  261. data: [0.5, 1.5, 2.5]
  262. }]
  263. },
  264. options: {
  265. scale: {
  266. pointLabels: {
  267. display: false
  268. }
  269. }
  270. }
  271. });
  272. expect(chart.scale.ticks).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']);
  273. chart.options.scale.ticks.maxTicksLimit = 11;
  274. chart.update();
  275. expect(chart.scale.ticks).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']);
  276. chart.options.scale.ticks.stepSize = 0.01;
  277. chart.update();
  278. expect(chart.scale.ticks).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']);
  279. chart.options.scale.ticks.min = 0.3;
  280. chart.options.scale.ticks.max = 2.8;
  281. chart.update();
  282. expect(chart.scale.ticks).toEqual(['0.3', '0.5', '1.0', '1.5', '2.0', '2.5', '2.8']);
  283. });
  284. it('Should build labels using the user supplied callback', function() {
  285. var chart = window.acquireChart({
  286. type: 'radar',
  287. data: {
  288. datasets: [{
  289. data: [10, 5, 0, 25, 78]
  290. }],
  291. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  292. },
  293. options: {
  294. scale: {
  295. ticks: {
  296. callback: function(value, index) {
  297. return index.toString();
  298. }
  299. }
  300. }
  301. }
  302. });
  303. expect(chart.scale.ticks).toEqual(['0', '1', '2', '3', '4', '5', '6', '7', '8']);
  304. expect(chart.scale.pointLabels).toEqual(['label1', 'label2', 'label3', 'label4', 'label5']);
  305. });
  306. it('Should build point labels using the user supplied callback', function() {
  307. var chart = window.acquireChart({
  308. type: 'radar',
  309. data: {
  310. datasets: [{
  311. data: [10, 5, 0, 25, 78]
  312. }],
  313. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  314. },
  315. options: {
  316. scale: {
  317. pointLabels: {
  318. callback: function(value, index) {
  319. return index.toString();
  320. }
  321. }
  322. }
  323. }
  324. });
  325. expect(chart.scale.pointLabels).toEqual(['0', '1', '2', '3', '4']);
  326. });
  327. it('Should build point labels from falsy values', function() {
  328. var chart = window.acquireChart({
  329. type: 'radar',
  330. data: {
  331. datasets: [{
  332. data: [10, 5, 0, 25, 78, 20]
  333. }],
  334. labels: [0, '', undefined, null, NaN, false]
  335. }
  336. });
  337. expect(chart.scale.pointLabels).toEqual([0, '', '', '', '', '']);
  338. });
  339. it('should correctly set the center point', function() {
  340. var chart = window.acquireChart({
  341. type: 'radar',
  342. data: {
  343. datasets: [{
  344. data: [10, 5, 0, 25, 78]
  345. }],
  346. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  347. },
  348. options: {
  349. scale: {
  350. pointLabels: {
  351. callback: function(value, index) {
  352. return index.toString();
  353. }
  354. }
  355. }
  356. }
  357. });
  358. expect(chart.scale.drawingArea).toBe(227);
  359. expect(chart.scale.xCenter).toBe(256);
  360. expect(chart.scale.yCenter).toBe(284);
  361. });
  362. it('should correctly get the label for a given data index', function() {
  363. var chart = window.acquireChart({
  364. type: 'radar',
  365. data: {
  366. datasets: [{
  367. data: [10, 5, 0, 25, 78]
  368. }],
  369. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  370. },
  371. options: {
  372. scale: {
  373. pointLabels: {
  374. callback: function(value, index) {
  375. return index.toString();
  376. }
  377. }
  378. }
  379. }
  380. });
  381. expect(chart.scale.getLabelForIndex(1, 0)).toBe(5);
  382. });
  383. it('should get the correct distance from the center point', function() {
  384. var chart = window.acquireChart({
  385. type: 'radar',
  386. data: {
  387. datasets: [{
  388. data: [10, 5, 0, 25, 78]
  389. }],
  390. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  391. },
  392. options: {
  393. scale: {
  394. pointLabels: {
  395. callback: function(value, index) {
  396. return index.toString();
  397. }
  398. }
  399. }
  400. }
  401. });
  402. expect(chart.scale.getDistanceFromCenterForValue(chart.scale.min)).toBe(0);
  403. expect(chart.scale.getDistanceFromCenterForValue(chart.scale.max)).toBe(227);
  404. var position = chart.scale.getPointPositionForValue(1, 5);
  405. expect(position.x).toBeCloseToPixel(270);
  406. expect(position.y).toBeCloseToPixel(278);
  407. chart.scale.options.ticks.reverse = true;
  408. chart.update();
  409. expect(chart.scale.getDistanceFromCenterForValue(chart.scale.min)).toBe(227);
  410. expect(chart.scale.getDistanceFromCenterForValue(chart.scale.max)).toBe(0);
  411. });
  412. it('should correctly get angles for all points', function() {
  413. var chart = window.acquireChart({
  414. type: 'radar',
  415. data: {
  416. datasets: [{
  417. data: [10, 5, 0, 25, 78]
  418. }],
  419. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  420. },
  421. options: {
  422. scale: {
  423. pointLabels: {
  424. callback: function(value, index) {
  425. return index.toString();
  426. }
  427. }
  428. },
  429. startAngle: 15
  430. }
  431. });
  432. var radToNearestDegree = function(rad) {
  433. return Math.round((360 * rad) / (2 * Math.PI));
  434. };
  435. var slice = 72; // (360 / 5)
  436. for (var i = 0; i < 5; i++) {
  437. expect(radToNearestDegree(chart.scale.getIndexAngle(i))).toBe(15 + (slice * i));
  438. }
  439. chart.options.startAngle = 0;
  440. chart.update();
  441. for (var x = 0; x < 5; x++) {
  442. expect(radToNearestDegree(chart.scale.getIndexAngle(x))).toBe((slice * x));
  443. }
  444. });
  445. it('should correctly get the correct label alignment for all points', function() {
  446. var chart = window.acquireChart({
  447. type: 'radar',
  448. data: {
  449. datasets: [{
  450. data: [10, 5, 0, 25, 78]
  451. }],
  452. labels: ['label1', 'label2', 'label3', 'label4', 'label5']
  453. },
  454. options: {
  455. scale: {
  456. pointLabels: {
  457. callback: function(value, index) {
  458. return index.toString();
  459. }
  460. },
  461. ticks: {
  462. display: false
  463. }
  464. }
  465. }
  466. });
  467. var scale = chart.scale;
  468. [{
  469. startAngle: 30,
  470. textAlign: ['right', 'right', 'left', 'left', 'left'],
  471. y: [82, 366, 506, 319, 53]
  472. }, {
  473. startAngle: -30,
  474. textAlign: ['right', 'right', 'left', 'left', 'right'],
  475. y: [319, 506, 366, 82, 53]
  476. }, {
  477. startAngle: 750,
  478. textAlign: ['right', 'right', 'left', 'left', 'left'],
  479. y: [82, 366, 506, 319, 53]
  480. }].forEach(function(expected) {
  481. chart.options.startAngle = expected.startAngle;
  482. chart.update();
  483. scale.ctx = window.createMockContext();
  484. chart.draw();
  485. scale.ctx.getCalls().filter(function(x) {
  486. return x.name === 'setTextAlign';
  487. }).forEach(function(x, i) {
  488. expect(x.args[0]).toBe(expected.textAlign[i]);
  489. });
  490. scale.ctx.getCalls().filter(function(x) {
  491. return x.name === 'fillText';
  492. }).map(function(x, i) {
  493. expect(x.args[2]).toBeCloseToPixel(expected.y[i]);
  494. });
  495. });
  496. });
  497. });