TooltipsSpec.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. import {
  2. bootstrapDiagram,
  3. inject
  4. } from 'test/TestHelper';
  5. import {
  6. forEach,
  7. assign
  8. } from 'min-dash';
  9. import { domify } from 'min-dom';
  10. import tooltipsModule from 'lib/features/tooltips';
  11. describe('features/tooltips', function() {
  12. describe('bootstrap', function() {
  13. beforeEach(bootstrapDiagram({ modules: [ tooltipsModule ] }));
  14. it('should expose api', inject(function(tooltips) {
  15. expect(tooltips).to.exist;
  16. expect(tooltips.get).to.exist;
  17. expect(tooltips.add).to.exist;
  18. expect(tooltips.remove).to.exist;
  19. }));
  20. });
  21. describe('#add', function() {
  22. beforeEach(bootstrapDiagram({ modules: [ tooltipsModule ] }));
  23. it('should add <div>', inject(function(tooltips, canvas) {
  24. // when
  25. var id = tooltips.add({
  26. position: {
  27. x: 100,
  28. y: 200
  29. },
  30. html: '<div class="tooltip"></div>'
  31. });
  32. // then
  33. expect(id).to.exist;
  34. expect(tooltips.get(id)).to.exist;
  35. expect(queryTooltip(id)).to.exist;
  36. }));
  37. it('should add Element', inject(function(tooltips, canvas) {
  38. // when
  39. var id = tooltips.add({
  40. position: {
  41. x: 100,
  42. y: 200
  43. },
  44. html: highlight(domify('<div class="tooltip" />'))
  45. });
  46. // then
  47. var tooltip = tooltips.get(id);
  48. expect(tooltip).to.exist;
  49. expect(isVisible(tooltips._tooltipRoot)).to.be.true;
  50. expect(isVisible(tooltip.html)).to.be.true;
  51. expect(queryTooltip(id)).to.exist;
  52. }));
  53. it('should add with timeout', function(done) {
  54. inject(function(tooltips, canvas) {
  55. // when
  56. var id = tooltips.add({
  57. position: {
  58. x: 100,
  59. y: 200
  60. },
  61. timeout: 200,
  62. html: '<div class="tooltip" id="html-ov"></div>'
  63. });
  64. // then
  65. expect(id).to.exist;
  66. expect(tooltips.get(id)).to.exist;
  67. // but when
  68. setTimeout(function() {
  69. expect(tooltips.get(id)).not.to.exist;
  70. done();
  71. }, 300);
  72. })();
  73. });
  74. });
  75. describe('#remove', function() {
  76. beforeEach(bootstrapDiagram({ modules: [ tooltipsModule ] }));
  77. it('should remove tooltip', inject(function(tooltips, canvas) {
  78. // given
  79. var id = tooltips.add({
  80. position: {
  81. x: 100,
  82. y: 200
  83. },
  84. html: highlight(domify('<div class="tooltip" id="html-ov2"></div>'))
  85. });
  86. // when
  87. tooltips.remove(id);
  88. // then
  89. expect(tooltips.get(id)).not.to.exist;
  90. expect(queryTooltip(id)).not.to.exist;
  91. }));
  92. it('should remove non-existing', inject(function(tooltips) {
  93. expect(function() {
  94. tooltips.remove('non-existing');
  95. }).not.to.throw;
  96. }));
  97. });
  98. describe('positioning', function() {
  99. beforeEach(bootstrapDiagram({ modules: [ tooltipsModule ] }));
  100. function position(tooltipHtml) {
  101. var parent = tooltipHtml.parentNode;
  102. var result = {};
  103. forEach([ 'left', 'right', 'top', 'bottom' ], function(pos) {
  104. var p = parseInt(parent.style[pos]);
  105. if (!isNaN(p)) {
  106. result[pos] = p;
  107. }
  108. });
  109. return result;
  110. }
  111. it('should position absolute', inject(function(tooltips) {
  112. var html = createOverlay();
  113. // when
  114. tooltips.add({
  115. position: {
  116. x: 100,
  117. y: 50
  118. },
  119. html: html
  120. });
  121. // then
  122. expect(position(html)).to.eql({
  123. left: 100,
  124. top: 50
  125. });
  126. }));
  127. });
  128. describe('zoom behavior', function() {
  129. beforeEach(bootstrapDiagram({
  130. modules: [ tooltipsModule ],
  131. canvas: { deferUpdate: false }
  132. }));
  133. function isVisible(element) {
  134. return element.parentNode.style.display !== 'none';
  135. }
  136. it('should respect default min/max show rules', inject(function(tooltips, canvas) {
  137. // given
  138. var html = createOverlay();
  139. tooltips.add({
  140. position: { x: 20, y: 50 },
  141. html: html
  142. });
  143. // when zoom in visibility range
  144. canvas.zoom(0.7);
  145. // then
  146. expect(isVisible(html)).to.be.true;
  147. // when zoom below visibility range
  148. canvas.zoom(0.6);
  149. // then
  150. expect(isVisible(html)).to.be.false;
  151. // when zoom in visibility range
  152. canvas.zoom(3.0);
  153. // then
  154. expect(isVisible(html)).to.be.true;
  155. // when zoom above visibility range
  156. canvas.zoom(6.0);
  157. // then
  158. expect(isVisible(html)).to.be.false;
  159. }));
  160. it('should respect tooltip specific min/max rules', inject(function(tooltips, canvas) {
  161. // given
  162. var html = createOverlay();
  163. tooltips.add({
  164. position: { x: 20, y: 50 },
  165. html: html,
  166. show: {
  167. minZoom: 0.3,
  168. maxZoom: 4
  169. }
  170. });
  171. // when zoom in visibility range
  172. canvas.zoom(0.6);
  173. // then
  174. expect(isVisible(html)).to.be.true;
  175. // when zoom on visibility range border
  176. canvas.zoom(0.3);
  177. // then
  178. expect(isVisible(html)).to.be.true;
  179. // when zoom below visibility range
  180. canvas.zoom(0.2);
  181. // then
  182. expect(isVisible(html)).to.be.false;
  183. // when zoom in visibility range
  184. canvas.zoom(3);
  185. // then
  186. expect(isVisible(html)).to.be.true;
  187. // when zoom on visibility range border
  188. canvas.zoom(4.0);
  189. // then
  190. expect(isVisible(html)).to.be.true;
  191. // when zoom above visibility range
  192. canvas.zoom(4.1);
  193. // then
  194. expect(isVisible(html)).to.be.false;
  195. }));
  196. });
  197. describe('scroll/zoom behavior', function() {
  198. beforeEach(bootstrapDiagram({
  199. modules: [ tooltipsModule ],
  200. canvas: { deferUpdate: false }
  201. }));
  202. it('should not be transformed initially', inject(function(tooltips, canvas) {
  203. // given
  204. // diagram got newly created
  205. // then
  206. expect(transformMatrix(tooltips._tooltipRoot)).not.to.exist;
  207. }));
  208. it('should transform tooltip container on scroll', inject(function(tooltips, canvas) {
  209. // when
  210. canvas.scroll({
  211. dx: 100,
  212. dy: 50
  213. });
  214. // then
  215. expect(transformMatrix(tooltips._tooltipRoot)).to.eql({
  216. a : 1, b : 0,
  217. c : 0, d : 1,
  218. e : 100, f : 50
  219. });
  220. }));
  221. it('should transform tooltip container on zoom', inject(function(tooltips, canvas) {
  222. // when
  223. canvas.zoom(2);
  224. var mtrx = transformMatrix(tooltips._tooltipRoot);
  225. // then
  226. expect(mtrx.a).to.eql(2);
  227. expect(mtrx.d).to.eql(2);
  228. }));
  229. it('should transform tooltip container on zoom (with position)', inject(function(tooltips, canvas) {
  230. // when
  231. canvas.zoom(2, { x: 300, y: 300 });
  232. // then
  233. expect(transformMatrix(tooltips._tooltipRoot)).to.eql({
  234. a : 2, b : 0,
  235. c : 0, d : 2,
  236. e : -300, f : -300
  237. });
  238. }));
  239. });
  240. });
  241. // helpers //////////////////////
  242. function asMatrix(transformStr) {
  243. if (transformStr && transformStr !== 'none') {
  244. var m = transformStr.match(/[+-]?\d*[.]?\d+(?=,|\))/g);
  245. return {
  246. a: parseFloat(m[0]),
  247. b: parseFloat(m[1]),
  248. c: parseFloat(m[2]),
  249. d: parseFloat(m[3]),
  250. e: parseFloat(m[4]),
  251. f: parseFloat(m[5])
  252. };
  253. }
  254. }
  255. function transformMatrix(element) {
  256. return asMatrix(element.style.transform);
  257. }
  258. function isVisible(element) {
  259. return window.getComputedStyle(element).display !== 'none';
  260. }
  261. function highlight(element) {
  262. assign(element.style, { background: 'fuchsia', minWidth: '10px', minHeight: '10px' });
  263. return element;
  264. }
  265. function createOverlay() {
  266. var element = highlight(domify('<div>TEST<br/>TEST</div>'));
  267. assign(element.style, { width: 40, height: 40 });
  268. return element;
  269. }
  270. function queryTooltip(id) {
  271. return document.querySelector('[data-tooltip-id=' + id + ']');
  272. }