plugin.legend.tests.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. // Test the rectangle element
  2. describe('Legend block tests', function() {
  3. describe('auto', jasmine.fixture.specs('plugin.legend'));
  4. it('should have the correct default config', function() {
  5. expect(Chart.defaults.global.legend).toEqual({
  6. display: true,
  7. position: 'top',
  8. align: 'center',
  9. fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
  10. reverse: false,
  11. weight: 1000,
  12. // a callback that will handle
  13. onClick: jasmine.any(Function),
  14. onHover: null,
  15. onLeave: null,
  16. labels: {
  17. boxWidth: 40,
  18. padding: 10,
  19. generateLabels: jasmine.any(Function)
  20. }
  21. });
  22. });
  23. it('should update bar chart correctly', function() {
  24. var chart = window.acquireChart({
  25. type: 'bar',
  26. data: {
  27. datasets: [{
  28. label: 'dataset1',
  29. backgroundColor: '#f31',
  30. borderCapStyle: 'butt',
  31. borderDash: [2, 2],
  32. borderDashOffset: 5.5,
  33. data: []
  34. }, {
  35. label: 'dataset2',
  36. hidden: true,
  37. borderJoinStyle: 'miter',
  38. data: []
  39. }, {
  40. label: 'dataset3',
  41. borderWidth: 10,
  42. borderColor: 'green',
  43. pointStyle: 'crossRot',
  44. data: []
  45. }],
  46. labels: []
  47. }
  48. });
  49. expect(chart.legend.legendItems).toEqual([{
  50. text: 'dataset1',
  51. fillStyle: '#f31',
  52. hidden: false,
  53. lineCap: undefined,
  54. lineDash: undefined,
  55. lineDashOffset: undefined,
  56. lineJoin: undefined,
  57. lineWidth: 0,
  58. strokeStyle: 'rgba(0,0,0,0.1)',
  59. pointStyle: undefined,
  60. rotation: undefined,
  61. datasetIndex: 0
  62. }, {
  63. text: 'dataset2',
  64. fillStyle: 'rgba(0,0,0,0.1)',
  65. hidden: true,
  66. lineCap: undefined,
  67. lineDash: undefined,
  68. lineDashOffset: undefined,
  69. lineJoin: undefined,
  70. lineWidth: 0,
  71. strokeStyle: 'rgba(0,0,0,0.1)',
  72. pointStyle: undefined,
  73. rotation: undefined,
  74. datasetIndex: 1
  75. }, {
  76. text: 'dataset3',
  77. fillStyle: 'rgba(0,0,0,0.1)',
  78. hidden: false,
  79. lineCap: undefined,
  80. lineDash: undefined,
  81. lineDashOffset: undefined,
  82. lineJoin: undefined,
  83. lineWidth: 10,
  84. strokeStyle: 'green',
  85. pointStyle: undefined,
  86. rotation: undefined,
  87. datasetIndex: 2
  88. }]);
  89. });
  90. it('should update line chart correctly', function() {
  91. var chart = window.acquireChart({
  92. type: 'line',
  93. data: {
  94. datasets: [{
  95. label: 'dataset1',
  96. backgroundColor: '#f31',
  97. borderCapStyle: 'round',
  98. borderDash: [2, 2],
  99. borderDashOffset: 5.5,
  100. data: []
  101. }, {
  102. label: 'dataset2',
  103. hidden: true,
  104. borderJoinStyle: 'round',
  105. data: []
  106. }, {
  107. label: 'dataset3',
  108. borderWidth: 10,
  109. borderColor: 'green',
  110. pointStyle: 'crossRot',
  111. fill: false,
  112. data: []
  113. }],
  114. labels: []
  115. }
  116. });
  117. expect(chart.legend.legendItems).toEqual([{
  118. text: 'dataset1',
  119. fillStyle: '#f31',
  120. hidden: false,
  121. lineCap: 'round',
  122. lineDash: [2, 2],
  123. lineDashOffset: 5.5,
  124. lineJoin: 'miter',
  125. lineWidth: 3,
  126. strokeStyle: 'rgba(0,0,0,0.1)',
  127. pointStyle: undefined,
  128. rotation: undefined,
  129. datasetIndex: 0
  130. }, {
  131. text: 'dataset2',
  132. fillStyle: 'rgba(0,0,0,0.1)',
  133. hidden: true,
  134. lineCap: 'butt',
  135. lineDash: [],
  136. lineDashOffset: 0,
  137. lineJoin: 'round',
  138. lineWidth: 3,
  139. strokeStyle: 'rgba(0,0,0,0.1)',
  140. pointStyle: undefined,
  141. rotation: undefined,
  142. datasetIndex: 1
  143. }, {
  144. text: 'dataset3',
  145. fillStyle: 'rgba(0,0,0,0)',
  146. hidden: false,
  147. lineCap: 'butt',
  148. lineDash: [],
  149. lineDashOffset: 0,
  150. lineJoin: 'miter',
  151. lineWidth: 10,
  152. strokeStyle: 'green',
  153. pointStyle: undefined,
  154. rotation: undefined,
  155. datasetIndex: 2
  156. }]);
  157. });
  158. it('should filter items', function() {
  159. var chart = window.acquireChart({
  160. type: 'bar',
  161. data: {
  162. datasets: [{
  163. label: 'dataset1',
  164. backgroundColor: '#f31',
  165. borderCapStyle: 'butt',
  166. borderDash: [2, 2],
  167. borderDashOffset: 5.5,
  168. data: []
  169. }, {
  170. label: 'dataset2',
  171. hidden: true,
  172. borderJoinStyle: 'miter',
  173. data: [],
  174. legendHidden: true
  175. }, {
  176. label: 'dataset3',
  177. borderWidth: 10,
  178. borderColor: 'green',
  179. pointStyle: 'crossRot',
  180. data: []
  181. }],
  182. labels: []
  183. },
  184. options: {
  185. legend: {
  186. labels: {
  187. filter: function(legendItem, data) {
  188. var dataset = data.datasets[legendItem.datasetIndex];
  189. return !dataset.legendHidden;
  190. }
  191. }
  192. }
  193. }
  194. });
  195. expect(chart.legend.legendItems).toEqual([{
  196. text: 'dataset1',
  197. fillStyle: '#f31',
  198. hidden: false,
  199. lineCap: undefined,
  200. lineDash: undefined,
  201. lineDashOffset: undefined,
  202. lineJoin: undefined,
  203. lineWidth: 0,
  204. strokeStyle: 'rgba(0,0,0,0.1)',
  205. pointStyle: undefined,
  206. rotation: undefined,
  207. datasetIndex: 0
  208. }, {
  209. text: 'dataset3',
  210. fillStyle: 'rgba(0,0,0,0.1)',
  211. hidden: false,
  212. lineCap: undefined,
  213. lineDash: undefined,
  214. lineDashOffset: undefined,
  215. lineJoin: undefined,
  216. lineWidth: 10,
  217. strokeStyle: 'green',
  218. pointStyle: undefined,
  219. rotation: undefined,
  220. datasetIndex: 2
  221. }]);
  222. });
  223. it('should not throw when the label options are missing', function() {
  224. var makeChart = function() {
  225. window.acquireChart({
  226. type: 'bar',
  227. data: {
  228. datasets: [{
  229. label: 'dataset1',
  230. backgroundColor: '#f31',
  231. borderCapStyle: 'butt',
  232. borderDash: [2, 2],
  233. borderDashOffset: 5.5,
  234. data: []
  235. }],
  236. labels: []
  237. },
  238. options: {
  239. legend: {
  240. labels: false,
  241. }
  242. }
  243. });
  244. };
  245. expect(makeChart).not.toThrow();
  246. });
  247. it('should not draw legend items outside of the chart bounds', function() {
  248. var chart = window.acquireChart(
  249. {
  250. type: 'line',
  251. data: {
  252. datasets: [1, 2, 3].map(function(n) {
  253. return {
  254. label: 'dataset' + n,
  255. data: []
  256. };
  257. }),
  258. labels: []
  259. },
  260. options: {
  261. legend: {
  262. position: 'right'
  263. }
  264. }
  265. },
  266. {
  267. canvas: {
  268. width: 512,
  269. height: 105
  270. }
  271. }
  272. );
  273. // Check some basic assertions about the test setup
  274. expect(chart.width).toBe(512);
  275. expect(chart.legend.legendHitBoxes.length).toBe(3);
  276. // Check whether any legend items reach outside the established bounds
  277. chart.legend.legendHitBoxes.forEach(function(item) {
  278. expect(item.left + item.width).toBeLessThanOrEqual(chart.width);
  279. });
  280. });
  281. it('should pick up the first item when the property is an array', function() {
  282. var chart = window.acquireChart({
  283. type: 'bar',
  284. data: {
  285. datasets: [{
  286. label: 'dataset1',
  287. backgroundColor: ['#f31', '#666', '#14e'],
  288. borderWidth: [5, 10, 15],
  289. borderColor: ['red', 'green', 'blue'],
  290. data: []
  291. }],
  292. labels: []
  293. }
  294. });
  295. expect(chart.legend.legendItems).toEqual([{
  296. text: 'dataset1',
  297. fillStyle: '#f31',
  298. hidden: false,
  299. lineCap: undefined,
  300. lineDash: undefined,
  301. lineDashOffset: undefined,
  302. lineJoin: undefined,
  303. lineWidth: 5,
  304. strokeStyle: 'red',
  305. pointStyle: undefined,
  306. rotation: undefined,
  307. datasetIndex: 0
  308. }]);
  309. });
  310. it('should use the value for the first item when the property is a function', function() {
  311. var helpers = window.Chart.helpers;
  312. var chart = window.acquireChart({
  313. type: 'bar',
  314. data: {
  315. datasets: [{
  316. label: 'dataset1',
  317. backgroundColor: function(ctx) {
  318. var value = ctx.dataset.data[ctx.dataIndex] || 0;
  319. return helpers.color({r: value * 10, g: 0, b: 0}).rgbString();
  320. },
  321. borderWidth: function(ctx) {
  322. var value = ctx.dataset.data[ctx.dataIndex] || 0;
  323. return value;
  324. },
  325. borderColor: function(ctx) {
  326. var value = ctx.dataset.data[ctx.dataIndex] || 0;
  327. return helpers.color({r: 255 - value * 10, g: 0, b: 0}).rgbString();
  328. },
  329. data: [5, 10, 15, 20]
  330. }],
  331. labels: ['A', 'B', 'C', 'D']
  332. }
  333. });
  334. expect(chart.legend.legendItems).toEqual([{
  335. text: 'dataset1',
  336. fillStyle: 'rgb(50, 0, 0)',
  337. hidden: false,
  338. lineCap: undefined,
  339. lineDash: undefined,
  340. lineDashOffset: undefined,
  341. lineJoin: undefined,
  342. lineWidth: 5,
  343. strokeStyle: 'rgb(205, 0, 0)',
  344. pointStyle: undefined,
  345. rotation: undefined,
  346. datasetIndex: 0
  347. }]);
  348. });
  349. it('should draw correctly when usePointStyle is true', function() {
  350. var chart = window.acquireChart({
  351. type: 'line',
  352. data: {
  353. datasets: [{
  354. label: 'dataset1',
  355. backgroundColor: '#f31',
  356. borderCapStyle: 'butt',
  357. borderDash: [2, 2],
  358. borderDashOffset: 5.5,
  359. borderWidth: 0,
  360. borderColor: '#f31',
  361. pointStyle: 'crossRot',
  362. pointBackgroundColor: 'rgba(0,0,0,0.1)',
  363. pointBorderWidth: 5,
  364. pointBorderColor: 'green',
  365. data: []
  366. }, {
  367. label: 'dataset2',
  368. backgroundColor: '#f31',
  369. borderJoinStyle: 'miter',
  370. borderWidth: 2,
  371. borderColor: '#f31',
  372. pointStyle: 'crossRot',
  373. pointRotation: 15,
  374. data: []
  375. }],
  376. labels: []
  377. },
  378. options: {
  379. legend: {
  380. labels: {
  381. usePointStyle: true
  382. }
  383. }
  384. }
  385. });
  386. expect(chart.legend.legendItems).toEqual([{
  387. text: 'dataset1',
  388. fillStyle: 'rgba(0,0,0,0.1)',
  389. hidden: false,
  390. lineCap: undefined,
  391. lineDash: undefined,
  392. lineDashOffset: undefined,
  393. lineJoin: undefined,
  394. lineWidth: 5,
  395. strokeStyle: 'green',
  396. pointStyle: 'crossRot',
  397. rotation: undefined,
  398. datasetIndex: 0
  399. }, {
  400. text: 'dataset2',
  401. fillStyle: '#f31',
  402. hidden: false,
  403. lineCap: undefined,
  404. lineDash: undefined,
  405. lineDashOffset: undefined,
  406. lineJoin: undefined,
  407. lineWidth: 2,
  408. strokeStyle: '#f31',
  409. pointStyle: 'crossRot',
  410. rotation: 15,
  411. datasetIndex: 1
  412. }]);
  413. });
  414. describe('config update', function() {
  415. it ('should update the options', function() {
  416. var chart = acquireChart({
  417. type: 'line',
  418. data: {
  419. labels: ['A', 'B', 'C', 'D'],
  420. datasets: [{
  421. data: [10, 20, 30, 100]
  422. }]
  423. },
  424. options: {
  425. legend: {
  426. display: true
  427. }
  428. }
  429. });
  430. expect(chart.legend.options.display).toBe(true);
  431. chart.options.legend.display = false;
  432. chart.update();
  433. expect(chart.legend.options.display).toBe(false);
  434. });
  435. it ('should update the associated layout item', function() {
  436. var chart = acquireChart({
  437. type: 'line',
  438. data: {},
  439. options: {
  440. legend: {
  441. fullWidth: true,
  442. position: 'top',
  443. weight: 150
  444. }
  445. }
  446. });
  447. expect(chart.legend.fullWidth).toBe(true);
  448. expect(chart.legend.position).toBe('top');
  449. expect(chart.legend.weight).toBe(150);
  450. chart.options.legend.fullWidth = false;
  451. chart.options.legend.position = 'left';
  452. chart.options.legend.weight = 42;
  453. chart.update();
  454. expect(chart.legend.fullWidth).toBe(false);
  455. expect(chart.legend.position).toBe('left');
  456. expect(chart.legend.weight).toBe(42);
  457. });
  458. it ('should remove the legend if the new options are false', function() {
  459. var chart = acquireChart({
  460. type: 'line',
  461. data: {
  462. labels: ['A', 'B', 'C', 'D'],
  463. datasets: [{
  464. data: [10, 20, 30, 100]
  465. }]
  466. }
  467. });
  468. expect(chart.legend).not.toBe(undefined);
  469. chart.options.legend = false;
  470. chart.update();
  471. expect(chart.legend).toBe(undefined);
  472. });
  473. it ('should create the legend if the legend options are changed to exist', function() {
  474. var chart = acquireChart({
  475. type: 'line',
  476. data: {
  477. labels: ['A', 'B', 'C', 'D'],
  478. datasets: [{
  479. data: [10, 20, 30, 100]
  480. }]
  481. },
  482. options: {
  483. legend: false
  484. }
  485. });
  486. expect(chart.legend).toBe(undefined);
  487. chart.options.legend = {};
  488. chart.update();
  489. expect(chart.legend).not.toBe(undefined);
  490. expect(chart.legend.options).toEqual(jasmine.objectContaining(Chart.defaults.global.legend));
  491. });
  492. });
  493. describe('callbacks', function() {
  494. it('should call onClick, onHover and onLeave at the correct times', function() {
  495. var clickItem = null;
  496. var hoverItem = null;
  497. var leaveItem = null;
  498. var chart = acquireChart({
  499. type: 'line',
  500. data: {
  501. labels: ['A', 'B', 'C', 'D'],
  502. datasets: [{
  503. data: [10, 20, 30, 100]
  504. }]
  505. },
  506. options: {
  507. legend: {
  508. onClick: function(_, item) {
  509. clickItem = item;
  510. },
  511. onHover: function(_, item) {
  512. hoverItem = item;
  513. },
  514. onLeave: function(_, item) {
  515. leaveItem = item;
  516. }
  517. }
  518. }
  519. });
  520. var hb = chart.legend.legendHitBoxes[0];
  521. var el = {
  522. x: hb.left + (hb.width / 2),
  523. y: hb.top + (hb.height / 2)
  524. };
  525. jasmine.triggerMouseEvent(chart, 'click', el);
  526. expect(clickItem).toBe(chart.legend.legendItems[0]);
  527. jasmine.triggerMouseEvent(chart, 'mousemove', el);
  528. expect(hoverItem).toBe(chart.legend.legendItems[0]);
  529. jasmine.triggerMouseEvent(chart, 'mousemove', chart.getDatasetMeta(0).data[0]);
  530. expect(leaveItem).toBe(chart.legend.legendItems[0]);
  531. });
  532. });
  533. });