bootstrap.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. // ensure every ObjectId has the id string as a property for correct comparisons
  19. require('mongodb-legacy').ObjectId.cacheHexString = true
  20. /*
  21. * Global stubs
  22. */
  23. const globalStubsSandbox = sinon.createSandbox()
  24. const globalStubs = {
  25. logger: {
  26. debug: globalStubsSandbox.stub(),
  27. info: globalStubsSandbox.stub(),
  28. log: globalStubsSandbox.stub(),
  29. warn: globalStubsSandbox.stub(),
  30. err: globalStubsSandbox.stub(),
  31. error: globalStubsSandbox.stub(),
  32. fatal: globalStubsSandbox.stub(),
  33. },
  34. }
  35. /*
  36. * Sandboxed module configuration
  37. */
  38. const SandboxedModule = require('sandboxed-module')
  39. SandboxedModule.configure({
  40. ignoreMissing: true,
  41. requires: getSandboxedModuleRequires(),
  42. globals: {
  43. AbortController,
  44. AbortSignal,
  45. Buffer,
  46. Promise,
  47. console,
  48. process,
  49. URL,
  50. TextEncoder,
  51. TextDecoder,
  52. },
  53. sourceTransformers: {
  54. removeNodePrefix: function (source) {
  55. return source.replace(/require\(['"]node:/g, "require('")
  56. },
  57. },
  58. })
  59. function getSandboxedModuleRequires() {
  60. const requires = {
  61. '@overleaf/logger': globalStubs.logger,
  62. }
  63. const internalModules = [
  64. '../../app/src/Features/Errors/Errors',
  65. '../../app/src/Features/Helpers/Mongo',
  66. ]
  67. const externalLibs = [
  68. 'async',
  69. 'bull',
  70. 'json2csv',
  71. 'lodash',
  72. 'marked',
  73. 'moment',
  74. '@overleaf/o-error',
  75. 'sanitize-html',
  76. 'sshpk',
  77. 'xml2js',
  78. 'mongodb',
  79. 'mongodb-legacy',
  80. ]
  81. for (const modulePath of internalModules) {
  82. requires[Path.resolve(__dirname, modulePath)] = require(modulePath)
  83. }
  84. for (const lib of externalLibs) {
  85. requires[lib] = require(lib)
  86. }
  87. return requires
  88. }
  89. /*
  90. * Mocha hooks
  91. */
  92. // sandboxed-module somehow registers every fake module it creates in this
  93. // module's children array, which uses quite a big amount of memory. We'll take
  94. // a copy of the module children array and restore it after each test so that
  95. // the garbage collector has a chance to reclaim the fake modules.
  96. let initialModuleChildren
  97. exports.mochaHooks = {
  98. beforeAll() {
  99. // Record initial module children
  100. initialModuleChildren = module.children.slice()
  101. },
  102. beforeEach() {
  103. // Install logger stub
  104. this.logger = globalStubs.logger
  105. },
  106. afterEach() {
  107. // Delete leaking sandboxed modules
  108. module.children = initialModuleChildren.slice()
  109. // Reset global stubs
  110. globalStubsSandbox.reset()
  111. // Restore other stubs
  112. sinon.restore()
  113. },
  114. }