| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- /* eslint-disable
- no-return-assign,
- no-undef,
- no-unused-vars,
- */
- // TODO: This file was created by bulk-decaffeinate.
- // Fix any style issues and re-enable lint.
- /*
- * decaffeinate suggestions:
- * DS102: Remove unnecessary code created because of implicit returns
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
- */
- import sinon from 'sinon'
- import { expect } from 'chai'
- import { strict as esmock } from 'esmock'
- import Core from 'overleaf-editor-core'
- import BPromise from 'bluebird'
- import * as Errors from '../../../../app/js/Errors.js'
- const MODULE_PATH = '../../../../app/js/SnapshotManager.js'
- describe('SnapshotManager', function () {
- beforeEach(async function () {
- this.HistoryStoreManager = {
- getBlobStore: sinon.stub(),
- getChunkAtVersion: sinon.stub(),
- getMostRecentChunk: sinon.stub(),
- getProjectBlobStream: sinon.stub(),
- }
- this.WebApiManager = {
- getHistoryId: sinon.stub(),
- }
- this.SnapshotManager = await esmock(MODULE_PATH, {
- 'overleaf-editor-core': Core,
- '../../../../app/js/HistoryStoreManager.js': this.HistoryStoreManager,
- '../../../../app/js/WebApiManager.js': this.WebApiManager,
- '../../../../app/js/Errors.js': Errors,
- })
- this.projectId = 'project-id-123'
- this.historyId = 'ol-project-id-123'
- return (this.callback = sinon.stub())
- })
- describe('getFileSnapshotStream', function () {
- beforeEach(function () {
- this.WebApiManager.getHistoryId.yields(null, this.historyId)
- return this.HistoryStoreManager.getChunkAtVersion.yields(null, {
- chunk: {
- history: {
- snapshot: {
- files: {
- 'main.tex': {
- hash: '35c9bd86574d61dcadbce2fdd3d4a0684272c6ea',
- stringLength: 41,
- },
- 'binary.png': {
- hash: 'c6654ea913979e13e22022653d284444f284a172',
- byteLength: 41,
- },
- },
- },
- changes: [
- {
- operations: [
- {
- pathname: 'main.tex',
- textOperation: [41, '\n\nSeven eight'],
- },
- ],
- timestamp: '2017-12-04T10:29:17.786Z',
- authors: [31],
- },
- {
- operations: [
- {
- pathname: 'main.tex',
- textOperation: [54, ' nine'],
- },
- ],
- timestamp: '2017-12-04T10:29:22.905Z',
- authors: [31],
- },
- ],
- },
- startVersion: 3,
- authors: [
- {
- id: 31,
- email: 'james.allen@overleaf.com',
- name: 'James',
- },
- ],
- },
- })
- })
- describe('of a text file', function () {
- beforeEach(function (done) {
- this.HistoryStoreManager.getBlobStore.withArgs(this.historyId).returns({
- getString: BPromise.promisify(
- (this.getString = sinon.stub().yields(
- null,
- `\
- Hello world
- One two three
- Four five six\
- `.replace(/^\t/g, '')
- ))
- ),
- })
- this.SnapshotManager.getFileSnapshotStream(
- this.projectId,
- 5,
- 'main.tex',
- (error, stream) => {
- this.stream = stream
- return done(error)
- }
- )
- })
- it('should get the overleaf id', function () {
- return this.WebApiManager.getHistoryId
- .calledWith(this.projectId)
- .should.equal(true)
- })
- it('should get the chunk', function () {
- return this.HistoryStoreManager.getChunkAtVersion
- .calledWith(this.projectId, this.historyId, 5)
- .should.equal(true)
- })
- it('should get the blob of the starting snapshot', function () {
- return this.getString
- .calledWith('35c9bd86574d61dcadbce2fdd3d4a0684272c6ea')
- .should.equal(true)
- })
- it('should return a string stream with the text content', function () {
- return expect(this.stream.read().toString()).to.equal(
- `\
- Hello world
- One two three
- Four five six
- Seven eight nine\
- `.replace(/^\t/g, '')
- )
- })
- describe('on blob store error', function () {
- beforeEach(function () {
- this.error = new Error('ESOCKETTIMEDOUT')
- this.HistoryStoreManager.getBlobStore
- .withArgs(this.historyId)
- .returns({
- getString: BPromise.promisify(sinon.stub().throws(this.error)),
- })
- })
- it('should call back with error', function (done) {
- this.SnapshotManager.getFileSnapshotStream(
- this.projectId,
- 5,
- 'main.tex',
- error => {
- expect(error).to.exist
- expect(error.name).to.equal(this.error.name)
- done()
- }
- )
- })
- })
- })
- describe('of a binary file', function () {
- beforeEach(function (done) {
- this.HistoryStoreManager.getProjectBlobStream
- .withArgs(this.historyId)
- .yields(null, (this.stream = 'mock-stream'))
- return this.SnapshotManager.getFileSnapshotStream(
- this.projectId,
- 5,
- 'binary.png',
- (error, returnedStream) => {
- this.returnedStream = returnedStream
- return done(error)
- }
- )
- })
- it('should get the overleaf id', function () {
- return this.WebApiManager.getHistoryId
- .calledWith(this.projectId)
- .should.equal(true)
- })
- it('should get the chunk', function () {
- return this.HistoryStoreManager.getChunkAtVersion
- .calledWith(this.projectId, this.historyId, 5)
- .should.equal(true)
- })
- it('should get the blob of the starting snapshot', function () {
- return this.HistoryStoreManager.getProjectBlobStream
- .calledWith(
- this.historyId,
- 'c6654ea913979e13e22022653d284444f284a172'
- )
- .should.equal(true)
- })
- return it('should return a stream with the blob content', function () {
- return expect(this.returnedStream).to.equal(this.stream)
- })
- })
- return describe("when the file doesn't exist", function () {
- beforeEach(function (done) {
- return this.SnapshotManager.getFileSnapshotStream(
- this.projectId,
- 5,
- 'not-here.png',
- (error, returnedStream) => {
- this.error = error
- this.returnedStream = returnedStream
- return done()
- }
- )
- })
- return it('should return a NotFoundError', function () {
- expect(this.error).to.exist
- expect(this.error.message).to.equal('not-here.png not found')
- return expect(this.error).to.be.an.instanceof(Errors.NotFoundError)
- })
- })
- })
- describe('getProjectSnapshot', function () {
- beforeEach(function () {
- this.WebApiManager.getHistoryId.yields(null, this.historyId)
- return this.HistoryStoreManager.getChunkAtVersion.yields(null, {
- chunk: (this.chunk = {
- history: {
- snapshot: {
- files: {
- 'main.tex': {
- hash: '35c9bd86574d61dcadbce2fdd3d4a0684272c6ea',
- stringLength: 41,
- },
- 'unchanged.tex': {
- hash: '35c9bd86574d61dcadbce2fdd3d4a0684272c6ea',
- stringLength: 41,
- },
- 'binary.png': {
- hash: 'c6654ea913979e13e22022653d284444f284a172',
- byteLength: 41,
- },
- },
- },
- changes: [
- {
- operations: [
- {
- pathname: 'main.tex',
- textOperation: [41, '\n\nSeven eight'],
- },
- ],
- timestamp: '2017-12-04T10:29:17.786Z',
- authors: [31],
- },
- {
- operations: [
- {
- pathname: 'main.tex',
- textOperation: [54, ' nine'],
- },
- ],
- timestamp: '2017-12-04T10:29:22.905Z',
- authors: [31],
- },
- ],
- },
- startVersion: 3,
- authors: [
- {
- id: 31,
- email: 'james.allen@overleaf.com',
- name: 'James',
- },
- ],
- }),
- })
- })
- describe('of project', function () {
- beforeEach(function (done) {
- this.HistoryStoreManager.getBlobStore.withArgs(this.historyId).returns({
- getString: BPromise.promisify(
- (this.getString = sinon.stub().yields(
- null,
- `\
- Hello world
- One two three
- Four five six\
- `.replace(/^\t/g, '')
- ))
- ),
- })
- this.SnapshotManager.getProjectSnapshot(
- this.projectId,
- 5,
- (error, data) => {
- this.data = data
- done(error)
- }
- )
- })
- it('should get the overleaf id', function () {
- return this.WebApiManager.getHistoryId
- .calledWith(this.projectId)
- .should.equal(true)
- })
- it('should get the chunk', function () {
- return this.HistoryStoreManager.getChunkAtVersion
- .calledWith(this.projectId, this.historyId, 5)
- .should.equal(true)
- })
- return it('should produce the snapshot file data', function () {
- expect(this.data).to.have.all.keys(['files', 'projectId'])
- expect(this.data.projectId).to.equal('project-id-123')
- expect(this.data.files['main.tex']).to.exist
- expect(this.data.files['unchanged.tex']).to.exist
- expect(this.data.files['binary.png']).to.exist
- // files with operations in the chunk should return content only
- expect(this.data.files['main.tex'].data.content).to.equal(
- 'Hello world\n\nOne two three\n\nFour five six\n\nSeven eight nine'
- )
- expect(this.data.files['main.tex'].data.hash).to.not.exist
- // unchanged files in the chunk should return hash only
- expect(this.data.files['unchanged.tex'].data.hash).to.equal(
- '35c9bd86574d61dcadbce2fdd3d4a0684272c6ea'
- )
- expect(this.data.files['unchanged.tex'].data.content).to.not.exist
- return expect(this.data.files['binary.png'].data.hash).to.equal(
- 'c6654ea913979e13e22022653d284444f284a172'
- )
- })
- })
- describe('on blob store error', function () {
- beforeEach(function () {
- this.error = new Error('ESOCKETTIMEDOUT')
- this.HistoryStoreManager.getBlobStore.withArgs(this.historyId).returns({
- getString: BPromise.promisify(sinon.stub().yields(this.error)),
- })
- })
- it('should call back with error', function (done) {
- this.SnapshotManager.getProjectSnapshot(this.projectId, 5, error => {
- expect(error).to.exist
- expect(error.message).to.equal(this.error.message)
- done()
- })
- })
- })
- })
- return describe('getLatestSnapshot', function () {
- describe('for a project', function () {
- beforeEach(function (done) {
- this.HistoryStoreManager.getMostRecentChunk.yields(null, {
- chunk: (this.chunk = {
- history: {
- snapshot: {
- files: {
- 'main.tex': {
- hash: '35c9bd86574d61dcadbce2fdd3d4a0684272c6ea',
- stringLength: 41,
- },
- 'binary.png': {
- hash: 'c6654ea913979e13e22022653d284444f284a172',
- byteLength: 41,
- },
- },
- },
- changes: [
- {
- operations: [
- {
- pathname: 'main.tex',
- textOperation: [41, '\n\nSeven eight'],
- },
- ],
- timestamp: '2017-12-04T10:29:17.786Z',
- authors: [31],
- },
- {
- operations: [
- {
- pathname: 'main.tex',
- textOperation: [54, ' nine'],
- },
- ],
- timestamp: '2017-12-04T10:29:22.905Z',
- authors: [31],
- },
- ],
- },
- startVersion: 3,
- authors: [
- {
- id: 31,
- email: 'james.allen@overleaf.com',
- name: 'James',
- },
- ],
- }),
- })
- this.HistoryStoreManager.getBlobStore.withArgs(this.historyId).returns({
- getString: BPromise.promisify(
- (this.getString = sinon.stub().yields(
- null,
- `\
- Hello world
- One two three
- Four five six\
- `.replace(/^\t/g, '')
- ))
- ),
- })
- this.SnapshotManager.getLatestSnapshot(
- this.projectId,
- this.historyId,
- (error, data) => {
- this.data = data
- done(error)
- }
- )
- })
- it('should get the chunk', function () {
- return this.HistoryStoreManager.getMostRecentChunk
- .calledWith(this.projectId, this.historyId)
- .should.equal(true)
- })
- return it('should produce the snapshot file data', function () {
- expect(this.data).to.have.all.keys(['main.tex', 'binary.png'])
- expect(this.data['main.tex']).to.exist
- expect(this.data['binary.png']).to.exist
- expect(this.data['main.tex'].getStringLength()).to.equal(59)
- expect(this.data['binary.png'].getByteLength()).to.equal(41)
- return expect(this.data['binary.png'].getHash()).to.equal(
- 'c6654ea913979e13e22022653d284444f284a172'
- )
- })
- })
- return describe('when the chunk is empty', function () {
- beforeEach(function (done) {
- this.HistoryStoreManager.getMostRecentChunk.yields(null)
- return this.SnapshotManager.getLatestSnapshot(
- this.projectId,
- this.historyId,
- (error, data) => {
- this.error = error
- this.data = data
- return done()
- }
- )
- })
- it('should get the chunk', function () {
- return this.HistoryStoreManager.getMostRecentChunk
- .calledWith(this.projectId, this.historyId)
- .should.equal(true)
- })
- return it('return an error', function () {
- expect(this.error).to.exist
- return expect(this.error.message).to.equal('undefined chunk')
- })
- })
- })
- })
|