| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- /* eslint-disable
- max-len,
- no-return-assign,
- */
- /* global inject, sinon */
- // 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 HistoryV2Manager from '../../../../frontend/js/ide/history/HistoryV2Manager'
- export default describe('HistoryV2Manager', function () {
- beforeEach(function (done) {
- this.defaultHistoryScope = {
- isV2: true,
- updates: [],
- viewMode: 'point_in_time',
- nextBeforeTimestamp: null,
- loading: false,
- atEnd: false,
- userHasFullFeature: undefined,
- freeHistoryLimitHit: false,
- selection: {
- docs: {},
- pathname: null,
- range: {
- fromV: null,
- toV: null,
- },
- hoveredRange: {
- fromV: null,
- toV: null,
- },
- diff: null,
- files: [],
- file: null,
- },
- error: null,
- showOnlyLabels: false,
- labels: null,
- loadingFileTree: true,
- isReact: false,
- }
- this.sampleUpdates = [
- {
- fromV: 4,
- toV: 5,
- meta: {
- users: [
- {
- first_name: 'john.doe',
- last_name: '',
- email: 'john.doe@domain.tld',
- id: '5b57299087712202fb599ab4',
- hue: 200,
- },
- ],
- start_ts: 1544021278346,
- end_ts: 1544021278346,
- },
- labels: [
- {
- id: '5c07e822042e67003b448f18',
- comment: 'My first label',
- version: 5,
- user_id: '5b57299087712202fb599ab4',
- created_at: '2018-12-05T15:00:50.688Z',
- },
- ],
- pathnames: [],
- project_ops: [
- {
- add: {
- pathname: 'chapters/chapter1.tex',
- },
- atV: 4,
- },
- ],
- },
- {
- fromV: 3,
- toV: 4,
- meta: {
- users: [
- {
- first_name: 'john.doe',
- last_name: '',
- email: 'john.doe@domain.tld',
- id: '5b57299087712202fb599ab4',
- hue: 200,
- },
- ],
- start_ts: 1544021262622,
- end_ts: 1544021262622,
- },
- labels: [],
- pathnames: ['main.tex'],
- project_ops: [],
- },
- {
- fromV: 0,
- toV: 3,
- meta: {
- users: [
- {
- first_name: 'john.doe',
- last_name: '',
- email: 'john.doe@domain.tld',
- id: '5b57299087712202fb599ab4',
- hue: 200,
- },
- ],
- start_ts: 1544021213540,
- end_ts: 1544021213618,
- },
- labels: [],
- pathnames: [],
- project_ops: [
- {
- add: {
- pathname: 'universe.jpg',
- },
- atV: 2,
- },
- {
- add: {
- pathname: 'references.bib',
- },
- atV: 1,
- },
- {
- add: {
- pathname: 'main.tex',
- },
- atV: 0,
- },
- ],
- },
- ]
- inject(($q, $http, $filter, $rootScope) => {
- this.$scope = $rootScope.$new()
- this.$scope.project = {
- features: {
- versioning: true,
- },
- }
- this.$scope.user = {
- isAdmin: false,
- }
- this.ide = {
- globalEditorWatchdogManager: { attachToEditor() {} },
- $q,
- $http,
- $filter,
- }
- this.eventTracking = {
- sendMB: () => {},
- }
- this.localStorage = sinon.stub().returns(null)
- this.historyManager = new HistoryV2Manager(
- this.ide,
- this.$scope,
- this.localStorage,
- this.eventTracking
- )
- done()
- })
- })
- it('should setup the history scope on initialization', function () {
- expect(this.$scope.history).to.deep.equal(this.defaultHistoryScope)
- })
- it('should keep history updates after performing a soft reset', function () {
- const historyScopeWithUpdates = Object.assign(
- {},
- this.defaultHistoryScope,
- {
- updates: this.sampleUpdates,
- }
- )
- this.$scope.history.updates = this.sampleUpdates
- this.historyManager.softReset()
- expect(this.$scope.history).to.deep.equal(historyScopeWithUpdates)
- })
- it('should discard history updates after performing a hard reset', function () {
- this.$scope.history.updates = this.sampleUpdates
- this.historyManager.hardReset()
- expect(this.$scope.history).to.deep.equal(this.defaultHistoryScope)
- })
- it('should setup history with full access to the feature if the project has versioning', function () {
- this.$scope.$digest()
- expect(this.$scope.history.userHasFullFeature).to.equal(true)
- })
- it('should setup history without full access to the feature if the project does not have versioning', function () {
- this.$scope.project.features.versioning = false
- this.historyManager = new HistoryV2Manager(
- this.ide,
- this.$scope,
- this.localStorage
- )
- this.$scope.$digest()
- expect(this.$scope.history.userHasFullFeature).to.equal(false)
- })
- it('should setup history with full access to the feature for admin users even if the project does not have versioning', function () {
- this.$scope.project.features.versioning = false
- this.$scope.user.isAdmin = true
- this.historyManager = new HistoryV2Manager(
- this.ide,
- this.$scope,
- this.localStorage
- )
- this.$scope.$digest()
- expect(this.$scope.history.userHasFullFeature).to.equal(true)
- })
- describe('autoSelectFile', function () {
- describe('for compare mode', function () {
- beforeEach(function () {
- this.mockedFilesList = [
- {
- pathname: 'main.tex',
- },
- {
- pathname: 'references.bib',
- },
- {
- pathname: 'universe.jpg',
- },
- {
- pathname: 'chapters/chapter2.tex',
- },
- {
- pathname: 'chapters/draft.tex',
- operation: 'removed',
- deletedAtV: 47,
- },
- {
- pathname: 'chapters/chapter3.tex',
- operation: 'added',
- },
- {
- pathname: 'chapters/chapter1.tex',
- operation: 'edited',
- },
- {
- pathname: 'chapters/foo.tex',
- oldPathname: 'chapters/bar.tex',
- operation: 'renamed',
- },
- ]
- this.mockedMainTex = this.mockedFilesList[0]
- this.mockedReferencesFile = this.mockedFilesList[1]
- this.mockedRemovedFile = this.mockedFilesList[4]
- this.mockedAddedFile = this.mockedFilesList[5]
- this.mockedEditedFile = this.mockedFilesList[6]
- this.mockedRenamedFile = this.mockedFilesList[7]
- this.$scope.history.viewMode = 'compare'
- this.$scope.history.selection.files = this.mockedFilesList
- })
- describe('with a previously selected file', function () {
- it('should prefer the previously selected file if it is available and has operations', function () {
- this.historyManager._previouslySelectedPathname =
- this.mockedAddedFile.pathname
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedAddedFile
- )
- })
- it('should prefer a file with ops if the previously selected file is available but has no operations', function () {
- this.historyManager._previouslySelectedPathname =
- this.mockedReferencesFile.pathname
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.operation).to.exist
- })
- it('should ignore the previously selected file if it is not available', function () {
- this.historyManager._previouslySelectedPathname = 'non/existent.file'
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.not.equal(
- 'non/existent.file'
- )
- })
- })
- describe('without a previously selected file, with a list of files containing operations', function () {
- it('should prefer edited files', function () {
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedEditedFile
- )
- })
- it('should prefer added files if no edited files are present', function () {
- const indexOfEditedFile = this.$scope.history.selection.files.indexOf(
- this.mockedEditedFile
- )
- this.$scope.history.selection.files.splice(indexOfEditedFile, 1)
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedAddedFile
- )
- })
- it('should prefer renamed files if no edited or added files are present', function () {
- const indexOfEditedFile = this.$scope.history.selection.files.indexOf(
- this.mockedEditedFile
- )
- this.$scope.history.selection.files.splice(indexOfEditedFile, 1)
- const indexOfAddedFile = this.$scope.history.selection.files.indexOf(
- this.mockedAddedFile
- )
- this.$scope.history.selection.files.splice(indexOfAddedFile, 1)
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedRenamedFile
- )
- })
- it('should prefer removed files if no edited, added or renamed files are present', function () {
- const indexOfEditedFile = this.$scope.history.selection.files.indexOf(
- this.mockedEditedFile
- )
- this.$scope.history.selection.files.splice(indexOfEditedFile, 1)
- const indexOfAddedFile = this.$scope.history.selection.files.indexOf(
- this.mockedAddedFile
- )
- this.$scope.history.selection.files.splice(indexOfAddedFile, 1)
- const indexOfRenamedFile =
- this.$scope.history.selection.files.indexOf(this.mockedRenamedFile)
- this.$scope.history.selection.files.splice(indexOfRenamedFile, 1)
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedRemovedFile
- )
- })
- })
- describe('without a previously selected file, with a list of files without operations', function () {
- beforeEach(function () {
- this.mockedFilesListWithNoOps = [
- {
- pathname: 'main.tex',
- },
- {
- pathname: 'references.bib',
- },
- {
- pathname: 'other.tex',
- },
- {
- pathname: 'universe.jpg',
- },
- ]
- this.mockedMainTex = this.mockedFilesListWithNoOps[0]
- this.mockedReferencesFile = this.mockedFilesListWithNoOps[1]
- this.mockedOtherTexFile = this.mockedFilesListWithNoOps[2]
- this.$scope.history.selection.files = this.mockedFilesListWithNoOps
- })
- it('should prefer main.tex if it exists', function () {
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedMainTex
- )
- })
- it('should prefer another tex file if main.tex does not exist', function () {
- const indexOfMainTex = this.$scope.history.selection.files.indexOf(
- this.mockedMainTex
- )
- this.$scope.history.selection.files.splice(indexOfMainTex, 1)
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedOtherTexFile
- )
- })
- it('should pick the first available file if no tex files are available', function () {
- const indexOfMainTex = this.$scope.history.selection.files.indexOf(
- this.mockedMainTex
- )
- this.$scope.history.selection.files.splice(indexOfMainTex, 1)
- const indexOfOtherTexFile =
- this.$scope.history.selection.files.indexOf(this.mockedOtherTexFile)
- this.$scope.history.selection.files.splice(indexOfOtherTexFile, 1)
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file).to.deep.equal(
- this.mockedReferencesFile
- )
- })
- })
- })
- describe('for point-in-time mode', function () {
- beforeEach(function () {
- this.$scope.history.viewMode = 'point_in_time'
- this.sampleUpdates[0] = {
- fromV: 4,
- toV: 5,
- meta: {
- users: [
- {
- first_name: 'john.doe',
- last_name: '',
- email: 'john.doe@domain.tld',
- id: '5b57299087712202fb599ab4',
- hue: 200,
- },
- ],
- start_ts: 1544021278346,
- end_ts: 1544021278346,
- },
- pathnames: ['main.tex'],
- project_ops: [
- {
- add: {
- pathname: 'chapters/chapter1.tex',
- },
- atV: 4,
- },
- {
- rename: {
- pathname: 'foo.tex',
- newPathname: 'bar.tex',
- },
- },
- ],
- }
- this.sampleUpdateEditedFile = this.sampleUpdates[0].pathnames[0]
- this.sampleUpdateAddedFile =
- this.sampleUpdates[0].project_ops[0].add.pathname
- this.sampleUpdateRenamedFile =
- this.sampleUpdates[0].project_ops[1].rename.newPathname
- this.$scope.history.updates = this.sampleUpdates
- this.$scope.history.selection.range = {
- fromV: this.sampleUpdates[0].toV,
- toV: this.sampleUpdates[0].toV,
- }
- this.mockedFilesList = [
- {
- pathname: 'main.tex',
- },
- {
- pathname: 'references.bib',
- },
- {
- pathname: 'universe.jpg',
- },
- {
- pathname: 'chapters/chapter2.tex',
- },
- {
- pathname: 'chapters/draft.tex',
- },
- {
- pathname: 'chapters/chapter3.tex',
- },
- {
- pathname: 'chapters/chapter1.tex',
- },
- {
- pathname: 'bar.tex',
- },
- ]
- this.$scope.history.selection.files = this.mockedFilesList
- })
- describe('with a previously selected file', function () {
- it('should prefer the previously selected file if it is available and has operations', function () {
- this.historyManager._previouslySelectedPathname = 'main.tex'
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.equal(
- this.sampleUpdateEditedFile
- )
- })
- it('should prefer a file with ops if the previously selected file is available but has no operations', function () {
- this.historyManager._previouslySelectedPathname = 'main.tex'
- this.sampleUpdates[0].pathnames = []
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.equal(
- this.sampleUpdateAddedFile
- )
- })
- it('should ignore the previously selected file if it is not available', function () {
- this.historyManager._previouslySelectedPathname = 'non/existent.file'
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.not.equal(
- 'non/existent.file'
- )
- })
- })
- describe('without a previously selected file, with a list of files containing operations', function () {
- it('should prefer edited files', function () {
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.equal(
- this.sampleUpdateEditedFile
- )
- })
- it('should prefer added files if no edited files are present', function () {
- this.sampleUpdates[0].pathnames = []
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.equal(
- this.sampleUpdateAddedFile
- )
- })
- it('should prefer renamed files if no edited or added files are present', function () {
- this.sampleUpdates[0].pathnames = []
- this.sampleUpdates[0].project_ops.shift()
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.equal(
- this.sampleUpdateRenamedFile
- )
- })
- })
- describe('without a previously selected file, with a list of files without operations', function () {
- beforeEach(function () {
- this.sampleUpdates[0].pathnames = []
- this.sampleUpdates[0].project_ops = []
- this.mockedMainTex = this.mockedFilesList[0]
- this.mockedReferencesFile = this.mockedFilesList[1]
- })
- it('should prefer main.tex if it exists', function () {
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.equal(
- this.mockedMainTex.pathname
- )
- })
- it('should prefer another tex file if main.tex does not exist', function () {
- const indexOfMainTex = this.$scope.history.selection.files.indexOf(
- this.mockedMainTex
- )
- this.$scope.history.selection.files.splice(indexOfMainTex, 1)
- this.historyManager.autoSelectFile()
- expect(this.$scope.history.selection.file.pathname).to.match(/.tex$/)
- })
- })
- })
- describe('_loadLabels', function () {
- it('should return labels list as is if there is a label for the last version', function () {
- const labels = [
- {
- id: '1',
- version: 1,
- comment: 'foo',
- created_at: new Date().toISOString(),
- },
- {
- id: '2',
- version: 2,
- comment: 'bar',
- created_at: new Date().toISOString(),
- },
- {
- id: '3',
- version: 3,
- comment: 'baz',
- created_at: new Date().toISOString(),
- },
- ]
- const lastUpdate = 3
- const labelsResult = this.historyManager._loadLabels(labels, lastUpdate)
- expect(labelsResult).to.have.members(labels)
- })
- it('should return a labels list with a pseudo current state label if there is no label for the last version', function () {
- const labels = [
- {
- id: '1',
- version: 1,
- comment: 'foo',
- created_at: new Date().toISOString(),
- },
- {
- id: '2',
- version: 2,
- comment: 'bar',
- created_at: new Date().toISOString(),
- },
- {
- id: '3',
- version: 3,
- comment: 'baz',
- created_at: new Date().toISOString(),
- },
- ]
- const lastUpdate = 5
- const labelsResult = this.historyManager._loadLabels(labels, lastUpdate)
- expect(labelsResult).to.include.members(labels)
- expect(labelsResult[0].isPseudoCurrentStateLabel).to.equal(true)
- expect(labelsResult[0].version).to.equal(5)
- })
- it('should keep pseudo label when deleting label', function () {
- this.historyManager.$scope.history.labels = [
- {
- id: '1',
- version: 1,
- comment: 'foo',
- created_at: new Date().toISOString(),
- },
- ]
- const lastUpdate = 5
- this.historyManager.$scope.history.labels =
- this.historyManager._loadLabels(
- this.historyManager.$scope.history.labels,
- lastUpdate
- )
- expect(
- this.historyManager.$scope.history.labels[0].isPseudoCurrentStateLabel
- ).to.equal(true)
- this.historyManager.$scope.history.labels =
- this.historyManager._loadLabels([], lastUpdate)
- expect(
- this.historyManager.$scope.history.labels[0].isPseudoCurrentStateLabel
- ).to.equal(true)
- expect(this.historyManager.$scope.history.labels[0].version).to.equal(5)
- })
- })
- })
- })
|