common.js 4.6 KB

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