ReadingASnapshotTests.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. import { expect } from 'chai'
  2. import { ObjectId } from 'mongodb'
  3. import nock from 'nock'
  4. import * as ProjectHistoryClient from './helpers/ProjectHistoryClient.js'
  5. import * as ProjectHistoryApp from './helpers/ProjectHistoryApp.js'
  6. const MockHistoryStore = () => nock('http://localhost:3100')
  7. const MockWeb = () => nock('http://localhost:3000')
  8. const fixture = path => new URL(`../fixtures/${path}`, import.meta.url)
  9. describe('ReadSnapshot', function () {
  10. beforeEach(function (done) {
  11. ProjectHistoryApp.ensureRunning(error => {
  12. if (error) {
  13. throw error
  14. }
  15. this.historyId = ObjectId().toString()
  16. MockHistoryStore().post('/api/projects').reply(200, {
  17. projectId: this.historyId,
  18. })
  19. ProjectHistoryClient.initializeProject(
  20. this.historyId,
  21. (error, v1Project) => {
  22. if (error) {
  23. throw error
  24. }
  25. this.projectId = ObjectId().toString()
  26. MockWeb()
  27. .get(`/project/${this.projectId}/details`)
  28. .reply(200, {
  29. name: 'Test Project',
  30. overleaf: { history: { id: v1Project.id } },
  31. })
  32. done()
  33. }
  34. )
  35. })
  36. })
  37. afterEach(function () {
  38. nock.cleanAll()
  39. })
  40. describe('of a text file', function () {
  41. it('should return the snapshot of a doc at the given version', function (done) {
  42. MockHistoryStore()
  43. .get(`/api/projects/${this.historyId}/versions/5/history`)
  44. .replyWithFile(200, fixture('chunks/4-6.json'))
  45. MockHistoryStore()
  46. .get(
  47. `/api/projects/${this.historyId}/blobs/c6654ea913979e13e22022653d284444f284a172`
  48. )
  49. .replyWithFile(
  50. 200,
  51. fixture('blobs/c6654ea913979e13e22022653d284444f284a172')
  52. )
  53. ProjectHistoryClient.getSnapshot(
  54. this.projectId,
  55. 'foo.tex',
  56. 5,
  57. (error, body) => {
  58. if (error) {
  59. throw error
  60. }
  61. expect(body).to.deep.equal(
  62. `\
  63. Hello world
  64. One two three
  65. Four five six
  66. Seven eight nine\
  67. `.replace(/^\t/g, '')
  68. )
  69. done()
  70. }
  71. )
  72. })
  73. it('should return the snapshot of a doc at a different version', function (done) {
  74. MockHistoryStore()
  75. .get(`/api/projects/${this.historyId}/versions/4/history`)
  76. .replyWithFile(200, fixture('chunks/4-6.json'))
  77. MockHistoryStore()
  78. .get(
  79. `/api/projects/${this.historyId}/blobs/c6654ea913979e13e22022653d284444f284a172`
  80. )
  81. .replyWithFile(
  82. 200,
  83. fixture('blobs/c6654ea913979e13e22022653d284444f284a172')
  84. )
  85. ProjectHistoryClient.getSnapshot(
  86. this.projectId,
  87. 'foo.tex',
  88. 4,
  89. (error, body) => {
  90. if (error) {
  91. throw error
  92. }
  93. expect(body).to.deep.equal(
  94. `\
  95. Hello world
  96. One two three
  97. Four five six
  98. Seven eight nince\
  99. `.replace(/^\t/g, '')
  100. )
  101. done()
  102. }
  103. )
  104. })
  105. it('should return the snapshot of a doc after a rename version', function (done) {
  106. MockHistoryStore()
  107. .get(`/api/projects/${this.historyId}/versions/6/history`)
  108. .replyWithFile(200, fixture('chunks/4-6.json'))
  109. MockHistoryStore()
  110. .get(
  111. `/api/projects/${this.historyId}/blobs/c6654ea913979e13e22022653d284444f284a172`
  112. )
  113. .replyWithFile(
  114. 200,
  115. fixture('blobs/c6654ea913979e13e22022653d284444f284a172')
  116. )
  117. ProjectHistoryClient.getSnapshot(
  118. this.projectId,
  119. 'bar.tex',
  120. 6,
  121. (error, body) => {
  122. if (error) {
  123. throw error
  124. }
  125. expect(body).to.deep.equal(
  126. `\
  127. Hello world
  128. One two three
  129. Four five six
  130. Seven eight nine\
  131. `.replace(/^\t/g, '')
  132. )
  133. done()
  134. }
  135. )
  136. })
  137. })
  138. describe('of a binary file', function () {
  139. beforeEach(function () {
  140. MockHistoryStore()
  141. .get(`/api/projects/${this.historyId}/versions/4/history`)
  142. .reply(200, {
  143. chunk: {
  144. history: {
  145. snapshot: {
  146. files: {
  147. binary_file: {
  148. hash: 'c6654ea913979e13e22022653d284444f284a172',
  149. byteLength: 41,
  150. },
  151. },
  152. },
  153. changes: [],
  154. },
  155. startVersion: 3,
  156. },
  157. authors: [],
  158. })
  159. })
  160. it('should return the snapshot of the file at the given version', function (done) {
  161. MockHistoryStore()
  162. .get(
  163. `/api/projects/${this.historyId}/blobs/c6654ea913979e13e22022653d284444f284a172`
  164. )
  165. .replyWithFile(
  166. 200,
  167. fixture('blobs/c6654ea913979e13e22022653d284444f284a172')
  168. )
  169. ProjectHistoryClient.getSnapshot(
  170. this.projectId,
  171. 'binary_file',
  172. 4,
  173. (error, body) => {
  174. if (error) {
  175. throw error
  176. }
  177. expect(body).to.deep.equal(
  178. `\
  179. Hello world
  180. One two three
  181. Four five six\
  182. `.replace(/^\t/g, '')
  183. )
  184. done()
  185. }
  186. )
  187. })
  188. it("should return an error when the blob doesn't exist", function (done) {
  189. MockHistoryStore()
  190. .get(`/api/projects/${this.historyId}/versions/4/history`)
  191. .reply(200, {
  192. chunk: {
  193. history: {
  194. snapshot: {
  195. files: {
  196. binary_file: {
  197. hash: 'c6654ea913979e13e22022653d284444f284a172',
  198. byteLength: 41,
  199. },
  200. },
  201. },
  202. changes: [],
  203. },
  204. startVersion: 3,
  205. },
  206. authors: [],
  207. })
  208. MockHistoryStore()
  209. .get(
  210. `/api/projects/${this.historyId}/blobs/c6654ea913979e13e22022653d284444f284a172`
  211. )
  212. .reply(404)
  213. ProjectHistoryClient.getSnapshot(
  214. this.projectId,
  215. 'binary_file',
  216. 4,
  217. { allowErrors: true },
  218. (error, body, statusCode) => {
  219. if (error) {
  220. throw error
  221. }
  222. expect(statusCode).to.equal(500)
  223. done()
  224. }
  225. )
  226. })
  227. it('should return an error when the blob request errors', function (done) {
  228. MockHistoryStore()
  229. .get(`/api/projects/${this.historyId}/versions/4/history`)
  230. .reply(200, {
  231. chunk: {
  232. history: {
  233. snapshot: {
  234. files: {
  235. binary_file: {
  236. hash: 'c6654ea913979e13e22022653d284444f284a172',
  237. byteLength: 41,
  238. },
  239. },
  240. },
  241. changes: [],
  242. },
  243. startVersion: 3,
  244. },
  245. authors: [],
  246. })
  247. MockHistoryStore()
  248. .get(
  249. `/api/projects/${this.historyId}/blobs/c6654ea913979e13e22022653d284444f284a172`
  250. )
  251. .replyWithError('oh no!')
  252. ProjectHistoryClient.getSnapshot(
  253. this.projectId,
  254. 'binary_file',
  255. 4,
  256. { allowErrors: true },
  257. (error, body, statusCode) => {
  258. if (error) {
  259. throw error
  260. }
  261. expect(statusCode).to.equal(500)
  262. done()
  263. }
  264. )
  265. })
  266. })
  267. })