SizeCheckTests.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. const { expect } = require('chai')
  2. const { setTimeout } = require('node:timers/promises')
  3. const Settings = require('@overleaf/settings')
  4. const MockWebApi = require('./helpers/MockWebApi')
  5. const DocUpdaterClient = require('./helpers/DocUpdaterClient')
  6. const DocUpdaterApp = require('./helpers/DocUpdaterApp')
  7. const { RequestFailedError } = require('@overleaf/fetch-utils')
  8. describe('SizeChecks', function () {
  9. before(async function () {
  10. await DocUpdaterApp.ensureRunning()
  11. })
  12. beforeEach(function () {
  13. this.version = 0
  14. this.update = {
  15. doc: this.doc_id,
  16. op: [
  17. {
  18. i: 'insert some more lines that will bring it above the limit\n',
  19. p: 42,
  20. },
  21. ],
  22. v: this.version,
  23. }
  24. this.project_id = DocUpdaterClient.randomId()
  25. this.doc_id = DocUpdaterClient.randomId()
  26. })
  27. describe('when a doc is above the doc size limit already', function () {
  28. beforeEach(function () {
  29. this.lines = ['x'.repeat(Settings.max_doc_length)] // including the extra newline, this will be over the limit
  30. MockWebApi.insertDoc(this.project_id, this.doc_id, {
  31. lines: this.lines,
  32. v: this.version,
  33. })
  34. })
  35. it('should error when fetching the doc', async function () {
  36. await expect(DocUpdaterClient.getDoc(this.project_id, this.doc_id))
  37. .to.be.rejectedWith(RequestFailedError)
  38. .and.eventually.have.nested.property('response.status', 500)
  39. })
  40. describe('when trying to update', function () {
  41. beforeEach(async function () {
  42. const update = {
  43. doc: this.doc_id,
  44. op: this.update.op,
  45. v: this.version,
  46. }
  47. await DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update)
  48. await setTimeout(200)
  49. })
  50. it('should still error when fetching the doc', async function () {
  51. await expect(DocUpdaterClient.getDoc(this.project_id, this.doc_id))
  52. .to.be.rejectedWith(RequestFailedError)
  53. .and.eventually.have.nested.property('response.status', 500)
  54. })
  55. })
  56. })
  57. describe('when the stringified JSON is above the doc size limit but the doc character count is not', function () {
  58. beforeEach(function () {
  59. let charsRemaining = Settings.max_doc_length
  60. this.lines = []
  61. // Take the maximum allowed doc length and split it into N lines of 63 characters + a newline.
  62. // The character count will be exactly max_doc_length
  63. // The JSON stringified size will exceed max_doc_length, due to the JSON formatting of the array.
  64. // This document should be allowed, because we use the character count as the limit, not the JSON size.
  65. while (charsRemaining > 0) {
  66. const charstoAdd = Math.min(charsRemaining - 1, 63) // allow for additional newline
  67. this.lines.push('x'.repeat(charstoAdd))
  68. charsRemaining -= charstoAdd + 1
  69. }
  70. MockWebApi.insertDoc(this.project_id, this.doc_id, {
  71. lines: this.lines,
  72. v: this.version,
  73. })
  74. })
  75. it('should be able to fetch the doc', async function () {
  76. const doc = await DocUpdaterClient.getDoc(this.project_id, this.doc_id)
  77. expect(doc.lines).to.deep.equal(this.lines)
  78. })
  79. describe('when trying to update', function () {
  80. beforeEach(async function () {
  81. const update = {
  82. doc: this.doc_id,
  83. op: this.update.op,
  84. v: this.version,
  85. }
  86. await DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update)
  87. await setTimeout(200)
  88. })
  89. it('should not update the doc', async function () {
  90. const doc = await DocUpdaterClient.getDoc(this.project_id, this.doc_id)
  91. expect(doc.lines).to.deep.equal(this.lines)
  92. })
  93. })
  94. })
  95. describe('when a doc is just below the doc size limit', function () {
  96. beforeEach(function () {
  97. this.lines = ['x'.repeat(Settings.max_doc_length - 1)] // character count is exactly max_doc_length after including the newline
  98. MockWebApi.insertDoc(this.project_id, this.doc_id, {
  99. lines: this.lines,
  100. v: this.version,
  101. })
  102. })
  103. it('should be able to fetch the doc', async function () {
  104. const doc = await DocUpdaterClient.getDoc(this.project_id, this.doc_id)
  105. expect(doc.lines).to.deep.equal(this.lines)
  106. })
  107. describe('when trying to update', function () {
  108. beforeEach(async function () {
  109. const update = {
  110. doc: this.doc_id,
  111. op: this.update.op,
  112. v: this.version,
  113. }
  114. await DocUpdaterClient.sendUpdate(this.project_id, this.doc_id, update)
  115. await setTimeout(200)
  116. })
  117. it('should not update the doc', async function () {
  118. const doc = await DocUpdaterClient.getDoc(this.project_id, this.doc_id)
  119. expect(doc.lines).to.deep.equal(this.lines)
  120. })
  121. })
  122. })
  123. })