| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- import { vi, expect, describe, beforeEach, it } from 'vitest'
- import sinon from 'sinon'
- import Path from 'node:path'
- import * as Errors from '../../../app/js/Errors.js'
- const modulePath = Path.join(
- import.meta.dirname,
- '../../../app/js/ResourceStateManager'
- )
- describe('ResourceStateManager', () => {
- beforeEach(async ctx => {
- vi.doMock('fs', () => ({
- default: (ctx.fs = {}),
- }))
- vi.doMock('../../../app/js/SafeReader', () => ({
- default: (ctx.SafeReader = {}),
- }))
- ctx.ResourceStateManager = (await import(modulePath)).default
- ctx.basePath = '/path/to/write/files/to'
- ctx.resources = [
- { path: 'resource-1-mock' },
- { path: 'resource-2-mock' },
- { path: 'resource-3-mock' },
- ]
- ctx.state = '1234567890'
- ctx.resourceFileName = `${ctx.basePath}/.project-sync-state`
- ctx.resourceFileContents = `${ctx.resources[0].path}\n${ctx.resources[1].path}\n${ctx.resources[2].path}\nstateHash:${ctx.state}`
- ctx.callback = sinon.stub()
- })
- describe('saveProjectState', () => {
- beforeEach(ctx => {
- ctx.fs.writeFile = sinon.stub().callsArg(2)
- })
- describe('when the state is specified', () => {
- beforeEach(ctx => {
- ctx.ResourceStateManager.saveProjectState(
- ctx.state,
- ctx.resources,
- ctx.basePath,
- ctx.callback
- )
- })
- it('should write the resource list to disk', ctx => {
- ctx.fs.writeFile
- .calledWith(ctx.resourceFileName, ctx.resourceFileContents)
- .should.equal(true)
- })
- it('should call the callback', ctx => {
- ctx.callback.called.should.equal(true)
- })
- })
- describe('when the state is undefined', () => {
- beforeEach(ctx => {
- ctx.state = undefined
- ctx.fs.unlink = sinon.stub().callsArg(1)
- ctx.ResourceStateManager.saveProjectState(
- ctx.state,
- ctx.resources,
- ctx.basePath,
- ctx.callback
- )
- })
- it('should unlink the resource file', ctx => {
- ctx.fs.unlink.calledWith(ctx.resourceFileName).should.equal(true)
- })
- it('should not write the resource list to disk', ctx => {
- ctx.fs.writeFile.called.should.equal(false)
- })
- it('should call the callback', ctx => {
- ctx.callback.called.should.equal(true)
- })
- })
- })
- describe('checkProjectStateMatches', () => {
- describe('when the state matches', () => {
- beforeEach(ctx => {
- ctx.SafeReader.readFile = sinon
- .stub()
- .callsArgWith(3, null, ctx.resourceFileContents)
- ctx.ResourceStateManager.checkProjectStateMatches(
- ctx.state,
- ctx.basePath,
- ctx.callback
- )
- })
- it('should read the resource file', ctx => {
- ctx.SafeReader.readFile
- .calledWith(ctx.resourceFileName)
- .should.equal(true)
- })
- it('should call the callback with the results', ctx => {
- ctx.callback.calledWithMatch(null, ctx.resources).should.equal(true)
- })
- })
- describe('when the state file is not present', () => {
- beforeEach(ctx => {
- ctx.SafeReader.readFile = sinon.stub().callsArg(3)
- ctx.ResourceStateManager.checkProjectStateMatches(
- ctx.state,
- ctx.basePath,
- ctx.callback
- )
- })
- it('should read the resource file', ctx => {
- ctx.SafeReader.readFile
- .calledWith(ctx.resourceFileName)
- .should.equal(true)
- })
- it('should call the callback with an error', ctx => {
- ctx.callback
- .calledWith(sinon.match(Errors.FilesOutOfSyncError))
- .should.equal(true)
- const message = ctx.callback.args[0][0].message
- expect(message).to.include('invalid state for incremental update')
- })
- })
- describe('when the state does not match', () => {
- beforeEach(ctx => {
- ctx.SafeReader.readFile = sinon
- .stub()
- .callsArgWith(3, null, ctx.resourceFileContents)
- ctx.ResourceStateManager.checkProjectStateMatches(
- 'not-the-original-state',
- ctx.basePath,
- ctx.callback
- )
- })
- it('should call the callback with an error', ctx => {
- ctx.callback
- .calledWith(sinon.match(Errors.FilesOutOfSyncError))
- .should.equal(true)
- const message = ctx.callback.args[0][0].message
- expect(message).to.include('invalid state for incremental update')
- })
- })
- })
- describe('checkResourceFiles', () => {
- describe('when all the files are present', () => {
- beforeEach(ctx => {
- ctx.allFiles = [
- ctx.resources[0].path,
- ctx.resources[1].path,
- ctx.resources[2].path,
- ]
- ctx.ResourceStateManager.checkResourceFiles(
- ctx.resources,
- ctx.allFiles,
- ctx.basePath,
- ctx.callback
- )
- })
- it('should call the callback', ctx => {
- ctx.callback.calledWithExactly().should.equal(true)
- })
- })
- describe('when there is a missing file', () => {
- beforeEach(ctx => {
- ctx.allFiles = [ctx.resources[0].path, ctx.resources[1].path]
- ctx.fs.stat = sinon.stub().callsArgWith(1, new Error())
- ctx.ResourceStateManager.checkResourceFiles(
- ctx.resources,
- ctx.allFiles,
- ctx.basePath,
- ctx.callback
- )
- })
- it('should call the callback with an error', ctx => {
- ctx.callback
- .calledWith(sinon.match(Errors.FilesOutOfSyncError))
- .should.equal(true)
- const message = ctx.callback.args[0][0].message
- expect(message).to.include(
- 'resource files missing in incremental update'
- )
- })
- })
- describe('when a resource contains a relative path', () => {
- beforeEach(ctx => {
- ctx.resources[0].path = '../foo/bar.tex'
- ctx.allFiles = [
- ctx.resources[0].path,
- ctx.resources[1].path,
- ctx.resources[2].path,
- ]
- ctx.ResourceStateManager.checkResourceFiles(
- ctx.resources,
- ctx.allFiles,
- ctx.basePath,
- ctx.callback
- )
- })
- it('should call the callback with an error', ctx => {
- ctx.callback.calledWith(sinon.match(Error)).should.equal(true)
- const message = ctx.callback.args[0][0].message
- expect(message).to.include('relative path in resource file list')
- })
- })
- })
- })
|