common.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. 'use strict';
  2. /**
  3. * @typedef {import('../context.js')} Context
  4. * @typedef {import('../mocha.js')} Mocha
  5. */
  6. /**
  7. @module interfaces/common
  8. */
  9. var Suite = require('../suite');
  10. var errors = require('../errors');
  11. var createMissingArgumentError = errors.createMissingArgumentError;
  12. var createUnsupportedError = errors.createUnsupportedError;
  13. var createForbiddenExclusivityError = errors.createForbiddenExclusivityError;
  14. /**
  15. * Functions common to more than one interface.
  16. *
  17. * @private
  18. * @param {Suite[]} suites
  19. * @param {Context} context
  20. * @param {Mocha} mocha
  21. * @return {Object} An object containing common functions.
  22. */
  23. module.exports = function (suites, context, mocha) {
  24. /**
  25. * Check if the suite should be tested.
  26. *
  27. * @private
  28. * @param {Suite} suite - suite to check
  29. * @returns {boolean}
  30. */
  31. function shouldBeTested(suite) {
  32. return (
  33. !mocha.options.grep ||
  34. (mocha.options.grep &&
  35. mocha.options.grep.test(suite.fullTitle()) &&
  36. !mocha.options.invert)
  37. );
  38. }
  39. return {
  40. /**
  41. * This is only present if flag --delay is passed into Mocha. It triggers
  42. * root suite execution.
  43. *
  44. * @param {Suite} suite The root suite.
  45. * @return {Function} A function which runs the root suite
  46. */
  47. runWithSuite: function runWithSuite(suite) {
  48. return function run() {
  49. suite.run();
  50. };
  51. },
  52. /**
  53. * Execute before running tests.
  54. *
  55. * @param {string} name
  56. * @param {Function} fn
  57. */
  58. before: function (name, fn) {
  59. return suites[0].beforeAll(name, fn);
  60. },
  61. /**
  62. * Execute after running tests.
  63. *
  64. * @param {string} name
  65. * @param {Function} fn
  66. */
  67. after: function (name, fn) {
  68. return suites[0].afterAll(name, fn);
  69. },
  70. /**
  71. * Execute before each test case.
  72. *
  73. * @param {string} name
  74. * @param {Function} fn
  75. */
  76. beforeEach: function (name, fn) {
  77. return suites[0].beforeEach(name, fn);
  78. },
  79. /**
  80. * Execute after each test case.
  81. *
  82. * @param {string} name
  83. * @param {Function} fn
  84. */
  85. afterEach: function (name, fn) {
  86. return suites[0].afterEach(name, fn);
  87. },
  88. suite: {
  89. /**
  90. * Create an exclusive Suite; convenience function
  91. * See docstring for create() below.
  92. *
  93. * @param {Object} opts
  94. * @returns {Suite}
  95. */
  96. only: function only(opts) {
  97. if (mocha.options.forbidOnly) {
  98. throw createForbiddenExclusivityError(mocha);
  99. }
  100. opts.isOnly = true;
  101. return this.create(opts);
  102. },
  103. /**
  104. * Create a Suite, but skip it; convenience function
  105. * See docstring for create() below.
  106. *
  107. * @param {Object} opts
  108. * @returns {Suite}
  109. */
  110. skip: function skip(opts) {
  111. opts.pending = true;
  112. return this.create(opts);
  113. },
  114. /**
  115. * Creates a suite.
  116. *
  117. * @param {Object} opts Options
  118. * @param {string} opts.title Title of Suite
  119. * @param {Function} [opts.fn] Suite Function (not always applicable)
  120. * @param {boolean} [opts.pending] Is Suite pending?
  121. * @param {string} [opts.file] Filepath where this Suite resides
  122. * @param {boolean} [opts.isOnly] Is Suite exclusive?
  123. * @returns {Suite}
  124. */
  125. create: function create(opts) {
  126. var suite = Suite.create(suites[0], opts.title);
  127. suite.pending = Boolean(opts.pending);
  128. suite.file = opts.file;
  129. suites.unshift(suite);
  130. if (opts.isOnly) {
  131. suite.markOnly();
  132. }
  133. if (
  134. suite.pending &&
  135. mocha.options.forbidPending &&
  136. shouldBeTested(suite)
  137. ) {
  138. throw createUnsupportedError('Pending test forbidden');
  139. }
  140. if (typeof opts.fn === 'function') {
  141. opts.fn.call(suite);
  142. suites.shift();
  143. } else if (typeof opts.fn === 'undefined' && !suite.pending) {
  144. throw createMissingArgumentError(
  145. 'Suite "' +
  146. suite.fullTitle() +
  147. '" was defined but no callback was supplied. ' +
  148. 'Supply a callback or explicitly skip the suite.',
  149. 'callback',
  150. 'function'
  151. );
  152. } else if (!opts.fn && suite.pending) {
  153. suites.shift();
  154. }
  155. return suite;
  156. }
  157. },
  158. test: {
  159. /**
  160. * Exclusive test-case.
  161. *
  162. * @param {Object} mocha
  163. * @param {Function} test
  164. * @returns {*}
  165. */
  166. only: function (mocha, test) {
  167. if (mocha.options.forbidOnly) {
  168. throw createForbiddenExclusivityError(mocha);
  169. }
  170. test.markOnly();
  171. return test;
  172. },
  173. /**
  174. * Pending test case.
  175. *
  176. * @param {string} title
  177. */
  178. skip: function (title) {
  179. context.test(title);
  180. }
  181. }
  182. };
  183. };