|
|
@@ -36,7 +36,6 @@ describe('ConversionManager', function () {
|
|
|
}
|
|
|
|
|
|
ctx.conversionId = 'test-conversion-id'
|
|
|
- ctx.inputPath = '/path/to/input.docx'
|
|
|
ctx.conversionDir = '/compiles/test-conversion-id'
|
|
|
ctx.outputPath = '/compiles/test-conversion-id/output-uuid.zip'
|
|
|
|
|
|
@@ -65,188 +64,287 @@ describe('ConversionManager', function () {
|
|
|
ctx.uuidStub.restore()
|
|
|
})
|
|
|
|
|
|
- describe('convertDocxToLaTeXWithLock', function () {
|
|
|
- describe('general behavior', function () {
|
|
|
- beforeEach(async function (ctx) {
|
|
|
- ctx.result =
|
|
|
- await ctx.ConversionManager.promises.convertDocxToLaTeXWithLock(
|
|
|
- ctx.conversionId,
|
|
|
- ctx.inputPath
|
|
|
- )
|
|
|
+ describe('convertToLaTeXWithLock', function () {
|
|
|
+ describe('with conversionType=docx', function () {
|
|
|
+ beforeEach(function (ctx) {
|
|
|
+ ctx.inputPath = '/path/to/input.docx'
|
|
|
})
|
|
|
|
|
|
- it('should acquire a lock', async function (ctx) {
|
|
|
- sinon.assert.calledWith(ctx.LockManager.acquire, ctx.conversionDir)
|
|
|
- })
|
|
|
+ describe('file setup and pandoc args', function () {
|
|
|
+ beforeEach(async function (ctx) {
|
|
|
+ ctx.result =
|
|
|
+ await ctx.ConversionManager.promises.convertToLaTeXWithLock(
|
|
|
+ ctx.conversionId,
|
|
|
+ ctx.inputPath,
|
|
|
+ 'docx'
|
|
|
+ )
|
|
|
+ })
|
|
|
|
|
|
- it('should copy the input file to the conversion directory', async function (ctx) {
|
|
|
- sinon.assert.calledWith(ctx.fs.mkdir, ctx.conversionDir, {
|
|
|
- recursive: true,
|
|
|
+ it('should acquire a lock', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(ctx.LockManager.acquire, ctx.conversionDir)
|
|
|
})
|
|
|
- sinon.assert.calledWith(
|
|
|
- ctx.fs.copyFile,
|
|
|
- ctx.inputPath,
|
|
|
- Path.join(ctx.conversionDir, 'input.docx')
|
|
|
- )
|
|
|
- })
|
|
|
|
|
|
- it('should convert conversion timeout to milliseconds', async function (ctx) {
|
|
|
- expect(ctx.CommandRunner.promises.run.firstCall.args[4]).toBe(60_000)
|
|
|
- expect(ctx.CommandRunner.promises.run.secondCall.args[4]).toBe(60_000)
|
|
|
- })
|
|
|
+ it('should copy the input file to the conversion directory with docx filename', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(ctx.fs.mkdir, ctx.conversionDir, {
|
|
|
+ recursive: true,
|
|
|
+ })
|
|
|
+ sinon.assert.calledWith(
|
|
|
+ ctx.fs.copyFile,
|
|
|
+ ctx.inputPath,
|
|
|
+ Path.join(ctx.conversionDir, 'input.docx')
|
|
|
+ )
|
|
|
+ })
|
|
|
|
|
|
- it('should run pandoc followed by zip in the conversion directory', function (ctx) {
|
|
|
- expect(ctx.CommandRunner.promises.run.callCount).toBe(2)
|
|
|
- expect(ctx.CommandRunner.promises.run.firstCall.args).toEqual([
|
|
|
- ctx.conversionId,
|
|
|
- [
|
|
|
- 'pandoc',
|
|
|
- 'input.docx',
|
|
|
- '--output',
|
|
|
- 'main.tex',
|
|
|
- '--extract-media=.',
|
|
|
- '--from',
|
|
|
- 'docx+citations',
|
|
|
- '--to',
|
|
|
- 'latex',
|
|
|
- '--citeproc',
|
|
|
- '--standalone',
|
|
|
- ],
|
|
|
- ctx.conversionDir,
|
|
|
- ctx.Settings.pandocImage,
|
|
|
- 60_000,
|
|
|
- {},
|
|
|
- 'conversions',
|
|
|
- ])
|
|
|
- expect(ctx.CommandRunner.promises.run.secondCall.args).toEqual([
|
|
|
- ctx.conversionId,
|
|
|
- ['zip', '-r', 'output-uuid.zip', '.'],
|
|
|
- ctx.conversionDir,
|
|
|
- ctx.Settings.pandocImage,
|
|
|
- 60_000,
|
|
|
- {},
|
|
|
- 'conversions',
|
|
|
- ])
|
|
|
+ it('should convert conversion timeout to milliseconds', async function (ctx) {
|
|
|
+ expect(ctx.CommandRunner.promises.run.firstCall.args[4]).toBe(60_000)
|
|
|
+ expect(ctx.CommandRunner.promises.run.secondCall.args[4]).toBe(60_000)
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should run pandoc with docx args followed by zip', function (ctx) {
|
|
|
+ expect(ctx.CommandRunner.promises.run.callCount).toBe(2)
|
|
|
+ expect(ctx.CommandRunner.promises.run.firstCall.args).toEqual([
|
|
|
+ ctx.conversionId,
|
|
|
+ [
|
|
|
+ 'pandoc',
|
|
|
+ 'input.docx',
|
|
|
+ '--output',
|
|
|
+ 'main.tex',
|
|
|
+ '--to',
|
|
|
+ 'latex',
|
|
|
+ '--standalone',
|
|
|
+ '--extract-media=.',
|
|
|
+ '--from',
|
|
|
+ 'docx+citations',
|
|
|
+ '--citeproc',
|
|
|
+ ],
|
|
|
+ ctx.conversionDir,
|
|
|
+ ctx.Settings.pandocImage,
|
|
|
+ 60_000,
|
|
|
+ {},
|
|
|
+ 'conversions',
|
|
|
+ ])
|
|
|
+ expect(ctx.CommandRunner.promises.run.secondCall.args).toEqual([
|
|
|
+ ctx.conversionId,
|
|
|
+ ['zip', '-r', 'output-uuid.zip', '.'],
|
|
|
+ ctx.conversionDir,
|
|
|
+ ctx.Settings.pandocImage,
|
|
|
+ 60_000,
|
|
|
+ {},
|
|
|
+ 'conversions',
|
|
|
+ ])
|
|
|
+ })
|
|
|
})
|
|
|
- })
|
|
|
|
|
|
- describe('successful conversion', function () {
|
|
|
- beforeEach(async function (ctx) {
|
|
|
- ctx.CommandRunner.promises.run.resolves({
|
|
|
- stdout: 'mock-stdout',
|
|
|
- stderr: 'mock-stderr',
|
|
|
- exitCode: 0,
|
|
|
+ describe('successful conversion', function () {
|
|
|
+ beforeEach(async function (ctx) {
|
|
|
+ ctx.CommandRunner.promises.run.resolves({
|
|
|
+ stdout: 'mock-stdout',
|
|
|
+ stderr: 'mock-stderr',
|
|
|
+ exitCode: 0,
|
|
|
+ })
|
|
|
+
|
|
|
+ ctx.result =
|
|
|
+ await ctx.ConversionManager.promises.convertToLaTeXWithLock(
|
|
|
+ ctx.conversionId,
|
|
|
+ ctx.inputPath,
|
|
|
+ 'docx'
|
|
|
+ )
|
|
|
})
|
|
|
|
|
|
- ctx.result =
|
|
|
- await ctx.ConversionManager.promises.convertDocxToLaTeXWithLock(
|
|
|
- ctx.conversionId,
|
|
|
- ctx.inputPath
|
|
|
+ it('should remove the source document after conversion', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(
|
|
|
+ ctx.fs.unlink,
|
|
|
+ Path.join(ctx.conversionDir, 'input.docx')
|
|
|
)
|
|
|
- })
|
|
|
+ })
|
|
|
|
|
|
- it('should remove the source document after conversion', async function (ctx) {
|
|
|
- sinon.assert.calledWith(
|
|
|
- ctx.fs.unlink,
|
|
|
- Path.join(ctx.conversionDir, 'input.docx')
|
|
|
- )
|
|
|
- })
|
|
|
+ it('should return the output zip path', function (ctx) {
|
|
|
+ expect(ctx.result).toBe(ctx.outputPath)
|
|
|
+ })
|
|
|
|
|
|
- it('should return the conversion directory', function (ctx) {
|
|
|
- expect(ctx.result).toBe(ctx.outputPath)
|
|
|
+ it('should release the lock', function (ctx) {
|
|
|
+ sinon.assert.called(ctx.lock.release)
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
- it('should release the lock', function (ctx) {
|
|
|
- sinon.assert.called(ctx.lock.release)
|
|
|
- })
|
|
|
- })
|
|
|
+ describe('unsuccessful conversion (exitcode)', function () {
|
|
|
+ beforeEach(async function (ctx) {
|
|
|
+ ctx.CommandRunner.promises.run.resolves({
|
|
|
+ stdout: 'mock-stdout',
|
|
|
+ stderr: 'mock-stderr',
|
|
|
+ exitCode: 63,
|
|
|
+ })
|
|
|
|
|
|
- describe('unsuccessful conversion (exitcode)', function () {
|
|
|
- beforeEach(async function (ctx) {
|
|
|
- ctx.CommandRunner.promises.run.resolves({
|
|
|
- stdout: 'mock-stdout',
|
|
|
- stderr: 'mock-stderr',
|
|
|
- exitCode: 63,
|
|
|
+ await expect(
|
|
|
+ ctx.ConversionManager.promises.convertToLaTeXWithLock(
|
|
|
+ ctx.conversionId,
|
|
|
+ ctx.inputPath,
|
|
|
+ 'docx'
|
|
|
+ )
|
|
|
+ ).to.be.rejectedWith('pandoc conversion failed')
|
|
|
})
|
|
|
|
|
|
- await expect(
|
|
|
- ctx.ConversionManager.promises.convertDocxToLaTeXWithLock(
|
|
|
- ctx.conversionId,
|
|
|
- ctx.inputPath
|
|
|
- )
|
|
|
- ).to.be.rejectedWith('pandoc conversion failed')
|
|
|
- })
|
|
|
+ it('should remove the entire conversion directory', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(ctx.fs.rm, ctx.conversionDir, {
|
|
|
+ force: true,
|
|
|
+ recursive: true,
|
|
|
+ })
|
|
|
+ })
|
|
|
|
|
|
- it('should remove the entire conversion directory', async function (ctx) {
|
|
|
- sinon.assert.calledWith(ctx.fs.rm, ctx.conversionDir, {
|
|
|
- force: true,
|
|
|
- recursive: true,
|
|
|
+ it('should release the lock', function (ctx) {
|
|
|
+ sinon.assert.called(ctx.lock.release)
|
|
|
})
|
|
|
})
|
|
|
|
|
|
- it('should release the lock', function (ctx) {
|
|
|
- sinon.assert.called(ctx.lock.release)
|
|
|
- })
|
|
|
- })
|
|
|
+ describe('unsuccessful compression (exitcode)', function () {
|
|
|
+ beforeEach(async function (ctx) {
|
|
|
+ ctx.CommandRunner.promises.run
|
|
|
+ .onFirstCall()
|
|
|
+ .resolves({
|
|
|
+ stdout: 'mock-pandoc-stdout',
|
|
|
+ stderr: 'mock-pandoc-stderr',
|
|
|
+ exitCode: 0,
|
|
|
+ })
|
|
|
+ .onSecondCall()
|
|
|
+ .resolves({
|
|
|
+ stdout: 'mock-zip-stdout',
|
|
|
+ stderr: 'mock-zip-stderr',
|
|
|
+ exitCode: 12,
|
|
|
+ })
|
|
|
+
|
|
|
+ await expect(
|
|
|
+ ctx.ConversionManager.promises.convertToLaTeXWithLock(
|
|
|
+ ctx.conversionId,
|
|
|
+ ctx.inputPath,
|
|
|
+ 'docx'
|
|
|
+ )
|
|
|
+ ).to.be.rejectedWith('pandoc conversion failed')
|
|
|
+ })
|
|
|
|
|
|
- describe('unsuccessful compression (exitcode)', function () {
|
|
|
- beforeEach(async function (ctx) {
|
|
|
- ctx.CommandRunner.promises.run
|
|
|
- .onFirstCall()
|
|
|
- .resolves({
|
|
|
- stdout: 'mock-pandoc-stdout',
|
|
|
- stderr: 'mock-pandoc-stderr',
|
|
|
- exitCode: 0,
|
|
|
- })
|
|
|
- .onSecondCall()
|
|
|
- .resolves({
|
|
|
- stdout: 'mock-zip-stdout',
|
|
|
- stderr: 'mock-zip-stderr',
|
|
|
- exitCode: 12,
|
|
|
+ it('should remove the entire conversion directory', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(ctx.fs.rm, ctx.conversionDir, {
|
|
|
+ force: true,
|
|
|
+ recursive: true,
|
|
|
})
|
|
|
+ })
|
|
|
|
|
|
- await expect(
|
|
|
- ctx.ConversionManager.promises.convertDocxToLaTeXWithLock(
|
|
|
- ctx.conversionId,
|
|
|
- ctx.inputPath
|
|
|
- )
|
|
|
- ).to.be.rejectedWith('pandoc conversion failed')
|
|
|
+ it('should release the lock', function (ctx) {
|
|
|
+ sinon.assert.called(ctx.lock.release)
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
- it('should remove the entire conversion directory', async function (ctx) {
|
|
|
- sinon.assert.calledWith(ctx.fs.rm, ctx.conversionDir, {
|
|
|
- force: true,
|
|
|
- recursive: true,
|
|
|
+ describe('unsuccessful conversion (throws)', function () {
|
|
|
+ beforeEach(async function (ctx) {
|
|
|
+ ctx.CommandRunner.promises.run.rejects(
|
|
|
+ new Error('mock conversion error')
|
|
|
+ )
|
|
|
+ await expect(
|
|
|
+ ctx.ConversionManager.promises.convertToLaTeXWithLock(
|
|
|
+ ctx.conversionId,
|
|
|
+ ctx.inputPath,
|
|
|
+ 'docx'
|
|
|
+ )
|
|
|
+ ).to.be.rejectedWith('pandoc conversion failed')
|
|
|
})
|
|
|
- })
|
|
|
|
|
|
- it('should release the lock', function (ctx) {
|
|
|
- sinon.assert.called(ctx.lock.release)
|
|
|
+ it('should remove the entire conversion directory', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(ctx.fs.rm, ctx.conversionDir, {
|
|
|
+ force: true,
|
|
|
+ recursive: true,
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should release the lock', function (ctx) {
|
|
|
+ sinon.assert.called(ctx.lock.release)
|
|
|
+ })
|
|
|
})
|
|
|
})
|
|
|
|
|
|
- describe('unsuccessful conversion (throws)', function () {
|
|
|
- beforeEach(async function (ctx) {
|
|
|
- ctx.CommandRunner.promises.run.rejects(
|
|
|
- new Error('mock conversion error')
|
|
|
- )
|
|
|
- await expect(
|
|
|
- ctx.ConversionManager.promises.convertDocxToLaTeXWithLock(
|
|
|
- ctx.conversionId,
|
|
|
- ctx.inputPath
|
|
|
- )
|
|
|
- ).to.be.rejectedWith('pandoc conversion failed')
|
|
|
+ describe('with conversionType=markdown', function () {
|
|
|
+ beforeEach(function (ctx) {
|
|
|
+ ctx.inputPath = '/path/to/input.md'
|
|
|
})
|
|
|
|
|
|
- it('should remove the entire conversion directory', async function (ctx) {
|
|
|
- sinon.assert.calledWith(ctx.fs.rm, ctx.conversionDir, {
|
|
|
- force: true,
|
|
|
- recursive: true,
|
|
|
+ describe('file setup and pandoc args', function () {
|
|
|
+ beforeEach(async function (ctx) {
|
|
|
+ ctx.result =
|
|
|
+ await ctx.ConversionManager.promises.convertToLaTeXWithLock(
|
|
|
+ ctx.conversionId,
|
|
|
+ ctx.inputPath,
|
|
|
+ 'markdown'
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should copy the input file to the conversion directory with md filename', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(ctx.fs.mkdir, ctx.conversionDir, {
|
|
|
+ recursive: true,
|
|
|
+ })
|
|
|
+ sinon.assert.calledWith(
|
|
|
+ ctx.fs.copyFile,
|
|
|
+ ctx.inputPath,
|
|
|
+ Path.join(ctx.conversionDir, 'input.md')
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should run pandoc with markdown args followed by zip', function (ctx) {
|
|
|
+ expect(ctx.CommandRunner.promises.run.callCount).toBe(2)
|
|
|
+ expect(ctx.CommandRunner.promises.run.firstCall.args).toEqual([
|
|
|
+ ctx.conversionId,
|
|
|
+ [
|
|
|
+ 'pandoc',
|
|
|
+ 'input.md',
|
|
|
+ '--output',
|
|
|
+ 'main.tex',
|
|
|
+ '--to',
|
|
|
+ 'latex',
|
|
|
+ '--standalone',
|
|
|
+ '--from',
|
|
|
+ 'markdown',
|
|
|
+ ],
|
|
|
+ ctx.conversionDir,
|
|
|
+ ctx.Settings.pandocImage,
|
|
|
+ 60_000,
|
|
|
+ {},
|
|
|
+ 'conversions',
|
|
|
+ ])
|
|
|
+ expect(ctx.CommandRunner.promises.run.secondCall.args).toEqual([
|
|
|
+ ctx.conversionId,
|
|
|
+ ['zip', '-r', 'output-uuid.zip', '.'],
|
|
|
+ ctx.conversionDir,
|
|
|
+ ctx.Settings.pandocImage,
|
|
|
+ 60_000,
|
|
|
+ {},
|
|
|
+ 'conversions',
|
|
|
+ ])
|
|
|
})
|
|
|
})
|
|
|
|
|
|
- it('should release the lock', function (ctx) {
|
|
|
- sinon.assert.called(ctx.lock.release)
|
|
|
+ describe('successful conversion', function () {
|
|
|
+ beforeEach(async function (ctx) {
|
|
|
+ ctx.CommandRunner.promises.run.resolves({
|
|
|
+ stdout: 'mock-stdout',
|
|
|
+ stderr: 'mock-stderr',
|
|
|
+ exitCode: 0,
|
|
|
+ })
|
|
|
+
|
|
|
+ ctx.result =
|
|
|
+ await ctx.ConversionManager.promises.convertToLaTeXWithLock(
|
|
|
+ ctx.conversionId,
|
|
|
+ ctx.inputPath,
|
|
|
+ 'markdown'
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should remove the source document after conversion', async function (ctx) {
|
|
|
+ sinon.assert.calledWith(
|
|
|
+ ctx.fs.unlink,
|
|
|
+ Path.join(ctx.conversionDir, 'input.md')
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
+ it('should return the output zip path', function (ctx) {
|
|
|
+ expect(ctx.result).toBe(ctx.outputPath)
|
|
|
+ })
|
|
|
})
|
|
|
})
|
|
|
})
|