diff --git a/test/scripts/console/generate.js b/test/scripts/console/generate.js index 4755e87a00..89ea10d038 100644 --- a/test/scripts/console/generate.js +++ b/test/scripts/console/generate.js @@ -1,143 +1,180 @@ 'use strict'; -const pathFn = require('path'); -const fs = require('hexo-fs'); +const { join } = require('path'); +const { emptyDir, exists, mkdirs, readFile, rmdir, stat, unlink, writeFile } = require('hexo-fs'); const Promise = require('bluebird'); -const sinon = require('sinon'); +const { spy } = require('sinon'); describe('generate', () => { const Hexo = require('../../../lib/hexo'); const generateConsole = require('../../../lib/plugins/console/generate'); let hexo, generate; - beforeEach(() => { - hexo = new Hexo(pathFn.join(__dirname, 'generate_test'), {silent: true}); + beforeEach(async () => { + hexo = new Hexo(join(__dirname, 'generate_test'), {silent: true}); generate = generateConsole.bind(hexo); - return fs.mkdirs(hexo.base_dir).then(() => hexo.init()); + await mkdirs(hexo.base_dir); + hexo.init(); }); - afterEach(() => fs.rmdir(hexo.base_dir)); - - function testGenerate(options) { + afterEach(async () => { + const exist = await exists(hexo.base_dir); + if (exist) { + await emptyDir(hexo.base_dir); + await rmdir(hexo.base_dir); + } + }); - return Promise.all([ + const testGenerate = async options => { + await Promise.all([ // Add some source files - fs.writeFile(pathFn.join(hexo.source_dir, 'test.txt'), 'test'), - fs.writeFile(pathFn.join(hexo.source_dir, 'faz', 'yo.txt'), 'yoooo'), + writeFile(join(hexo.source_dir, 'test.txt'), 'test'), + writeFile(join(hexo.source_dir, 'faz', 'yo.txt'), 'yoooo'), // Add some files to public folder - fs.writeFile(pathFn.join(hexo.public_dir, 'foo.txt'), 'foo'), - fs.writeFile(pathFn.join(hexo.public_dir, 'bar', 'boo.txt'), 'boo'), - fs.writeFile(pathFn.join(hexo.public_dir, 'faz', 'yo.txt'), 'yo') - ]).then(() => generate(options)).then(() => Promise.all([ - fs.readFile(pathFn.join(hexo.public_dir, 'test.txt')), - fs.readFile(pathFn.join(hexo.public_dir, 'faz', 'yo.txt')), - fs.exists(pathFn.join(hexo.public_dir, 'foo.txt')), - fs.exists(pathFn.join(hexo.public_dir, 'bar', 'boo.txt')) - ])).then(result => { - // Check the new file - result[0].should.eql('test'); - - // Check the updated file - result[1].should.eql('yoooo'); - - // Old files should not be deleted - result[2].should.be.true; - result[3].should.be.true; - }); - } + writeFile(join(hexo.public_dir, 'foo.txt'), 'foo'), + writeFile(join(hexo.public_dir, 'bar', 'boo.txt'), 'boo'), + writeFile(join(hexo.public_dir, 'faz', 'yo.txt'), 'yo') + ]); + await generate(options); + + const result = await Promise.all([ + readFile(join(hexo.public_dir, 'test.txt')), + readFile(join(hexo.public_dir, 'faz', 'yo.txt')), + exists(join(hexo.public_dir, 'foo.txt')), + exists(join(hexo.public_dir, 'bar', 'boo.txt')) + ]); + // Check the new file + result[0].should.eql('test'); + // Check the updated file + result[1].should.eql('yoooo'); + // Old files should not be deleted + result[2].should.eql(true); + result[3].should.eql(true); + }; it('default', () => testGenerate()); - it('write file if not exist', () => { - const src = pathFn.join(hexo.source_dir, 'test.txt'); - const dest = pathFn.join(hexo.public_dir, 'test.txt'); + it('write file if not exist', async () => { + const src = join(hexo.source_dir, 'test.txt'); + const dest = join(hexo.public_dir, 'test.txt'); const content = 'test'; // Add some source files - return fs.writeFile(src, content).then(() => // First generation - generate()).then(() => // Delete generated files - fs.unlink(dest)).then(() => // Second generation - generate()).then(() => fs.readFile(dest)).then(result => { - result.should.eql(content); - - // Remove source files and generated files - return Promise.all([ - fs.unlink(src), - fs.unlink(dest) - ]); - }); + await writeFile(src, content); + + // First generation + await generate(); + + // Delete generated files + await unlink(dest); + + // Second generation + await generate(); + + const result = await readFile(dest); + + result.should.eql(content); + + // Remove source files and generated files + await Promise.all([ + unlink(src), + unlink(dest) + ]); }); - it('don\'t write if file unchanged', () => { - const src = pathFn.join(hexo.source_dir, 'test.txt'); - const dest = pathFn.join(hexo.public_dir, 'test.txt'); + it('don\'t write if file unchanged', async () => { + const src = join(hexo.source_dir, 'test.txt'); + const dest = join(hexo.public_dir, 'test.txt'); const content = 'test'; const newContent = 'newtest'; // Add some source files - return fs.writeFile(src, content).then(() => // First generation - generate()).then(() => // Change the generated file - fs.writeFile(dest, newContent)).then(() => // Second generation - generate()).then(() => // Read the generated file - fs.readFile(dest)).then(result => { - // Make sure the generated file didn't changed - result.should.eql(newContent); - - // Remove source files and generated files - return Promise.all([ - fs.unlink(src), - fs.unlink(dest) - ]); - }); + await writeFile(src, content); + + // First generation + await generate(); + + // Change the generated file + await writeFile(dest, newContent); + + // Second generation + await generate(); + + // Read the generated file + const result = await readFile(dest); + + // Make sure the generated file didn't change + result.should.eql(newContent); + + // Remove source files and generated files + await Promise.all([ + unlink(src), + unlink(dest) + ]); }); - it('force regenerate', () => { - const src = pathFn.join(hexo.source_dir, 'test.txt'); - const dest = pathFn.join(hexo.public_dir, 'test.txt'); + it('force regenerate', async () => { + const src = join(hexo.source_dir, 'test.txt'); + const dest = join(hexo.public_dir, 'test.txt'); const content = 'test'; - let mtime; - - return fs.writeFile(src, content).then(() => // First generation - generate()).then(() => // Read file status - fs.stat(dest)).then(stats => { - mtime = stats.mtime.getTime(); - }).delay(1000).then(() => // Force regenerate - generate({force: true})).then(() => fs.stat(dest)).then(stats => { - stats.mtime.getTime().should.be.above(mtime); - - // Remove source files and generated files - return Promise.all([ - fs.unlink(src), - fs.unlink(dest) - ]); - }); + + await writeFile(src, content); + + // First generation + await generate(); + + // Read file status + let stats = await stat(dest); + const mtime = stats.mtime.getTime(); + + await Promise.delay(1000); + + // Force regenerate + await generate({ force: true }); + stats = await stat(dest); + + stats.mtime.getTime().should.above(mtime); + + // Remove source files and generated files + await Promise.all([ + unlink(src), + unlink(dest) + ]); }); - it('watch - update', () => { - const src = pathFn.join(hexo.source_dir, 'test.txt'); - const dest = pathFn.join(hexo.public_dir, 'test.txt'); + it('watch - update', async () => { + const src = join(hexo.source_dir, 'test.txt'); + const dest = join(hexo.public_dir, 'test.txt'); const content = 'test'; - return testGenerate({watch: true}).then(() => // Update the file - fs.writeFile(src, content)).delay(300).then(() => fs.readFile(dest)).then(result => { - // Check the updated file - result.should.eql(content); - }).finally(() => { - // Stop watching - hexo.unwatch(); - }); - }); + await testGenerate({ watch: true }); + + // Update the file + await writeFile(src, content); + + await Promise.delay(300); + + // Check the updated file + const result = await readFile(dest); + result.should.eql(content); - it('watch - delete', () => testGenerate({watch: true}).then(() => fs.unlink(pathFn.join(hexo.source_dir, 'test.txt'))).delay(300).then(() => fs.exists(pathFn.join(hexo.public_dir, 'test.txt'))).then(exist => { - exist.should.be.false; - }).finally(() => { // Stop watching - hexo.unwatch(); - })); + await hexo.unwatch(); + }); - it('deploy', () => { - const deployer = sinon.spy(); + it('watch - delete', async () => { + await testGenerate({ watch: true }); + + await unlink(join(hexo.source_dir, 'test.txt')); + await Promise.delay(300); + + const exist = await exists(join(hexo.public_dir, 'test.txt')); + exist.should.eql(false); + }); + + it('deploy', async () => { + const deployer = spy(); hexo.extend.deployer.register('test', deployer); @@ -145,31 +182,41 @@ describe('generate', () => { type: 'test' }; - return generate({deploy: true}).then(() => { - deployer.calledOnce.should.be.true; - }); + await generate({ deploy: true }); + + deployer.calledOnce.should.eql(true); }); - it('update theme source files', () => Promise.all([ + it('update theme source files', async () => { // Add some source files - fs.writeFile(pathFn.join(hexo.theme_dir, 'source', 'a.txt'), 'a'), - fs.writeFile(pathFn.join(hexo.theme_dir, 'source', 'b.txt'), 'b'), - fs.writeFile(pathFn.join(hexo.theme_dir, 'source', 'c.swig'), 'c') - ]).then(() => generate()).then(() => // Update source file - Promise.all([ - fs.writeFile(pathFn.join(hexo.theme_dir, 'source', 'b.txt'), 'bb'), - fs.writeFile(pathFn.join(hexo.theme_dir, 'source', 'c.swig'), 'cc') - ])).then(() => // Generate again - generate()).then(() => // Read the updated source file - Promise.all([ - fs.readFile(pathFn.join(hexo.public_dir, 'b.txt')), - fs.readFile(pathFn.join(hexo.public_dir, 'c.html')) - ])).then(result => { + await Promise.all([ + // Add some source files + writeFile(join(hexo.theme_dir, 'source', 'a.txt'), 'a'), + writeFile(join(hexo.theme_dir, 'source', 'b.txt'), 'b'), + writeFile(join(hexo.theme_dir, 'source', 'c.swig'), 'c') + ]); + await generate(); + + // Update source file + await Promise.all([ + writeFile(join(hexo.theme_dir, 'source', 'b.txt'), 'bb'), + writeFile(join(hexo.theme_dir, 'source', 'c.swig'), 'cc') + ]); + + // Generate again + await generate(); + + // Read the updated source file + const result = await Promise.all([ + readFile(join(hexo.public_dir, 'b.txt')), + readFile(join(hexo.public_dir, 'c.html')) + ]); + result[0].should.eql('bb'); result[1].should.eql('cc'); - })); + }); - it('proceeds after error when bail option is not set', () => { + it('proceeds after error when bail option is not set', async () => { hexo.extend.renderer.register('err', 'html', () => Promise.reject(new Error('Testing unhandled exception'))); hexo.extend.generator.register('test_page', () => [ @@ -181,14 +228,13 @@ describe('generate', () => { ] ); - return Promise.all([ - fs.writeFile(pathFn.join(hexo.theme_dir, 'layout', 'post.err'), 'post') - ]).then(() => { - return generate(); - }); + await Promise.all([ + writeFile(join(hexo.theme_dir, 'layout', 'post.err'), 'post') + ]); + return generate(); }); - it('proceeds after error when bail option is set to false', () => { + it('proceeds after error when bail option is set to false', async () => { hexo.extend.renderer.register('err', 'html', () => Promise.reject(new Error('Testing unhandled exception'))); hexo.extend.generator.register('test_page', () => [ @@ -200,14 +246,13 @@ describe('generate', () => { ] ); - return Promise.all([ - fs.writeFile(pathFn.join(hexo.theme_dir, 'layout', 'post.err'), 'post') - ]).then(() => { - return generate({bail: false}); - }); + await Promise.all([ + writeFile(join(hexo.theme_dir, 'layout', 'post.err'), 'post') + ]); + return generate({ bail: false }); }); - it('breaks after error when bail option is set to true', () => { + it('breaks after error when bail option is set to true', async () => { hexo.extend.renderer.register('err', 'html', () => Promise.reject(new Error('Testing unhandled exception'))); hexo.extend.generator.register('test_page', () => [ @@ -219,20 +264,21 @@ describe('generate', () => { ] ); - const errorCallback = sinon.spy(err => { + const errorCallback = spy(err => { err.should.have.property('message', 'Testing unhandled exception'); }); - return Promise.all([ - fs.writeFile(pathFn.join(hexo.theme_dir, 'layout', 'post.err'), 'post') - ]).then(() => { - return generate({bail: true}).catch(errorCallback).finally(() => { - errorCallback.calledOnce.should.be.true; - }); + await Promise.all([ + writeFile(join(hexo.theme_dir, 'layout', 'post.err'), 'post') + ]); + + return generate({ bail: true }).catch(errorCallback).finally(() => { + errorCallback.calledOnce.should.be.true; }); }); - it('should generate all files even when concurrency is set', () => { - return generate({ concurrency: 1 }).then(() => generate({ concurrency: 2 })); + it('should generate all files even when concurrency is set', async () => { + await generate({ concurrency: 1 }); + return generate({ concurrency: 2 }); }); });