expand-suite.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /**
  2. * Module dependencies
  3. */
  4. var _ = require('@sailshq/lodash');
  5. /**
  6. * Expand the provided test suite with more tests automatically.
  7. *
  8. * @param {Array} testSuite
  9. * @return {Array}
  10. */
  11. module.exports = function expandSuite ( testSuite ) {
  12. // For all `example: undefined` tests, also test `example: '==='`
  13. var starTests = [];
  14. _.each(testSuite, function (test){
  15. if (_.isUndefined(test.example)) {
  16. var newTest = {
  17. example: '===',
  18. actual: test.actual
  19. };
  20. if (test.hasOwnProperty('result')) {
  21. newTest.result = test.result;
  22. }
  23. if (test.hasOwnProperty('strictEq')) {
  24. newTest.strictEq = _.cloneDeep(test.strictEq);
  25. }
  26. if (test.hasOwnProperty('isNew')) {
  27. newTest.isNew = _.cloneDeep(test.isNew);
  28. }
  29. starTests.push(newTest);
  30. }
  31. });
  32. testSuite = testSuite.concat(starTests);
  33. // Lodash 3.0 deprecated prototypal cloning of things like Errors
  34. // (so we shim a quick version for our purposes)
  35. var customCloneDeep = function (val){
  36. return _.cloneDeep(val, function(_val) {
  37. // Don't worry about cloning most things that _.cloneDeep would
  38. // normally reject; instead just pass them straight through.
  39. if (_.isError(_val)) {
  40. return _val;
  41. }
  42. else if (_.isFunction(_val)) {
  43. return _val;
  44. }
  45. else if (_.isObject(_val) && _val instanceof Buffer) {
  46. return _val;
  47. }
  48. else if (_.isObject(_val) && _val instanceof require('stream').Readable) {
  49. return _val;
  50. }
  51. // Otherwise allow vanilla _.cloneDeep() behavior:
  52. else { return undefined; }
  53. });
  54. };
  55. // Inject an extra test for each existing test in order to ensure correct
  56. // behavior when recursive examples/values are provided
  57. var recursiveTests = [];
  58. _.each(testSuite, function (test){
  59. // ...but skip:
  60. // • tests with example: `undefined`
  61. // • tests that expect errors
  62. // • tests that expect a result===`undefined`
  63. // • tests that verify `strictEq` or `isNew`
  64. // (nested behavior is different in these cases^)
  65. if (!test.error && !_.isUndefined(test.result) && !test.hasOwnProperty('strictEq') && !test.hasOwnProperty('isNew')) {
  66. // test one level of additional array nesting
  67. if (!_.isUndefined(test.actual)) {
  68. recursiveTests.push({
  69. example: [ customCloneDeep(test.example) ],
  70. actual: [ customCloneDeep(test.actual) ],
  71. result: [ customCloneDeep(test.result) ],
  72. _meta: '+1 array depth'
  73. });
  74. }
  75. // test one level of additional dictionary nesting
  76. recursiveTests.push({
  77. example: { xtra: customCloneDeep(test.example) },
  78. actual: { xtra: customCloneDeep(test.actual) },
  79. result: { xtra: customCloneDeep(test.result) },
  80. _meta: '+1 dictionary depth'
  81. });
  82. // test one level of additional dictionary nesting AND 1 level of additional array nesting
  83. recursiveTests.push({
  84. example: [ { xtra: customCloneDeep(test.example) } ],
  85. actual: [ { xtra: customCloneDeep(test.actual) } ],
  86. result: [ { xtra: customCloneDeep(test.result) } ],
  87. _meta: '+1 array depth, +1 dictionary depth'
  88. });
  89. // test two levels of additional dictionary nesting
  90. recursiveTests.push({
  91. example: { xtra: { xtra2: customCloneDeep(test.example) } },
  92. actual: { xtra: { xtra2: customCloneDeep(test.actual) } },
  93. result: { xtra:{ xtra2: customCloneDeep(test.result) } },
  94. _meta: '+2 dictionary depth'
  95. });
  96. if (!_.isUndefined(test.actual)) {
  97. // test two levels of additional array nesting
  98. recursiveTests.push({
  99. example: [ [ customCloneDeep(test.example) ] ],
  100. actual: [ [ customCloneDeep(test.actual) ] ],
  101. result: [ [ customCloneDeep(test.result) ] ],
  102. _meta: '+2 array depth'
  103. });
  104. }
  105. // test two levels of additional dictionary nesting AND 1 level of array nesting
  106. recursiveTests.push({
  107. example: [ { xtra: { xtra2: customCloneDeep(test.example) } } ],
  108. actual: [ { xtra: { xtra2: customCloneDeep(test.actual) } } ],
  109. result: [ { xtra:{ xtra2: customCloneDeep(test.result) } } ],
  110. _meta: '+1 array depth, +2 dictionary depth'
  111. });
  112. // test two levels of additional dictionary nesting and one level of array nesting, then WITHIN that, 1 level of array nesting
  113. if (!_.isUndefined(test.actual)) {
  114. recursiveTests.push({
  115. example: [ { xtra: { xtra2: [customCloneDeep(test.example)] } } ],
  116. actual: [ { xtra: { xtra2: [customCloneDeep(test.actual)] } } ],
  117. result: [ { xtra:{ xtra2: [customCloneDeep(test.result)] } } ],
  118. _meta: '+1 array depth, +2 dictionary depth, +1 nested array depth'
  119. });
  120. }
  121. if (!_.isUndefined(test.actual)) {
  122. // test two levels of additional dictionary nesting and one level of array nesting, then WITHIN that, 2 levels of array nesting
  123. recursiveTests.push({
  124. example: [ { xtra: { xtra2: [[customCloneDeep(test.example)]] } } ],
  125. actual: [ { xtra: { xtra2: [[customCloneDeep(test.actual)]] } } ],
  126. result: [ { xtra:{ xtra2: [[customCloneDeep(test.result)]] } } ],
  127. _meta: '+1 array depth, +2 dictionary depth, +2 nested array depth'
  128. });
  129. }
  130. }
  131. });
  132. testSuite = testSuite.concat(recursiveTests);
  133. return testSuite;
  134. };