UpdatingDocsTests.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /* eslint-disable
  2. no-unused-vars,
  3. */
  4. // TODO: This file was created by bulk-decaffeinate.
  5. // Fix any style issues and re-enable lint.
  6. /*
  7. * decaffeinate suggestions:
  8. * DS102: Remove unnecessary code created because of implicit returns
  9. * DS207: Consider shorter variations of null checks
  10. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  11. */
  12. const sinon = require('sinon')
  13. const { ObjectId } = require('mongodb')
  14. const DocstoreApp = require('./helpers/DocstoreApp')
  15. const DocstoreClient = require('./helpers/DocstoreClient')
  16. describe('Applying updates to a doc', function () {
  17. beforeEach(function (done) {
  18. this.project_id = ObjectId()
  19. this.doc_id = ObjectId()
  20. this.originalLines = ['original', 'lines']
  21. this.newLines = ['new', 'lines']
  22. this.originalRanges = {
  23. changes: [
  24. {
  25. id: ObjectId().toString(),
  26. op: { i: 'foo', p: 3 },
  27. meta: {
  28. user_id: ObjectId().toString(),
  29. ts: new Date().toString(),
  30. },
  31. },
  32. ],
  33. }
  34. this.newRanges = {
  35. changes: [
  36. {
  37. id: ObjectId().toString(),
  38. op: { i: 'bar', p: 6 },
  39. meta: {
  40. user_id: ObjectId().toString(),
  41. ts: new Date().toString(),
  42. },
  43. },
  44. ],
  45. }
  46. this.version = 42
  47. return DocstoreApp.ensureRunning(() => {
  48. return DocstoreClient.createDoc(
  49. this.project_id,
  50. this.doc_id,
  51. this.originalLines,
  52. this.version,
  53. this.originalRanges,
  54. error => {
  55. if (error != null) {
  56. throw error
  57. }
  58. return done()
  59. }
  60. )
  61. })
  62. })
  63. describe('when nothing has been updated', function () {
  64. beforeEach(function (done) {
  65. return DocstoreClient.updateDoc(
  66. this.project_id,
  67. this.doc_id,
  68. this.originalLines,
  69. this.version,
  70. this.originalRanges,
  71. (error, res, body) => {
  72. if (error) return done(error)
  73. this.body = body
  74. return done()
  75. }
  76. )
  77. })
  78. it('should return modified = false', function () {
  79. return this.body.modified.should.equal(false)
  80. })
  81. return it('should not update the doc in the API', function (done) {
  82. return DocstoreClient.getDoc(
  83. this.project_id,
  84. this.doc_id,
  85. {},
  86. (error, res, doc) => {
  87. if (error) return done(error)
  88. doc.lines.should.deep.equal(this.originalLines)
  89. doc.version.should.equal(this.version)
  90. doc.ranges.should.deep.equal(this.originalRanges)
  91. return done()
  92. }
  93. )
  94. })
  95. })
  96. describe('when the lines have changed', function () {
  97. beforeEach(function (done) {
  98. return DocstoreClient.updateDoc(
  99. this.project_id,
  100. this.doc_id,
  101. this.newLines,
  102. this.version,
  103. this.originalRanges,
  104. (error, res, body) => {
  105. if (error) return done(error)
  106. this.body = body
  107. return done()
  108. }
  109. )
  110. })
  111. it('should return modified = true', function () {
  112. return this.body.modified.should.equal(true)
  113. })
  114. it('should return the rev', function () {
  115. return this.body.rev.should.equal(2)
  116. })
  117. return it('should update the doc in the API', function (done) {
  118. return DocstoreClient.getDoc(
  119. this.project_id,
  120. this.doc_id,
  121. {},
  122. (error, res, doc) => {
  123. if (error) return done(error)
  124. doc.lines.should.deep.equal(this.newLines)
  125. doc.version.should.equal(this.version)
  126. doc.ranges.should.deep.equal(this.originalRanges)
  127. return done()
  128. }
  129. )
  130. })
  131. })
  132. describe('when the version has changed', function () {
  133. beforeEach(function (done) {
  134. return DocstoreClient.updateDoc(
  135. this.project_id,
  136. this.doc_id,
  137. this.originalLines,
  138. this.version + 1,
  139. this.originalRanges,
  140. (error, res, body) => {
  141. if (error) return done(error)
  142. this.body = body
  143. return done()
  144. }
  145. )
  146. })
  147. it('should return modified = true', function () {
  148. return this.body.modified.should.equal(true)
  149. })
  150. it('should return the rev', function () {
  151. return this.body.rev.should.equal(1)
  152. })
  153. return it('should update the doc in the API', function (done) {
  154. return DocstoreClient.getDoc(
  155. this.project_id,
  156. this.doc_id,
  157. {},
  158. (error, res, doc) => {
  159. if (error) return done(error)
  160. doc.lines.should.deep.equal(this.originalLines)
  161. doc.version.should.equal(this.version + 1)
  162. doc.ranges.should.deep.equal(this.originalRanges)
  163. return done()
  164. }
  165. )
  166. })
  167. })
  168. describe('when the ranges have changed', function () {
  169. beforeEach(function (done) {
  170. return DocstoreClient.updateDoc(
  171. this.project_id,
  172. this.doc_id,
  173. this.originalLines,
  174. this.version,
  175. this.newRanges,
  176. (error, res, body) => {
  177. if (error) return done(error)
  178. this.body = body
  179. return done()
  180. }
  181. )
  182. })
  183. it('should return modified = true', function () {
  184. return this.body.modified.should.equal(true)
  185. })
  186. it('should return the rev', function () {
  187. return this.body.rev.should.equal(2)
  188. })
  189. return it('should update the doc in the API', function (done) {
  190. return DocstoreClient.getDoc(
  191. this.project_id,
  192. this.doc_id,
  193. {},
  194. (error, res, doc) => {
  195. if (error) return done(error)
  196. doc.lines.should.deep.equal(this.originalLines)
  197. doc.version.should.equal(this.version)
  198. doc.ranges.should.deep.equal(this.newRanges)
  199. return done()
  200. }
  201. )
  202. })
  203. })
  204. describe('when the doc does not exist', function () {
  205. beforeEach(function (done) {
  206. this.missing_doc_id = ObjectId()
  207. return DocstoreClient.updateDoc(
  208. this.project_id,
  209. this.missing_doc_id,
  210. this.originalLines,
  211. 0,
  212. this.originalRanges,
  213. (error, res, body) => {
  214. if (error) return done(error)
  215. this.res = res
  216. this.body = body
  217. return done()
  218. }
  219. )
  220. })
  221. it('should create the doc', function () {
  222. return this.body.rev.should.equal(1)
  223. })
  224. return it('should be retreivable', function (done) {
  225. return DocstoreClient.getDoc(
  226. this.project_id,
  227. this.missing_doc_id,
  228. {},
  229. (error, res, doc) => {
  230. if (error) return done(error)
  231. doc.lines.should.deep.equal(this.originalLines)
  232. doc.version.should.equal(0)
  233. doc.ranges.should.deep.equal(this.originalRanges)
  234. return done()
  235. }
  236. )
  237. })
  238. })
  239. describe('when malformed doc lines are provided', function () {
  240. describe('when the lines are not an array', function () {
  241. beforeEach(function (done) {
  242. return DocstoreClient.updateDoc(
  243. this.project_id,
  244. this.doc_id,
  245. { foo: 'bar' },
  246. this.version,
  247. this.originalRanges,
  248. (error, res, body) => {
  249. if (error) return done(error)
  250. this.res = res
  251. this.body = body
  252. return done()
  253. }
  254. )
  255. })
  256. it('should return 400', function () {
  257. return this.res.statusCode.should.equal(400)
  258. })
  259. return it('should not update the doc in the API', function (done) {
  260. return DocstoreClient.getDoc(
  261. this.project_id,
  262. this.doc_id,
  263. {},
  264. (error, res, doc) => {
  265. if (error) return done(error)
  266. doc.lines.should.deep.equal(this.originalLines)
  267. return done()
  268. }
  269. )
  270. })
  271. })
  272. return describe('when the lines are not present', function () {
  273. beforeEach(function (done) {
  274. return DocstoreClient.updateDoc(
  275. this.project_id,
  276. this.doc_id,
  277. null,
  278. this.version,
  279. this.originalRanges,
  280. (error, res, body) => {
  281. if (error) return done(error)
  282. this.res = res
  283. this.body = body
  284. return done()
  285. }
  286. )
  287. })
  288. it('should return 400', function () {
  289. return this.res.statusCode.should.equal(400)
  290. })
  291. return it('should not update the doc in the API', function (done) {
  292. return DocstoreClient.getDoc(
  293. this.project_id,
  294. this.doc_id,
  295. {},
  296. (error, res, doc) => {
  297. if (error) return done(error)
  298. doc.lines.should.deep.equal(this.originalLines)
  299. return done()
  300. }
  301. )
  302. })
  303. })
  304. })
  305. describe('when no version is provided', function () {
  306. beforeEach(function (done) {
  307. return DocstoreClient.updateDoc(
  308. this.project_id,
  309. this.doc_id,
  310. this.originalLines,
  311. null,
  312. this.originalRanges,
  313. (error, res, body) => {
  314. if (error) return done(error)
  315. this.res = res
  316. this.body = body
  317. return done()
  318. }
  319. )
  320. })
  321. it('should return 400', function () {
  322. return this.res.statusCode.should.equal(400)
  323. })
  324. return it('should not update the doc in the API', function (done) {
  325. return DocstoreClient.getDoc(
  326. this.project_id,
  327. this.doc_id,
  328. {},
  329. (error, res, doc) => {
  330. if (error) return done(error)
  331. doc.lines.should.deep.equal(this.originalLines)
  332. doc.version.should.equal(this.version)
  333. return done()
  334. }
  335. )
  336. })
  337. })
  338. describe('when the content is large', function () {
  339. beforeEach(function (done) {
  340. const line = new Array(1025).join('x') // 1kb
  341. this.largeLines = Array.apply(null, Array(1024)).map(() => line) // 1mb
  342. return DocstoreClient.updateDoc(
  343. this.project_id,
  344. this.doc_id,
  345. this.largeLines,
  346. this.version,
  347. this.originalRanges,
  348. (error, res, body) => {
  349. if (error) return done(error)
  350. this.body = body
  351. return done()
  352. }
  353. )
  354. })
  355. it('should return modified = true', function () {
  356. return this.body.modified.should.equal(true)
  357. })
  358. return it('should update the doc in the API', function (done) {
  359. return DocstoreClient.getDoc(
  360. this.project_id,
  361. this.doc_id,
  362. {},
  363. (error, res, doc) => {
  364. if (error) return done(error)
  365. doc.lines.should.deep.equal(this.largeLines)
  366. return done()
  367. }
  368. )
  369. })
  370. })
  371. describe('when there is a large json payload', function () {
  372. beforeEach(function (done) {
  373. const line = new Array(1025).join('x') // 1kb
  374. this.largeLines = Array.apply(null, Array(1024)).map(() => line) // 1kb
  375. this.originalRanges.padding = Array.apply(null, Array(2049)).map(
  376. () => line
  377. ) // 2mb + 1kb
  378. return DocstoreClient.updateDoc(
  379. this.project_id,
  380. this.doc_id,
  381. this.largeLines,
  382. this.version,
  383. this.originalRanges,
  384. (error, res, body) => {
  385. if (error) return done(error)
  386. this.res = res
  387. this.body = body
  388. return done()
  389. }
  390. )
  391. })
  392. it('should return modified = true', function () {
  393. return this.body.modified.should.equal(true)
  394. })
  395. return it('should update the doc in the API', function (done) {
  396. return DocstoreClient.getDoc(
  397. this.project_id,
  398. this.doc_id,
  399. {},
  400. (error, res, doc) => {
  401. if (error) return done(error)
  402. doc.lines.should.deep.equal(this.largeLines)
  403. return done()
  404. }
  405. )
  406. })
  407. })
  408. describe('when the document body is too large', function () {
  409. beforeEach(function (done) {
  410. const line = new Array(1025).join('x') // 1kb
  411. this.largeLines = Array.apply(null, Array(2049)).map(() => line) // 2mb + 1kb
  412. return DocstoreClient.updateDoc(
  413. this.project_id,
  414. this.doc_id,
  415. this.largeLines,
  416. this.version,
  417. this.originalRanges,
  418. (error, res, body) => {
  419. if (error) return done(error)
  420. this.res = res
  421. this.body = body
  422. return done()
  423. }
  424. )
  425. })
  426. it('should return 413', function () {
  427. return this.res.statusCode.should.equal(413)
  428. })
  429. it('should report body too large', function () {
  430. return this.res.body.should.equal('document body too large')
  431. })
  432. return it('should not update the doc in the API', function (done) {
  433. return DocstoreClient.getDoc(
  434. this.project_id,
  435. this.doc_id,
  436. {},
  437. (error, res, doc) => {
  438. if (error) return done(error)
  439. doc.lines.should.deep.equal(this.originalLines)
  440. return done()
  441. }
  442. )
  443. })
  444. })
  445. return describe('when the json payload is too large', function () {
  446. beforeEach(function (done) {
  447. const line = new Array(1025).join('x') // 1kb
  448. this.largeLines = Array.apply(null, Array(1024)).map(() => line) // 1kb
  449. this.originalRanges.padding = Array.apply(null, Array(6144)).map(
  450. () => line
  451. ) // 6mb
  452. return DocstoreClient.updateDoc(
  453. this.project_id,
  454. this.doc_id,
  455. this.largeLines,
  456. this.version,
  457. this.originalRanges,
  458. (error, res, body) => {
  459. if (error) return done(error)
  460. this.res = res
  461. this.body = body
  462. return done()
  463. }
  464. )
  465. })
  466. return it('should not update the doc in the API', function (done) {
  467. return DocstoreClient.getDoc(
  468. this.project_id,
  469. this.doc_id,
  470. {},
  471. (error, res, doc) => {
  472. if (error) return done(error)
  473. doc.lines.should.deep.equal(this.originalLines)
  474. return done()
  475. }
  476. )
  477. })
  478. })
  479. })