-
-
Notifications
You must be signed in to change notification settings - Fork 226
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
196 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const Command = require('../command'); | ||
|
||
class ExportCommand extends Command { | ||
async run(argv) { | ||
const {exportTask} = require('../tasks/import'); | ||
const {SystemError} = require('../errors'); | ||
|
||
const instance = this.system.getInstance(); | ||
const isRunning = await instance.isRunning(); | ||
|
||
if (!isRunning) { | ||
const shouldStart = await this.ui.confirm('Ghost instance is not currently running. Would you like to start it?', true); | ||
|
||
if (!shouldStart) { | ||
throw new SystemError('Ghost instance is not currently running'); | ||
} | ||
|
||
instance.checkEnvironment(); | ||
await this.ui.run(() => instance.start(), 'Starting Ghost'); | ||
} | ||
|
||
await this.ui.run(() => exportTask(this.ui, instance, argv.file), 'Exporting content'); | ||
this.ui.log(`Content exported to ${argv.file}`, 'green'); | ||
} | ||
} | ||
|
||
ExportCommand.description = 'Export content from a blog'; | ||
ExportCommand.params = '[file]'; | ||
|
||
module.exports = ExportCommand; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
const {importTask} = require('./tasks'); | ||
const {importTask, exportTask} = require('./tasks'); | ||
const parseExport = require('./parse-export'); | ||
|
||
module.exports = { | ||
importTask, | ||
exportTask, | ||
parseExport | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const {expect} = require('chai'); | ||
const sinon = require('sinon'); | ||
const proxyquire = require('proxyquire').noCallThru(); | ||
|
||
const {SystemError} = require('../../../lib/errors'); | ||
|
||
describe('Unit: Commands > import', function () { | ||
it('throws error if importing a 0.x import into a > 1.x blog', async function () { | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,92 +4,140 @@ const proxyquire = require('proxyquire').noCallThru(); | |
const Promise = require('bluebird'); | ||
const createConfigStub = require('../../../utils/config-stub'); | ||
|
||
const {SystemError} = require('../../../../lib/errors'); | ||
|
||
const modulePath = '../../../../lib/tasks/import/tasks'; | ||
|
||
describe('Unit: Tasks > Import > Import task', function () { | ||
it('works with already set up blog', async function () { | ||
const parseExport = sinon.stub().returns({data: {name: 'test', email: '[email protected]', blogTitle: 'test'}}); | ||
const isSetup = sinon.stub().resolves(true); | ||
const setup = sinon.stub().resolves(); | ||
const runImport = sinon.stub().resolves(); | ||
describe('Unit: Tasks > Import > Tasks', function () { | ||
describe('importTask', function () { | ||
it('works with already set up blog', async function () { | ||
const parseExport = sinon.stub().returns({data: {name: 'test', email: '[email protected]', blogTitle: 'test'}}); | ||
const isSetup = sinon.stub().resolves(true); | ||
const setup = sinon.stub().resolves(); | ||
const runImport = sinon.stub().resolves(); | ||
|
||
const {importTask} = proxyquire(modulePath, { | ||
'./parse-export': parseExport, | ||
'./api': {isSetup, setup, runImport} | ||
}); | ||
|
||
const prompt = sinon.stub().resolves({username: '[email protected]', password: '1234567890'}); | ||
const listr = sinon.stub().callsFake(tasks => Promise.each(tasks, async (t) => { | ||
if (t.enabled && !t.enabled()) { | ||
return; | ||
} | ||
|
||
await t.task(); | ||
})); | ||
const config = createConfigStub(); | ||
config.get.withArgs('url').returns('http://localhost:2368'); | ||
|
||
await importTask({prompt, listr}, {config, version: '1.0.0'}, 'test-export.json'); | ||
|
||
expect(parseExport.calledOnceWithExactly('test-export.json')).to.be.true; | ||
expect(isSetup.calledOnceWithExactly('1.0.0', 'http://localhost:2368')).to.be.true; | ||
expect(prompt.calledOnce).to.be.true; | ||
expect(prompt.args[0][0]).to.have.length(2); | ||
|
||
const usernamePrompt = prompt.args[0][0][0]; | ||
const passwordPrompt = prompt.args[0][0][1]; | ||
|
||
expect(usernamePrompt.validate('[email protected]')).to.be.true; | ||
expect(usernamePrompt.validate('not an email')).to.include('valid email'); | ||
expect(passwordPrompt.validate('1234567890')).to.be.true; | ||
expect(passwordPrompt.validate('short')).to.include('10 characters long'); | ||
|
||
expect(listr.calledOnce).to.be.true; | ||
expect(setup.called).to.be.false; | ||
expect(runImport.calledOnceWithExactly('1.0.0', 'http://localhost:2368', { | ||
username: '[email protected]', | ||
password: '1234567890' | ||
}, 'test-export.json')).to.be.true; | ||
}); | ||
|
||
const {importTask} = proxyquire(modulePath, { | ||
'./parse-export': parseExport, | ||
'./api': {isSetup, setup, runImport} | ||
it('works with not setup blog', async function () { | ||
const parseExport = sinon.stub().returns({data: {name: 'test', email: '[email protected]', blogTitle: 'test'}}); | ||
const isSetup = sinon.stub().resolves(false); | ||
const setup = sinon.stub().resolves(); | ||
const runImport = sinon.stub().resolves(); | ||
|
||
const {importTask} = proxyquire(modulePath, { | ||
'./parse-export': parseExport, | ||
'./api': {isSetup, setup, runImport} | ||
}); | ||
|
||
const prompt = sinon.stub().resolves({password: '1234567890'}); | ||
const listr = sinon.stub().callsFake(tasks => Promise.each(tasks, async (t) => { | ||
if (t.enabled && !t.enabled()) { | ||
return; | ||
} | ||
|
||
await t.task(); | ||
})); | ||
const config = createConfigStub(); | ||
config.get.withArgs('url').returns('http://localhost:2368'); | ||
|
||
await importTask({prompt, listr}, {config, version: '1.0.0'}, 'test-export.json'); | ||
|
||
expect(parseExport.calledOnceWithExactly('test-export.json')).to.be.true; | ||
expect(isSetup.calledOnceWithExactly('1.0.0', 'http://localhost:2368')).to.be.true; | ||
expect(prompt.calledOnce).to.be.true; | ||
expect(prompt.args[0][0]).to.have.length(1); | ||
expect(listr.calledOnce).to.be.true; | ||
expect(setup.calledOnceWithExactly('1.0.0', 'http://localhost:2368', { | ||
name: 'test', | ||
email: '[email protected]', | ||
blogTitle: 'test', | ||
password: '1234567890' | ||
})).to.be.true; | ||
expect(runImport.calledOnceWithExactly('1.0.0', 'http://localhost:2368', { | ||
username: '[email protected]', | ||
password: '1234567890' | ||
}, 'test-export.json')).to.be.true; | ||
}); | ||
}); | ||
|
||
const prompt = sinon.stub().resolves({username: '[email protected]', password: '1234567890'}); | ||
const listr = sinon.stub().callsFake(tasks => Promise.each(tasks, async (t) => { | ||
if (t.enabled && !t.enabled()) { | ||
return; | ||
} | ||
describe('exportTask', function () { | ||
it('throws error for not set up blog', async function () { | ||
const isSetup = sinon.stub().resolves(false); | ||
const config = createConfigStub(); | ||
|
||
await t.task(); | ||
})); | ||
const config = createConfigStub(); | ||
config.get.withArgs('url').returns('http://localhost:2368'); | ||
config.get.withArgs('url').returns('http://localhost:2368'); | ||
|
||
await importTask({prompt, listr}, {config, version: '1.0.0'}, 'test-export.json'); | ||
const {exportTask} = proxyquire(modulePath, { | ||
'./api': {isSetup} | ||
}); | ||
|
||
expect(parseExport.calledOnceWithExactly('test-export.json')).to.be.true; | ||
expect(isSetup.calledOnceWithExactly('1.0.0', 'http://localhost:2368')).to.be.true; | ||
expect(prompt.calledOnce).to.be.true; | ||
expect(prompt.args[0][0]).to.have.length(2); | ||
try { | ||
await exportTask({}, {config, version: '1.0.0'}, 'test-export.json'); | ||
} catch (error) { | ||
expect(error).to.be.an.instanceof(SystemError); | ||
expect(error.message).to.include('Cannot export content'); | ||
expect(isSetup.calledOnceWithExactly('1.0.0', 'http://localhost:2368')).to.be.true; | ||
return; | ||
} | ||
|
||
const usernamePrompt = prompt.args[0][0][0]; | ||
const passwordPrompt = prompt.args[0][0][1]; | ||
expect.fail('exportTask should have errored'); | ||
}); | ||
|
||
expect(usernamePrompt.validate('[email protected]')).to.be.true; | ||
expect(usernamePrompt.validate('not an email')).to.include('valid email'); | ||
expect(passwordPrompt.validate('1234567890')).to.be.true; | ||
expect(passwordPrompt.validate('short')).to.include('10 characters long'); | ||
it('exports content', async function () { | ||
const isSetup = sinon.stub().resolves(true); | ||
const downloadExport = sinon.stub().resolves(); | ||
const config = createConfigStub(); | ||
const prompt = sinon.stub().resolves({username: 'username', password: 'password'}); | ||
|
||
expect(listr.calledOnce).to.be.true; | ||
expect(setup.called).to.be.false; | ||
expect(runImport.calledOnceWithExactly('1.0.0', 'http://localhost:2368', { | ||
username: '[email protected]', | ||
password: '1234567890' | ||
}, 'test-export.json')).to.be.true; | ||
}); | ||
config.get.withArgs('url').returns('http://localhost:2368'); | ||
|
||
it('works with not setup blog', async function () { | ||
const parseExport = sinon.stub().returns({data: {name: 'test', email: '[email protected]', blogTitle: 'test'}}); | ||
const isSetup = sinon.stub().resolves(false); | ||
const setup = sinon.stub().resolves(); | ||
const runImport = sinon.stub().resolves(); | ||
const {exportTask} = proxyquire(modulePath, { | ||
'./api': {isSetup, downloadExport} | ||
}); | ||
|
||
const {importTask} = proxyquire(modulePath, { | ||
'./parse-export': parseExport, | ||
'./api': {isSetup, setup, runImport} | ||
await exportTask({prompt}, {config, version: '1.0.0'}, 'test-export.json'); | ||
expect(isSetup.calledOnceWithExactly('1.0.0', 'http://localhost:2368')).to.be.true; | ||
expect(prompt.calledOnce).to.be.true; | ||
expect(downloadExport.calledOnceWithExactly('1.0.0', 'http://localhost:2368', { | ||
username: 'username', password: 'password' | ||
}, 'test-export.json')); | ||
}); | ||
|
||
const prompt = sinon.stub().resolves({password: '1234567890'}); | ||
const listr = sinon.stub().callsFake(tasks => Promise.each(tasks, async (t) => { | ||
if (t.enabled && !t.enabled()) { | ||
return; | ||
} | ||
|
||
await t.task(); | ||
})); | ||
const config = createConfigStub(); | ||
config.get.withArgs('url').returns('http://localhost:2368'); | ||
|
||
await importTask({prompt, listr}, {config, version: '1.0.0'}, 'test-export.json'); | ||
|
||
expect(parseExport.calledOnceWithExactly('test-export.json')).to.be.true; | ||
expect(isSetup.calledOnceWithExactly('1.0.0', 'http://localhost:2368')).to.be.true; | ||
expect(prompt.calledOnce).to.be.true; | ||
expect(prompt.args[0][0]).to.have.length(1); | ||
expect(listr.calledOnce).to.be.true; | ||
expect(setup.calledOnceWithExactly('1.0.0', 'http://localhost:2368', { | ||
name: 'test', | ||
email: '[email protected]', | ||
blogTitle: 'test', | ||
password: '1234567890' | ||
})).to.be.true; | ||
expect(runImport.calledOnceWithExactly('1.0.0', 'http://localhost:2368', { | ||
username: '[email protected]', | ||
password: '1234567890' | ||
}, 'test-export.json')).to.be.true; | ||
}); | ||
}); |