graceful-shutdown.spec.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { ensureUserExists, login } from './helpers/login'
  2. import {
  3. isExcludedBySharding,
  4. STARTUP_TIMEOUT,
  5. startWith,
  6. } from './helpers/config'
  7. import { dockerCompose, getRedisKeys } from './helpers/hostAdminClient'
  8. import { createProjectAndOpenInNewEditor } from './helpers/project'
  9. import { prepareWaitForNextCompileSlot } from './helpers/compile'
  10. const USER = 'user@example.com'
  11. const PROJECT_NAME = 'Old Project'
  12. function bringServerProBackUp() {
  13. cy.log('bring server pro back up')
  14. cy.then({ timeout: STARTUP_TIMEOUT }, async () => {
  15. await dockerCompose('up', '--detach', '--wait', 'sharelatex')
  16. })
  17. }
  18. describe('GracefulShutdown', function () {
  19. if (isExcludedBySharding('PRO_CUSTOM_1')) return
  20. startWith({
  21. pro: true,
  22. withDataDir: true,
  23. resetData: true,
  24. })
  25. ensureUserExists({ email: USER })
  26. let projectId: string
  27. it('should display banner and flush changes out of redis', function () {
  28. bringServerProBackUp()
  29. login(USER)
  30. const { recompile, waitForCompile } = prepareWaitForNextCompileSlot()
  31. waitForCompile(() => {
  32. createProjectAndOpenInNewEditor(PROJECT_NAME).then(id => {
  33. projectId = id
  34. })
  35. })
  36. cy.log('add additional content')
  37. cy.findByRole('region', { name: 'Editor' }).within(() => {
  38. cy.findByText('\\maketitle').parent().click()
  39. cy.findByText('\\maketitle').parent().type(`\n\\section{{}New Section}`)
  40. })
  41. recompile()
  42. cy.log(
  43. 'check flush from frontend to backend: should include new section in PDF'
  44. )
  45. cy.findByRole('region', { name: 'PDF preview' }).should(
  46. 'contain.text',
  47. 'New Section'
  48. )
  49. cy.log('should have unflushed content in redis before shutdown')
  50. cy.then(async () => {
  51. const keys = await getRedisKeys()
  52. expect(keys).to.contain(`DocsIn:${projectId}`)
  53. expect(keys).to.contain(`ProjectHistory:Ops:{${projectId}}`)
  54. })
  55. cy.log('trigger graceful shutdown')
  56. let pendingShutdown: Promise<any>
  57. cy.then(() => {
  58. pendingShutdown = dockerCompose('stop', '--timeout=60', 'sharelatex')
  59. })
  60. cy.log('wait for banner')
  61. cy.findByRole('dialog').findByText(/performing maintenance/)
  62. cy.log('wait for page reload')
  63. cy.findByRole('heading', { name: 'Maintenance' })
  64. cy.findByText(/is currently down for maintenance/)
  65. cy.log('wait for shutdown to complete')
  66. cy.then({ timeout: 60 * 1000 }, async () => {
  67. await pendingShutdown
  68. })
  69. cy.log('should not have any unflushed content in redis after shutdown')
  70. cy.then(async () => {
  71. const keys = await getRedisKeys()
  72. expect(keys).to.not.contain(`DocsIn:${projectId}`)
  73. expect(keys).to.not.contain(`ProjectHistory:Ops:{${projectId}}`)
  74. })
  75. bringServerProBackUp()
  76. cy.then(() => {
  77. cy.visit(`/project/${projectId}?trick-cypress-into-page-reload=true`)
  78. })
  79. cy.log('check loading doc from mongo')
  80. cy.findByRole('region', { name: 'Editor' }).findByText('New Section')
  81. cy.log('check PDF')
  82. cy.findByRole('region', { name: 'PDF preview' }).should(
  83. 'contain.text',
  84. 'New Section'
  85. )
  86. cy.log('check history')
  87. cy.findByRole('navigation', {
  88. name: 'Project actions',
  89. })
  90. .findByRole('button', { name: 'History' })
  91. .click()
  92. cy.findByText(/\\section\{New Section}/)
  93. })
  94. })