bootstrap.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. const Path = require('path')
  2. const chai = require('chai')
  3. const sinon = require('sinon')
  4. /*
  5. * Chai configuration
  6. */
  7. // add chai.should()
  8. chai.should()
  9. // Load sinon-chai assertions so expect(stubFn).to.have.been.calledWith('abc')
  10. // has a nicer failure messages
  11. chai.use(require('sinon-chai'))
  12. // Load promise support for chai
  13. chai.use(require('chai-as-promised'))
  14. // Do not truncate assertion errors
  15. chai.config.truncateThreshold = 0
  16. // add support for mongoose in sinon
  17. require('sinon-mongoose')
  18. /*
  19. * Global stubs
  20. */
  21. const globalStubsSandbox = sinon.createSandbox()
  22. const globalStubs = {
  23. logger: {
  24. debug: globalStubsSandbox.stub(),
  25. info: globalStubsSandbox.stub(),
  26. log: globalStubsSandbox.stub(),
  27. warn: globalStubsSandbox.stub(),
  28. err: globalStubsSandbox.stub(),
  29. error: globalStubsSandbox.stub(),
  30. fatal: globalStubsSandbox.stub()
  31. }
  32. }
  33. /*
  34. * Sandboxed module configuration
  35. */
  36. const SandboxedModule = require('sandboxed-module')
  37. SandboxedModule.configure({
  38. requires: getSandboxedModuleRequires(),
  39. globals: { Buffer, Promise, console, process },
  40. sourceTransformers: {
  41. coffee(source) {
  42. if (this.filename.endsWith('.coffee')) {
  43. // Coffeescript mucks with Error.prepareStackTrace, which, in turn,
  44. // conflicts with OError. This is a hacky way to prevent Coffeescript
  45. // from interfering.
  46. //
  47. // See https://github.com/jashkenas/coffeescript/blob/07f644c39223e016aceedd2cd71b5941579b5659/src/coffeescript.coffee#L368
  48. const originalPrepareStackTrace = Error.prepareStackTrace
  49. const compiled = require('coffeescript').compile(source)
  50. Error.prepareStackTrace = originalPrepareStackTrace
  51. return compiled
  52. }
  53. return source
  54. }
  55. }
  56. })
  57. function getSandboxedModuleRequires() {
  58. const requires = {
  59. 'logger-sharelatex': globalStubs.logger
  60. }
  61. const internalModules = [
  62. '../../app/src/util/promises',
  63. '../../app/src/Features/Errors/Errors',
  64. '../../app/src/Features/Helpers/Mongo'
  65. ]
  66. const externalLibs = [
  67. 'async',
  68. 'json2csv',
  69. 'lodash',
  70. 'marked',
  71. 'moment',
  72. '@overleaf/o-error',
  73. 'sanitize-html',
  74. 'sshpk',
  75. 'underscore',
  76. 'xml2js'
  77. ]
  78. for (const modulePath of internalModules) {
  79. requires[Path.resolve(__dirname, modulePath)] = require(modulePath)
  80. }
  81. for (const lib of externalLibs) {
  82. requires[lib] = require(lib)
  83. }
  84. return requires
  85. }
  86. /*
  87. * Mocha hooks
  88. */
  89. // sandboxed-module somehow registers every fake module it creates in this
  90. // module's children array, which uses quite a big amount of memory. We'll take
  91. // a copy of the module children array and restore it after each test so that
  92. // the garbage collector has a chance to reclaim the fake modules.
  93. let initialModuleChildren
  94. exports.mochaHooks = {
  95. beforeAll() {
  96. // Record initial module children
  97. initialModuleChildren = module.children.slice()
  98. },
  99. beforeEach() {
  100. // Install logger stub
  101. this.logger = globalStubs.logger
  102. },
  103. afterEach() {
  104. // Delete leaking sandboxed modules
  105. module.children = initialModuleChildren.slice()
  106. // Reset global stubs
  107. globalStubsSandbox.reset()
  108. // Restore other stubs
  109. sinon.restore()
  110. }
  111. }