index.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /**
  2. * A helper file that may be used in test cases for bpmn-js and extensions.
  3. *
  4. * Provides the globals
  5. *
  6. * * bootstrapModeler(): bootstrap a modeler instance
  7. * * bootstrapViewer(): bootstrap a viewer instance
  8. * * inject(function(a, b) {}): inject the bpmn-js services in the given function
  9. *
  10. *
  11. * In addition it provides the utilities
  12. *
  13. * * insertCSS(name, css): add a CSS file to be used in test cases
  14. *
  15. *
  16. * It is recommended to expose the helper through a per-project utility and
  17. * and perform custom bootstrapping (CSS, ...) in that utility.
  18. *
  19. * ```
  20. * export * from 'bpmn-js/test/helper';
  21. *
  22. * import {
  23. * insertCSS
  24. * } from 'bpmn-js/test/helper';
  25. *
  26. * var fs = require('fs');
  27. *
  28. * // insert diagram.css
  29. * insertCSS('diagram.css', fs.readFileSync('some-css.css', 'utf8'));
  30. * ```
  31. */
  32. import {
  33. isFunction,
  34. forEach,
  35. merge
  36. } from 'min-dash';
  37. import TestContainer from 'mocha-test-container-support';
  38. import Modeler from '../../lib/Modeler';
  39. import Viewer from '../../lib/Viewer';
  40. var OPTIONS, BPMN_JS;
  41. import translationModule from './TranslationCollector';
  42. export function bootstrapBpmnJS(BpmnJS, diagram, options, locals) {
  43. return function(done) {
  44. var testContainer;
  45. // Make sure the test container is an optional dependency and we fall back
  46. // to an empty <div> if it does not exist.
  47. //
  48. // This is needed if other libraries rely on this helper for testing
  49. // while not adding the mocha-test-container-support as a dependency.
  50. try {
  51. // 'this' is the current test context
  52. testContainer = TestContainer.get(this);
  53. } catch (e) {
  54. testContainer = document.createElement('div');
  55. document.body.appendChild(testContainer);
  56. }
  57. testContainer.classList.add('test-container');
  58. var _options = options,
  59. _locals = locals;
  60. if (_locals === undefined && isFunction(_options)) {
  61. _locals = _options;
  62. _options = null;
  63. }
  64. if (isFunction(_options)) {
  65. _options = _options();
  66. }
  67. if (isFunction(_locals)) {
  68. _locals = _locals();
  69. }
  70. _options = merge({
  71. container: testContainer,
  72. canvas: {
  73. deferUpdate: false
  74. }
  75. }, OPTIONS, _options);
  76. if (_locals) {
  77. var mockModule = {};
  78. forEach(_locals, function(v, k) {
  79. mockModule[k] = ['value', v];
  80. });
  81. _options.modules = [].concat(_options.modules || [], [ mockModule ]);
  82. }
  83. if (_options.modules && !_options.modules.length) {
  84. _options.modules = undefined;
  85. }
  86. // used to extract translations used during tests
  87. if (window.__env__ && window.__env__.TRANSLATIONS === 'enabled') {
  88. _options.additionalModules = [].concat(
  89. _options.additionalModules || [],
  90. [ translationModule ]
  91. );
  92. }
  93. // clean up old bpmn-js instance
  94. if (BPMN_JS) {
  95. BPMN_JS.destroy();
  96. }
  97. BPMN_JS = new BpmnJS(_options);
  98. BPMN_JS.importXML(diagram, done);
  99. };
  100. }
  101. /**
  102. * Bootstrap the Modeler given the specified options and a number of locals (i.e. services)
  103. *
  104. * @example
  105. *
  106. * describe(function() {
  107. *
  108. * var mockEvents;
  109. *
  110. * beforeEach(bootstrapModeler('some-xml', function() {
  111. * mockEvents = new Events();
  112. *
  113. * return {
  114. * events: mockEvents
  115. * };
  116. * }));
  117. *
  118. * });
  119. *
  120. * @param {String} xml document to display
  121. * @param {Object} (options) optional options to be passed to the diagram upon instantiation
  122. * @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them
  123. * @return {Function} a function to be passed to beforeEach
  124. */
  125. export function bootstrapModeler(diagram, options, locals) {
  126. return bootstrapBpmnJS(Modeler, diagram, options, locals);
  127. }
  128. /**
  129. * Bootstrap the Viewer given the specified options and a number of locals (i.e. services)
  130. *
  131. * @example
  132. *
  133. * describe(function() {
  134. *
  135. * var mockEvents;
  136. *
  137. * beforeEach(bootstrapViewer('some-xml', function() {
  138. * mockEvents = new Events();
  139. *
  140. * return {
  141. * events: mockEvents
  142. * };
  143. * }));
  144. *
  145. * });
  146. *
  147. * @param {String} xml document to display
  148. * @param {Object} (options) optional options to be passed to the diagram upon instantiation
  149. * @param {Object|Function} locals the local overrides to be used by the diagram or a function that produces them
  150. * @return {Function} a function to be passed to beforeEach
  151. */
  152. export function bootstrapViewer(diagram, options, locals) {
  153. return bootstrapBpmnJS(Viewer, diagram, options, locals);
  154. }
  155. /**
  156. * Injects services of an instantiated diagram into the argument.
  157. *
  158. * Use it in conjunction with {@link #bootstrapModeler} or {@link #bootstrapViewer}.
  159. *
  160. * @example
  161. *
  162. * describe(function() {
  163. *
  164. * var mockEvents;
  165. *
  166. * beforeEach(bootstrapViewer(...));
  167. *
  168. * it('should provide mocked events', inject(function(events) {
  169. * expect(events).to.eql(mockEvents);
  170. * }));
  171. *
  172. * });
  173. *
  174. * @param {Function} fn the function to inject to
  175. * @return {Function} a function that can be passed to it to carry out the injection
  176. */
  177. export function inject(fn) {
  178. return function() {
  179. if (!BPMN_JS) {
  180. throw new Error(
  181. 'no bootstraped bpmn-js instance, ' +
  182. 'ensure you created it via #boostrap(Modeler|Viewer)'
  183. );
  184. }
  185. BPMN_JS.invoke(fn);
  186. };
  187. }
  188. /**
  189. * Returns the current active BpmnJS instance.
  190. *
  191. * @return {BpmnJS}
  192. */
  193. export function getBpmnJS() {
  194. return BPMN_JS;
  195. }
  196. export function insertCSS(name, css) {
  197. if (document.querySelector('[data-css-file="' + name + '"]')) {
  198. return;
  199. }
  200. var head = document.head || document.getElementsByTagName('head')[0],
  201. style = document.createElement('style');
  202. style.setAttribute('data-css-file', name);
  203. style.type = 'text/css';
  204. if (style.styleSheet) {
  205. style.styleSheet.cssText = css;
  206. } else {
  207. style.appendChild(document.createTextNode(css));
  208. }
  209. head.appendChild(style);
  210. }