You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
285 lines
8.6 KiB
285 lines
8.6 KiB
import * as retry from 'bluebird-retry'; |
|
import { |
|
expect, |
|
use as chaiUse |
|
} from 'chai'; |
|
import * as fs from 'fs-extra'; |
|
import * as os from 'os'; |
|
import * as path from 'path'; |
|
import * as sinon from 'sinon'; |
|
import * as sinonChai from 'sinon-chai'; |
|
|
|
import { |
|
commands, |
|
TextEditor, |
|
Uri, |
|
window, |
|
workspace |
|
} from 'vscode'; |
|
|
|
import { |
|
controller, |
|
newJekyllFile |
|
} from '../../src/extension/commands'; |
|
|
|
chaiUse(sinonChai); |
|
|
|
const rootDir = path.resolve(__dirname, '..', '..', '..'); |
|
const tmpDir = path.resolve(os.tmpdir(), 'vscode-fileutils-test--new-file'); |
|
|
|
const fixtureFile1 = path.resolve(rootDir, 'test', 'fixtures', 'file-1.rb'); |
|
const fixtureFile2 = path.resolve(rootDir, 'test', 'fixtures', 'file-2.rb'); |
|
|
|
const editorFile1 = path.resolve(tmpDir, 'nested-dir-1', 'nested-dir-2', 'file-1.rb'); |
|
const editorFile2 = path.resolve(tmpDir, 'file-2.rb'); |
|
|
|
const targetFile = path.resolve(`${editorFile1}.tmp`); |
|
|
|
describe('newJekyllFile', () => { |
|
|
|
beforeEach(() => Promise.all([ |
|
fs.remove(tmpDir), |
|
fs.copy(fixtureFile1, editorFile1), |
|
fs.copy(fixtureFile2, editorFile2) |
|
])); |
|
|
|
afterEach(() => fs.remove(tmpDir)); |
|
|
|
describe('with open text document', () => { |
|
|
|
beforeEach(() => { |
|
|
|
const openDocument = () => { |
|
const uri = Uri.file(editorFile1); |
|
return workspace.openTextDocument(uri) |
|
.then((textDocument) => window.showTextDocument(textDocument)); |
|
}; |
|
|
|
const stubShowInputBox = () => { |
|
const fileName = path.basename(targetFile); |
|
sinon.stub(window, 'showInputBox').returns(Promise.resolve(fileName)); |
|
return Promise.resolve(); |
|
}; |
|
|
|
return Promise.all([ |
|
retry(() => openDocument(), { max_tries: 4, interval: 500 }), |
|
stubShowInputBox() |
|
]); |
|
}); |
|
|
|
afterEach(() => { |
|
|
|
const closeAllEditors = () => { |
|
return commands.executeCommand('workbench.action.closeAllEditors'); |
|
}; |
|
|
|
const restoreShowInputBox = () => { |
|
const stub: any = window.showInputBox; |
|
return Promise.resolve(stub.restore()); |
|
}; |
|
|
|
return Promise.all([ |
|
closeAllEditors(), |
|
restoreShowInputBox() |
|
]); |
|
}); |
|
|
|
it('prompts for file destination', () => { |
|
|
|
return newJekyllFile().then(() => { |
|
|
|
const delim: string = '-'; |
|
const ending: string = 'xxxxx.md'; |
|
const date: Date = new Date(); |
|
let monthDay: string = date.getDate().toString(); // Get the day as a number (1-31) |
|
let month: number = date.getMonth(); // Get the month as a number (0-11) 2018-05-05-xxxxx.md |
|
const fullYear: string = date.getFullYear().toString(); |
|
|
|
if (monthDay.length === 1) { |
|
monthDay = '0'.concat(monthDay); |
|
} |
|
|
|
month++; |
|
let monthStr: string = month.toString(); |
|
|
|
if (monthStr.length === 1) { |
|
monthStr = '0'.concat(monthStr); |
|
} |
|
|
|
const outputStr: string = fullYear.concat(delim, monthStr, delim, monthDay, delim, ending); |
|
|
|
const prompt = { value: outputStr, valueSelection: [11, 16] }; |
|
expect(window.showInputBox).to.have.been.calledWithExactly(prompt); |
|
}); |
|
|
|
}); |
|
|
|
it('create file at destination', () => { |
|
|
|
return newJekyllFile().then(() => { |
|
const message = `${targetFile} does not exist`; |
|
// tslint:disable-next-line:no-unused-expression |
|
expect(fs.existsSync(targetFile), message).to.be.true; |
|
}); |
|
}); |
|
|
|
it('opens new file as active editor', () => { |
|
|
|
return newJekyllFile().then(() => { |
|
const activeEditor: TextEditor = window.activeTextEditor; |
|
expect(activeEditor.document.fileName).to.equal(targetFile); |
|
}); |
|
}); |
|
|
|
// FIXME: controller#showNewFileDialog workspace root is undefined for some reason |
|
// describe('relative to project root', () => { |
|
|
|
// it('create file at destination', () => { |
|
|
|
// return newFile({ relativeToRoot: true }).then(() => { |
|
// const message = `${targetFile} does not exist`; |
|
// expect(fs.existsSync(targetFile), message).to.be.true; |
|
// }); |
|
// }); |
|
|
|
// }); |
|
|
|
describe('when target destination exists', () => { |
|
|
|
beforeEach(() => { |
|
|
|
const createTargetFile = () => { |
|
return fs.copy(editorFile2, targetFile); |
|
}; |
|
|
|
const stubShowInformationMessage = () => { |
|
sinon.stub(window, 'showInformationMessage').returns(Promise.resolve(true)); |
|
return Promise.resolve(); |
|
}; |
|
|
|
return Promise.all([ |
|
createTargetFile(), |
|
stubShowInformationMessage() |
|
]); |
|
}); |
|
|
|
afterEach(() => { |
|
const stub: any = window.showInformationMessage; |
|
return Promise.resolve(stub.restore()); |
|
}); |
|
|
|
it('asks to overwrite destination file', () => { |
|
|
|
const message = `File '${targetFile}' already exists.`; |
|
const action = 'Overwrite'; |
|
const options = { modal: true }; |
|
|
|
return newJekyllFile().then(() => { |
|
expect(window.showInformationMessage).to.have.been.calledWith(message, options, action); |
|
}); |
|
}); |
|
|
|
describe('responding with yes', () => { |
|
|
|
it('overwrites the existig file', () => { |
|
|
|
return newJekyllFile().then(() => { |
|
const fileContent = fs.readFileSync(targetFile).toString(); |
|
expect(fileContent).to.equal(''); |
|
}); |
|
}); |
|
|
|
}); |
|
|
|
describe('responding with no', () => { |
|
|
|
beforeEach(() => { |
|
const stub: any = window.showInformationMessage; |
|
stub.returns(Promise.resolve(false)); |
|
return Promise.resolve(); |
|
}); |
|
|
|
it('leaves existing file untouched', () => { |
|
|
|
return newJekyllFile().then(() => { |
|
const fileContent = fs.readFileSync(targetFile).toString(); |
|
expect(fileContent).to.equal('class FileTwo; end'); |
|
}); |
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
describe('with no open text document', () => { |
|
|
|
beforeEach(() => { |
|
|
|
const closeAllEditors = () => { |
|
return commands.executeCommand('workbench.action.closeAllEditors'); |
|
}; |
|
|
|
const stubShowInputBox = () => { |
|
sinon.stub(window, 'showInputBox'); |
|
return Promise.resolve(); |
|
}; |
|
|
|
return Promise.all([ |
|
closeAllEditors(), |
|
stubShowInputBox() |
|
]); |
|
}); |
|
|
|
afterEach(() => { |
|
const stub: any = window.showInputBox; |
|
return Promise.resolve(stub.restore()); |
|
}); |
|
|
|
it('ignores the command call', () => { |
|
|
|
return newJekyllFile().catch(() => { |
|
// tslint:disable-next-line:no-unused-expression |
|
expect(window.showInputBox).to.have.not.been.called; |
|
}); |
|
}); |
|
|
|
}); |
|
|
|
describe('error handling', () => { |
|
|
|
beforeEach(() => { |
|
sinon.stub(controller, 'showNewJekyllFileDialog').returns(Promise.reject('must fail')); |
|
sinon.stub(window, 'showErrorMessage'); |
|
return Promise.resolve(); |
|
}); |
|
|
|
afterEach(() => { |
|
|
|
const restoreShowNewFileDialog = () => { |
|
const stub: any = controller.showNewJekyllFileDialog; |
|
return Promise.resolve(stub.restore()); |
|
}; |
|
|
|
const restoreShowErrorMessage = () => { |
|
const stub: any = window.showErrorMessage; |
|
return Promise.resolve(stub.restore()); |
|
}; |
|
|
|
return Promise.all([ |
|
restoreShowNewFileDialog(), |
|
restoreShowErrorMessage() |
|
]); |
|
}); |
|
|
|
it('shows an error message', () => { |
|
|
|
return newJekyllFile().catch((err) => { |
|
expect(window.showErrorMessage).to.have.been.calledWithExactly('must fail'); |
|
}); |
|
}); |
|
|
|
}); |
|
|
|
});
|
|
|