platform.dom.tests.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. describe('Platform.dom', function() {
  2. describe('context acquisition', function() {
  3. var canvasId = 'chartjs-canvas';
  4. beforeEach(function() {
  5. var canvas = document.createElement('canvas');
  6. canvas.setAttribute('id', canvasId);
  7. window.document.body.appendChild(canvas);
  8. });
  9. afterEach(function() {
  10. document.getElementById(canvasId).remove();
  11. });
  12. // see https://github.com/chartjs/Chart.js/issues/2807
  13. it('should gracefully handle invalid item', function() {
  14. var chart = new Chart('foobar');
  15. expect(chart).not.toBeValidChart();
  16. chart.destroy();
  17. });
  18. it('should accept a DOM element id', function() {
  19. var canvas = document.getElementById(canvasId);
  20. var chart = new Chart(canvasId);
  21. expect(chart).toBeValidChart();
  22. expect(chart.canvas).toBe(canvas);
  23. expect(chart.ctx).toBe(canvas.getContext('2d'));
  24. chart.destroy();
  25. });
  26. it('should accept a canvas element', function() {
  27. var canvas = document.getElementById(canvasId);
  28. var chart = new Chart(canvas);
  29. expect(chart).toBeValidChart();
  30. expect(chart.canvas).toBe(canvas);
  31. expect(chart.ctx).toBe(canvas.getContext('2d'));
  32. chart.destroy();
  33. });
  34. it('should accept a canvas context2D', function() {
  35. var canvas = document.getElementById(canvasId);
  36. var context = canvas.getContext('2d');
  37. var chart = new Chart(context);
  38. expect(chart).toBeValidChart();
  39. expect(chart.canvas).toBe(canvas);
  40. expect(chart.ctx).toBe(context);
  41. chart.destroy();
  42. });
  43. it('should accept an array containing canvas', function() {
  44. var canvas = document.getElementById(canvasId);
  45. var chart = new Chart([canvas]);
  46. expect(chart).toBeValidChart();
  47. expect(chart.canvas).toBe(canvas);
  48. expect(chart.ctx).toBe(canvas.getContext('2d'));
  49. chart.destroy();
  50. });
  51. it('should accept a canvas from an iframe', function(done) {
  52. var iframe = document.createElement('iframe');
  53. iframe.onload = function() {
  54. var doc = iframe.contentDocument;
  55. doc.body.innerHTML += '<canvas id="chart"></canvas>';
  56. var canvas = doc.getElementById('chart');
  57. var chart = new Chart(canvas);
  58. expect(chart).toBeValidChart();
  59. expect(chart.canvas).toBe(canvas);
  60. expect(chart.ctx).toBe(canvas.getContext('2d'));
  61. chart.destroy();
  62. canvas.remove();
  63. iframe.remove();
  64. done();
  65. };
  66. document.body.appendChild(iframe);
  67. });
  68. });
  69. describe('config.options.aspectRatio', function() {
  70. it('should use default "global" aspect ratio for render and display sizes', function() {
  71. var chart = acquireChart({
  72. options: {
  73. responsive: false
  74. }
  75. }, {
  76. canvas: {
  77. style: 'width: 620px'
  78. }
  79. });
  80. expect(chart).toBeChartOfSize({
  81. dw: 620, dh: 310,
  82. rw: 620, rh: 310,
  83. });
  84. });
  85. it('should use default "chart" aspect ratio for render and display sizes', function() {
  86. var ratio = Chart.defaults.doughnut.aspectRatio;
  87. Chart.defaults.doughnut.aspectRatio = 1;
  88. var chart = acquireChart({
  89. type: 'doughnut',
  90. options: {
  91. responsive: false
  92. }
  93. }, {
  94. canvas: {
  95. style: 'width: 425px'
  96. }
  97. });
  98. Chart.defaults.doughnut.aspectRatio = ratio;
  99. expect(chart).toBeChartOfSize({
  100. dw: 425, dh: 425,
  101. rw: 425, rh: 425,
  102. });
  103. });
  104. it('should use "user" aspect ratio for render and display sizes', function() {
  105. var chart = acquireChart({
  106. options: {
  107. responsive: false,
  108. aspectRatio: 3
  109. }
  110. }, {
  111. canvas: {
  112. style: 'width: 405px'
  113. }
  114. });
  115. expect(chart).toBeChartOfSize({
  116. dw: 405, dh: 135,
  117. rw: 405, rh: 135,
  118. });
  119. });
  120. it('should not apply aspect ratio when height specified', function() {
  121. var chart = acquireChart({
  122. options: {
  123. responsive: false,
  124. aspectRatio: 3
  125. }
  126. }, {
  127. canvas: {
  128. style: 'width: 400px; height: 410px'
  129. }
  130. });
  131. expect(chart).toBeChartOfSize({
  132. dw: 400, dh: 410,
  133. rw: 400, rh: 410,
  134. });
  135. });
  136. });
  137. describe('config.options.responsive: false', function() {
  138. it('should use default canvas size for render and display sizes', function() {
  139. var chart = acquireChart({
  140. options: {
  141. responsive: false
  142. }
  143. }, {
  144. canvas: {
  145. style: ''
  146. }
  147. });
  148. expect(chart).toBeChartOfSize({
  149. dw: 300, dh: 150,
  150. rw: 300, rh: 150,
  151. });
  152. });
  153. it('should use canvas attributes for render and display sizes', function() {
  154. var chart = acquireChart({
  155. options: {
  156. responsive: false
  157. }
  158. }, {
  159. canvas: {
  160. style: '',
  161. width: 305,
  162. height: 245,
  163. }
  164. });
  165. expect(chart).toBeChartOfSize({
  166. dw: 305, dh: 245,
  167. rw: 305, rh: 245,
  168. });
  169. });
  170. it('should use canvas style for render and display sizes (if no attributes)', function() {
  171. var chart = acquireChart({
  172. options: {
  173. responsive: false
  174. }
  175. }, {
  176. canvas: {
  177. style: 'width: 345px; height: 125px'
  178. }
  179. });
  180. expect(chart).toBeChartOfSize({
  181. dw: 345, dh: 125,
  182. rw: 345, rh: 125,
  183. });
  184. });
  185. it('should use attributes for the render size and style for the display size', function() {
  186. var chart = acquireChart({
  187. options: {
  188. responsive: false
  189. }
  190. }, {
  191. canvas: {
  192. style: 'width: 345px; height: 125px;',
  193. width: 165,
  194. height: 85,
  195. }
  196. });
  197. expect(chart).toBeChartOfSize({
  198. dw: 345, dh: 125,
  199. rw: 165, rh: 85,
  200. });
  201. });
  202. // https://github.com/chartjs/Chart.js/issues/3860
  203. it('should support decimal display width and/or height', function() {
  204. var chart = acquireChart({
  205. options: {
  206. responsive: false
  207. }
  208. }, {
  209. canvas: {
  210. style: 'width: 345.42px; height: 125.42px;'
  211. }
  212. });
  213. expect(chart).toBeChartOfSize({
  214. dw: 345, dh: 125,
  215. rw: 345, rh: 125,
  216. });
  217. });
  218. });
  219. describe('config.options.responsive: true (maintainAspectRatio: true)', function() {
  220. it('should fill parent width and use aspect ratio to calculate height', function() {
  221. var chart = acquireChart({
  222. options: {
  223. responsive: true,
  224. maintainAspectRatio: true
  225. }
  226. }, {
  227. canvas: {
  228. style: 'width: 150px; height: 245px'
  229. },
  230. wrapper: {
  231. style: 'width: 300px; height: 350px'
  232. }
  233. });
  234. expect(chart).toBeChartOfSize({
  235. dw: 300, dh: 490,
  236. rw: 300, rh: 490,
  237. });
  238. });
  239. });
  240. describe('controller.destroy', function() {
  241. it('should reset context to default values', function() {
  242. var chart = acquireChart({});
  243. var context = chart.ctx;
  244. chart.destroy();
  245. // https://www.w3.org/TR/2dcontext/#conformance-requirements
  246. Chart.helpers.each({
  247. fillStyle: '#000000',
  248. font: '10px sans-serif',
  249. lineJoin: 'miter',
  250. lineCap: 'butt',
  251. lineWidth: 1,
  252. miterLimit: 10,
  253. shadowBlur: 0,
  254. shadowColor: 'rgba(0, 0, 0, 0)',
  255. shadowOffsetX: 0,
  256. shadowOffsetY: 0,
  257. strokeStyle: '#000000',
  258. textAlign: 'start',
  259. textBaseline: 'alphabetic'
  260. }, function(value, key) {
  261. expect(context[key]).toBe(value);
  262. });
  263. });
  264. it('should restore canvas initial values', function(done) {
  265. var chart = acquireChart({
  266. options: {
  267. responsive: true,
  268. maintainAspectRatio: false
  269. }
  270. }, {
  271. canvas: {
  272. width: 180,
  273. style: 'width: 512px; height: 480px'
  274. },
  275. wrapper: {
  276. style: 'width: 450px; height: 450px; position: relative'
  277. }
  278. });
  279. var canvas = chart.canvas;
  280. var wrapper = canvas.parentNode;
  281. wrapper.style.width = '475px';
  282. waitForResize(chart, function() {
  283. expect(chart).toBeChartOfSize({
  284. dw: 475, dh: 450,
  285. rw: 475, rh: 450,
  286. });
  287. chart.destroy();
  288. expect(canvas.getAttribute('width')).toBe('180');
  289. expect(canvas.getAttribute('height')).toBe(null);
  290. expect(canvas.style.width).toBe('512px');
  291. expect(canvas.style.height).toBe('480px');
  292. expect(canvas.style.display).toBe('');
  293. done();
  294. });
  295. });
  296. });
  297. describe('event handling', function() {
  298. it('should notify plugins about events', function() {
  299. var notifiedEvent;
  300. var plugin = {
  301. afterEvent: function(chart, e) {
  302. notifiedEvent = e;
  303. }
  304. };
  305. var chart = acquireChart({
  306. type: 'line',
  307. data: {
  308. labels: ['A', 'B', 'C', 'D'],
  309. datasets: [{
  310. data: [10, 20, 30, 100]
  311. }]
  312. },
  313. options: {
  314. responsive: true
  315. },
  316. plugins: [plugin]
  317. });
  318. var node = chart.canvas;
  319. var rect = node.getBoundingClientRect();
  320. var clientX = (rect.left + rect.right) / 2;
  321. var clientY = (rect.top + rect.bottom) / 2;
  322. var evt = new MouseEvent('click', {
  323. view: window,
  324. bubbles: true,
  325. cancelable: true,
  326. clientX: clientX,
  327. clientY: clientY
  328. });
  329. // Manually trigger rather than having an async test
  330. node.dispatchEvent(evt);
  331. // Check that notifiedEvent is correct
  332. expect(notifiedEvent).not.toBe(undefined);
  333. expect(notifiedEvent.native).toBe(evt);
  334. // Is type correctly translated
  335. expect(notifiedEvent.type).toBe(evt.type);
  336. // Relative Position
  337. expect(notifiedEvent.x).toBeCloseToPixel(chart.width / 2);
  338. expect(notifiedEvent.y).toBeCloseToPixel(chart.height / 2);
  339. });
  340. });
  341. });