SmokeTests.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. const fs = require('fs')
  2. const Path = require('path')
  3. const Settings = require('@overleaf/settings')
  4. const { getCsrfTokenForFactory } = require('./support/Csrf')
  5. const { SmokeTestFailure } = require('./support/Errors')
  6. const {
  7. requestFactory,
  8. assertHasStatusCode,
  9. } = require('./support/requestHelper')
  10. const { processWithTimeout } = require('./support/timeoutHelper')
  11. const STEP_TIMEOUT = Settings.smokeTest.stepTimeout
  12. const PATH_STEPS = Path.join(__dirname, './steps')
  13. const STEPS = fs
  14. .readdirSync(PATH_STEPS)
  15. .sort()
  16. .map(name => {
  17. const step = require(Path.join(PATH_STEPS, name))
  18. step.name = Path.basename(name, '.js')
  19. return step
  20. })
  21. async function runSmokeTests({ isAborted, stats }) {
  22. let lastStep = stats.start
  23. function completeStep(key) {
  24. const step = Date.now()
  25. stats.steps.push({ [key]: step - lastStep })
  26. lastStep = step
  27. }
  28. const request = requestFactory({ timeout: STEP_TIMEOUT })
  29. const getCsrfTokenFor = getCsrfTokenForFactory({ request })
  30. const ctx = {
  31. assertHasStatusCode,
  32. getCsrfTokenFor,
  33. processWithTimeout,
  34. request,
  35. stats,
  36. timeout: STEP_TIMEOUT,
  37. }
  38. const cleanupSteps = []
  39. async function runAndTrack(id, fn) {
  40. let result
  41. try {
  42. result = await fn(ctx)
  43. } catch (e) {
  44. throw new SmokeTestFailure(`${id} failed`, {}, e)
  45. } finally {
  46. completeStep(id)
  47. }
  48. Object.assign(ctx, result)
  49. }
  50. completeStep('init')
  51. let err
  52. try {
  53. for (const step of STEPS) {
  54. if (isAborted()) break
  55. const { name, run, cleanup } = step
  56. if (cleanup) cleanupSteps.unshift({ name, cleanup })
  57. await runAndTrack(`run.${name}`, run)
  58. }
  59. } catch (e) {
  60. err = e
  61. }
  62. const cleanupErrors = []
  63. for (const step of cleanupSteps) {
  64. const { name, cleanup } = step
  65. try {
  66. await runAndTrack(`cleanup.${name}`, cleanup)
  67. } catch (e) {
  68. // keep going with cleanup
  69. cleanupErrors.push(e)
  70. }
  71. }
  72. if (err) throw err
  73. if (cleanupErrors.length) {
  74. if (cleanupErrors.length === 1) throw cleanupErrors[0]
  75. throw new SmokeTestFailure('multiple cleanup steps failed', {
  76. stats,
  77. cleanupErrors,
  78. })
  79. }
  80. }
  81. module.exports = { runSmokeTests, SmokeTestFailure }