Mailspring/internal_packages/composer-templates/spec/template-store-spec.es6

181 lines
6.4 KiB
Text
Raw Normal View History

import fs from 'fs';
import { remote } from 'electron';
import {Message, DraftStore} from 'nylas-exports';
import TemplateStore from '../lib/template-store';
const { shell } = remote;
const stubTemplatesDir = '~/.nylas/templates';
const stubTemplateFiles = {
'template1.html': '<p>bla1</p>',
'template2.html': '<p>bla2</p>',
};
const stubTemplates = [
{id: 'template1.html', name: 'template1', path: `${stubTemplatesDir}/template1.html`},
{id: 'template2.html', name: 'template2', path: `${stubTemplatesDir}/template2.html`},
];
describe('TemplateStore', function templateStore() {
2016-05-06 13:30:34 +08:00
beforeEach(() => {
spyOn(fs, 'mkdir');
2016-05-06 13:30:34 +08:00
spyOn(shell, 'showItemInFolder').andCallFake(() => {});
spyOn(fs, 'writeFile').andCallFake((path, contents, callback) => {
callback(null);
});
2016-05-06 13:30:34 +08:00
spyOn(fs, 'readFile').andCallFake((path, callback) => {
const filename = path.split('/').pop();
callback(null, stubTemplateFiles[filename]);
});
});
2016-05-06 13:30:34 +08:00
it('should create the templates folder if it does not exist', () => {
2016-05-07 07:06:16 +08:00
spyOn(fs, 'exists').andCallFake((path, callback) => callback(false));
refactor(templates): major additions and refactoring for the Templates plugin. Summary: Adds several new features to the templates plugin, fixes some existing bugs, and refactors existing code. New Plugin Features/Fixes: - Changes the templates editor in preferences to allow variables to be entered with `{{brackets}}`. Handles many contenteditable complexities to implement. - Better interaction for renaming and deleting of templates in the editor. - Changes tabbing behavior when using templates. Tabbing between variables now wraps around, and typing tab from outside a variable region highlights the closest region. - Prevents "Enter" key in the composer when inside a variable region, and strips all formatting/tags from within the region - this prevents major contenteditable issues that can result in inline CSS in the style of our variable regions, which will not be removed when sending. - Shows a warning when choosing a template if it will replace existing text in a draft. - Prevents invalid characters in template names (due to filenames, esp. on Windows), and shows an error message. Strips these characters from draft titles when making a template. - Fixes a bug where TemplateStore's initialization code was being called multiple times. New N1 code: - Several new methods in `DOMUtils` useful for working with contenteditable. - Implement some missing methods in `Editor` Refactor: - Major refactor/rewrite of template composer extension to use new DOMUtils methods and simplify the logic (while adding new functionality). Remaining issues: - `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6 for consistency - Need tests for new DOMUtils functions and for new Templates plugin code. Test Plan: manual, need to update specs Reviewers: evan, bengotow Reviewed By: evan, bengotow Subscribers: juan Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
TemplateStore._init(stubTemplatesDir);
expect(fs.mkdir).toHaveBeenCalled();
});
2016-05-06 13:30:34 +08:00
it('should expose templates in the templates directory', () => {
let watchCallback;
2016-05-06 13:30:34 +08:00
spyOn(fs, 'exists').andCallFake((path, callback) => { callback(true); });
2016-05-07 07:06:16 +08:00
spyOn(fs, 'watch').andCallFake((path, callback) => { watchCallback = callback });
2016-05-06 13:30:34 +08:00
spyOn(fs, 'readdir').andCallFake((path, callback) => { callback(null, Object.keys(stubTemplateFiles)); });
refactor(templates): major additions and refactoring for the Templates plugin. Summary: Adds several new features to the templates plugin, fixes some existing bugs, and refactors existing code. New Plugin Features/Fixes: - Changes the templates editor in preferences to allow variables to be entered with `{{brackets}}`. Handles many contenteditable complexities to implement. - Better interaction for renaming and deleting of templates in the editor. - Changes tabbing behavior when using templates. Tabbing between variables now wraps around, and typing tab from outside a variable region highlights the closest region. - Prevents "Enter" key in the composer when inside a variable region, and strips all formatting/tags from within the region - this prevents major contenteditable issues that can result in inline CSS in the style of our variable regions, which will not be removed when sending. - Shows a warning when choosing a template if it will replace existing text in a draft. - Prevents invalid characters in template names (due to filenames, esp. on Windows), and shows an error message. Strips these characters from draft titles when making a template. - Fixes a bug where TemplateStore's initialization code was being called multiple times. New N1 code: - Several new methods in `DOMUtils` useful for working with contenteditable. - Implement some missing methods in `Editor` Refactor: - Major refactor/rewrite of template composer extension to use new DOMUtils methods and simplify the logic (while adding new functionality). Remaining issues: - `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6 for consistency - Need tests for new DOMUtils functions and for new Templates plugin code. Test Plan: manual, need to update specs Reviewers: evan, bengotow Reviewed By: evan, bengotow Subscribers: juan Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
TemplateStore._init(stubTemplatesDir);
watchCallback();
expect(TemplateStore.items()).toEqual(stubTemplates);
});
2016-05-06 13:30:34 +08:00
it('should watch the templates directory and reflect changes', () => {
let watchCallback = null;
let watchFired = false;
2016-05-06 13:30:34 +08:00
spyOn(fs, 'exists').andCallFake((path, callback) => callback(true));
2016-05-07 07:06:16 +08:00
spyOn(fs, 'watch').andCallFake((path, callback) => { watchCallback = callback });
2016-05-06 13:30:34 +08:00
spyOn(fs, 'readdir').andCallFake((path, callback) => {
if (watchFired) {
callback(null, Object.keys(stubTemplateFiles));
} else {
callback(null, []);
}
});
refactor(templates): major additions and refactoring for the Templates plugin. Summary: Adds several new features to the templates plugin, fixes some existing bugs, and refactors existing code. New Plugin Features/Fixes: - Changes the templates editor in preferences to allow variables to be entered with `{{brackets}}`. Handles many contenteditable complexities to implement. - Better interaction for renaming and deleting of templates in the editor. - Changes tabbing behavior when using templates. Tabbing between variables now wraps around, and typing tab from outside a variable region highlights the closest region. - Prevents "Enter" key in the composer when inside a variable region, and strips all formatting/tags from within the region - this prevents major contenteditable issues that can result in inline CSS in the style of our variable regions, which will not be removed when sending. - Shows a warning when choosing a template if it will replace existing text in a draft. - Prevents invalid characters in template names (due to filenames, esp. on Windows), and shows an error message. Strips these characters from draft titles when making a template. - Fixes a bug where TemplateStore's initialization code was being called multiple times. New N1 code: - Several new methods in `DOMUtils` useful for working with contenteditable. - Implement some missing methods in `Editor` Refactor: - Major refactor/rewrite of template composer extension to use new DOMUtils methods and simplify the logic (while adding new functionality). Remaining issues: - `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6 for consistency - Need tests for new DOMUtils functions and for new Templates plugin code. Test Plan: manual, need to update specs Reviewers: evan, bengotow Reviewed By: evan, bengotow Subscribers: juan Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
TemplateStore._init(stubTemplatesDir);
expect(TemplateStore.items()).toEqual([]);
watchFired = true;
watchCallback();
expect(TemplateStore.items()).toEqual(stubTemplates);
});
2016-05-06 13:30:34 +08:00
describe('insertTemplateId', () => {
xit('should insert the template with the given id into the draft with the given id', () => {
let watchCallback;
2016-05-06 13:30:34 +08:00
spyOn(fs, 'exists').andCallFake((path, callback) => { callback(true); });
2016-05-07 07:06:16 +08:00
spyOn(fs, 'watch').andCallFake((path, callback) => { watchCallback = callback });
2016-05-06 13:30:34 +08:00
spyOn(fs, 'readdir').andCallFake((path, callback) => { callback(null, Object.keys(stubTemplateFiles)); });
refactor(templates): major additions and refactoring for the Templates plugin. Summary: Adds several new features to the templates plugin, fixes some existing bugs, and refactors existing code. New Plugin Features/Fixes: - Changes the templates editor in preferences to allow variables to be entered with `{{brackets}}`. Handles many contenteditable complexities to implement. - Better interaction for renaming and deleting of templates in the editor. - Changes tabbing behavior when using templates. Tabbing between variables now wraps around, and typing tab from outside a variable region highlights the closest region. - Prevents "Enter" key in the composer when inside a variable region, and strips all formatting/tags from within the region - this prevents major contenteditable issues that can result in inline CSS in the style of our variable regions, which will not be removed when sending. - Shows a warning when choosing a template if it will replace existing text in a draft. - Prevents invalid characters in template names (due to filenames, esp. on Windows), and shows an error message. Strips these characters from draft titles when making a template. - Fixes a bug where TemplateStore's initialization code was being called multiple times. New N1 code: - Several new methods in `DOMUtils` useful for working with contenteditable. - Implement some missing methods in `Editor` Refactor: - Major refactor/rewrite of template composer extension to use new DOMUtils methods and simplify the logic (while adding new functionality). Remaining issues: - `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6 for consistency - Need tests for new DOMUtils functions and for new Templates plugin code. Test Plan: manual, need to update specs Reviewers: evan, bengotow Reviewed By: evan, bengotow Subscribers: juan Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
TemplateStore._init(stubTemplatesDir);
watchCallback();
const add = jasmine.createSpy('add');
2016-05-06 13:30:34 +08:00
spyOn(DraftStore, 'sessionForClientId').andCallFake(() => {
return Promise.resolve({changes: {add}});
});
2016-05-06 13:30:34 +08:00
runs(() => {
TemplateStore._onInsertTemplateId({
templateId: 'template1.html',
draftClientId: 'localid-draft',
});
});
2016-05-06 13:30:34 +08:00
waitsFor(() => add.calls.length > 0);
runs(() => {
expect(add).toHaveBeenCalledWith({
body: stubTemplateFiles['template1.html'],
});
});
});
});
2016-05-06 13:30:34 +08:00
describe('onCreateTemplate', () => {
beforeEach(() => {
let d;
2016-05-06 13:30:34 +08:00
spyOn(DraftStore, 'sessionForClientId').andCallFake((draftClientId) => {
if (draftClientId === 'localid-nosubject') {
d = new Message({subject: '', body: '<p>Body</p>'});
} else {
d = new Message({subject: 'Subject', body: '<p>Body</p>'});
}
const session = {draft() { return d; }};
return Promise.resolve(session);
});
refactor(templates): major additions and refactoring for the Templates plugin. Summary: Adds several new features to the templates plugin, fixes some existing bugs, and refactors existing code. New Plugin Features/Fixes: - Changes the templates editor in preferences to allow variables to be entered with `{{brackets}}`. Handles many contenteditable complexities to implement. - Better interaction for renaming and deleting of templates in the editor. - Changes tabbing behavior when using templates. Tabbing between variables now wraps around, and typing tab from outside a variable region highlights the closest region. - Prevents "Enter" key in the composer when inside a variable region, and strips all formatting/tags from within the region - this prevents major contenteditable issues that can result in inline CSS in the style of our variable regions, which will not be removed when sending. - Shows a warning when choosing a template if it will replace existing text in a draft. - Prevents invalid characters in template names (due to filenames, esp. on Windows), and shows an error message. Strips these characters from draft titles when making a template. - Fixes a bug where TemplateStore's initialization code was being called multiple times. New N1 code: - Several new methods in `DOMUtils` useful for working with contenteditable. - Implement some missing methods in `Editor` Refactor: - Major refactor/rewrite of template composer extension to use new DOMUtils methods and simplify the logic (while adding new functionality). Remaining issues: - `preferences-tempaltes.cjsx` and `template-editor.coffee` should be rewritten in ES6 for consistency - Need tests for new DOMUtils functions and for new Templates plugin code. Test Plan: manual, need to update specs Reviewers: evan, bengotow Reviewed By: evan, bengotow Subscribers: juan Differential Revision: https://phab.nylas.com/D2382
2015-12-30 07:11:04 +08:00
TemplateStore._init(stubTemplatesDir);
});
2016-05-06 13:30:34 +08:00
xit('should create a template with the given name and contents', () => {
const ref = TemplateStore.items();
TemplateStore._onCreateTemplate({name: '123', contents: 'bla'});
const item = (ref != null ? ref[0] : undefined);
expect(item.id).toBe('123.html');
expect(item.name).toBe('123');
expect(item.path.split('/').pop()).toBe('123.html');
});
2016-05-06 13:30:34 +08:00
xit('should display an error if no name is provided', () => {
spyOn(TemplateStore, '_displayError');
TemplateStore._onCreateTemplate({contents: 'bla'});
expect(TemplateStore._displayError).toHaveBeenCalled();
});
2016-05-06 13:30:34 +08:00
xit('should display an error if no content is provided', () => {
spyOn(TemplateStore, '_displayError');
TemplateStore._onCreateTemplate({name: 'bla'});
expect(TemplateStore._displayError).toHaveBeenCalled();
});
2016-05-06 13:30:34 +08:00
xit('should save the template file to the templates folder', () => {
TemplateStore._onCreateTemplate({name: '123', contents: 'bla'});
const path = `${stubTemplatesDir}/123.html`;
expect(fs.writeFile).toHaveBeenCalled();
expect(fs.writeFile.mostRecentCall.args[0]).toEqual(path);
expect(fs.writeFile.mostRecentCall.args[1]).toEqual('bla');
});
2016-05-06 13:30:34 +08:00
xit('should open the template so you can see it', () => {
TemplateStore._onCreateTemplate({name: '123', contents: 'bla'});
expect(shell.showItemInFolder).toHaveBeenCalled();
});
2016-05-06 13:30:34 +08:00
describe('when given a draft id', () => {
xit('should create a template from the name and contents of the given draft', () => {
spyOn(TemplateStore, 'trigger');
spyOn(TemplateStore, '_populate');
2016-05-06 13:30:34 +08:00
runs(() => {
TemplateStore._onCreateTemplate({draftClientId: 'localid-b'});
});
2016-05-07 07:06:16 +08:00
waitsFor(() => TemplateStore.trigger.callCount > 0);
2016-05-06 13:30:34 +08:00
runs(() => {
expect(TemplateStore.items().length).toEqual(1);
});
});
2016-05-06 13:30:34 +08:00
it('should display an error if the draft has no subject', () => {
spyOn(TemplateStore, '_displayError');
spyOn(fs, 'watch');
2016-05-06 13:30:34 +08:00
runs(() => {
TemplateStore._onCreateTemplate({draftClientId: 'localid-nosubject'});
});
2016-05-07 07:06:16 +08:00
waitsFor(() => TemplateStore._displayError.callCount > 0);
2016-05-06 13:30:34 +08:00
runs(() => {
expect(TemplateStore._displayError).toHaveBeenCalled();
});
});
});
});
2016-05-06 13:30:34 +08:00
describe('onShowTemplates', () => {
xit('should open the templates folder in the Finder', () => {
TemplateStore._onShowTemplates();
expect(shell.showItemInFolder).toHaveBeenCalled();
});
});
});