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

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');
});
});
});
});