Add JS specs for replyWithSelectedText

This commit is contained in:
Robert Speicher 2015-04-18 15:16:05 -04:00
parent ca5d0c8250
commit 8e6fa2555e
3 changed files with 519 additions and 0 deletions

View File

@ -1,3 +1,6 @@
#= require jquery
#= require mousetrap
#= require shortcuts_navigation
class @ShortcutsIssueable extends ShortcutsNavigation

View File

@ -0,0 +1,83 @@
#= require jquery
#= require jasmine-fixture
#= require shortcuts_issueable
describe 'ShortcutsIssueable', ->
beforeEach ->
@shortcut = new ShortcutsIssueable()
describe '#replyWithSelectedText', ->
# Stub window.getSelection to return the provided String.
stubSelection = (text) ->
window.getSelection = -> text
beforeEach ->
@selector = 'form.js-main-target-form textarea#note_note'
affix(@selector)
describe 'with empty selection', ->
it 'does nothing', ->
stubSelection('')
@shortcut.replyWithSelectedText()
expect($(@selector).val()).toBe('')
describe 'with any selection', ->
beforeEach ->
stubSelection('Selected text.')
it 'leaves existing input intact', ->
$(@selector).val('This text was already here.')
expect($(@selector).val()).toBe('This text was already here.')
@shortcut.replyWithSelectedText()
expect($(@selector).val()).
toBe("This text was already here.\n> Selected text.\n\n")
it 'triggers `input`', ->
triggered = false
$(@selector).on 'input', -> triggered = true
@shortcut.replyWithSelectedText()
expect(triggered).toBe(true)
it 'triggers `focus`', ->
focused = false
$(@selector).on 'focus', -> focused = true
@shortcut.replyWithSelectedText()
expect(focused).toBe(true)
describe 'with a one-line selection', ->
it 'quotes the selection', ->
stubSelection('This text has been selected.')
@shortcut.replyWithSelectedText()
expect($(@selector).val()).
toBe("> This text has been selected.\n\n")
describe 'with a multi-line selection', ->
it 'quotes the selected lines as a group', ->
stubSelection(
"""
Selected line one.
Selected line two.
Selected line three.
"""
)
@shortcut.replyWithSelectedText()
expect($(@selector).val()).
toBe(
"""
> Selected line one.
> Selected line two.
> Selected line three.
"""
)

View File

@ -0,0 +1,433 @@
/* jasmine-fixture - 1.2.2
* Makes injecting HTML snippets into the DOM easy & clean!
* https://github.com/searls/jasmine-fixture
*/
(function() {
var createHTMLBlock,
__slice = [].slice;
(function($) {
var ewwSideEffects, jasmineFixture, originalAffix, originalJasmineDotFixture, originalJasmineFixture, root, _, _ref;
root = this;
originalJasmineFixture = root.jasmineFixture;
originalJasmineDotFixture = (_ref = root.jasmine) != null ? _ref.fixture : void 0;
originalAffix = root.affix;
_ = function(list) {
return {
inject: function(iterator, memo) {
var item, _i, _len, _results;
_results = [];
for (_i = 0, _len = list.length; _i < _len; _i++) {
item = list[_i];
_results.push(memo = iterator(memo, item));
}
return _results;
}
};
};
root.jasmineFixture = function($) {
var $whatsTheRootOf, affix, create, jasmineFixture, noConflict;
affix = function(selectorOptions) {
return create.call(this, selectorOptions, true);
};
create = function(selectorOptions, attach) {
var $top;
$top = null;
_(selectorOptions.split(/[ ](?=[^\]]*?(?:\[|$))/)).inject(function($parent, elementSelector) {
var $el;
if (elementSelector === ">") {
return $parent;
}
$el = createHTMLBlock($, elementSelector);
if (attach || $top) {
$el.appendTo($parent);
}
$top || ($top = $el);
return $el;
}, $whatsTheRootOf(this));
return $top;
};
noConflict = function() {
var currentJasmineFixture, _ref1;
currentJasmineFixture = jasmine.fixture;
root.jasmineFixture = originalJasmineFixture;
if ((_ref1 = root.jasmine) != null) {
_ref1.fixture = originalJasmineDotFixture;
}
root.affix = originalAffix;
return currentJasmineFixture;
};
$whatsTheRootOf = function(that) {
if (that.jquery != null) {
return that;
} else if ($('#jasmine_content').length > 0) {
return $('#jasmine_content');
} else {
return $('<div id="jasmine_content"></div>').appendTo('body');
}
};
jasmineFixture = {
affix: affix,
create: create,
noConflict: noConflict
};
ewwSideEffects(jasmineFixture);
return jasmineFixture;
};
ewwSideEffects = function(jasmineFixture) {
var _ref1;
if ((_ref1 = root.jasmine) != null) {
_ref1.fixture = jasmineFixture;
}
$.fn.affix = root.affix = jasmineFixture.affix;
return afterEach(function() {
return $('#jasmine_content').remove();
});
};
if ($) {
return jasmineFixture = root.jasmineFixture($);
} else {
return root.affix = function() {
var nowJQueryExists;
nowJQueryExists = window.jQuery || window.$;
if (nowJQueryExists != null) {
jasmineFixture = root.jasmineFixture(nowJQueryExists);
return affix.call.apply(affix, [this].concat(__slice.call(arguments)));
} else {
throw new Error("jasmine-fixture requires jQuery to be defined at window.jQuery or window.$");
}
};
}
})(window.jQuery || window.$);
createHTMLBlock = (function() {
var bindData, bindEvents, parseAttributes, parseClasses, parseContents, parseEnclosure, parseReferences, parseVariableScope, regAttr, regAttrDfn, regAttrs, regCBrace, regClass, regClasses, regData, regDatas, regEvent, regEvents, regExclamation, regId, regReference, regTag, regTagNotContent, regZenTagDfn;
createHTMLBlock = function($, ZenObject, data, functions, indexes) {
var ZenCode, arr, block, blockAttrs, blockClasses, blockHTML, blockId, blockTag, blocks, el, el2, els, forScope, indexName, inner, len, obj, origZenCode, paren, result, ret, zc, zo;
if ($.isPlainObject(ZenObject)) {
ZenCode = ZenObject.main;
} else {
ZenCode = ZenObject;
ZenObject = {
main: ZenCode
};
}
origZenCode = ZenCode;
if (indexes === undefined) {
indexes = {};
}
if (ZenCode.charAt(0) === "!" || $.isArray(data)) {
if ($.isArray(data)) {
forScope = ZenCode;
} else {
obj = parseEnclosure(ZenCode, "!");
obj = obj.substring(obj.indexOf(":") + 1, obj.length - 1);
forScope = parseVariableScope(ZenCode);
}
while (forScope.charAt(0) === "@") {
forScope = parseVariableScope("!for:!" + parseReferences(forScope, ZenObject));
}
zo = ZenObject;
zo.main = forScope;
el = $();
if (ZenCode.substring(0, 5) === "!for:" || $.isArray(data)) {
if (!$.isArray(data) && obj.indexOf(":") > 0) {
indexName = obj.substring(0, obj.indexOf(":"));
obj = obj.substr(obj.indexOf(":") + 1);
}
arr = ($.isArray(data) ? data : data[obj]);
zc = zo.main;
if ($.isArray(arr) || $.isPlainObject(arr)) {
$.map(arr, function(value, index) {
var next;
zo.main = zc;
if (indexName !== undefined) {
indexes[indexName] = index;
}
if (!$.isPlainObject(value)) {
value = {
value: value
};
}
next = createHTMLBlock($, zo, value, functions, indexes);
if (el.length !== 0) {
return $.each(next, function(index, value) {
return el.push(value);
});
}
});
}
if (!$.isArray(data)) {
ZenCode = ZenCode.substr(obj.length + 6 + forScope.length);
} else {
ZenCode = "";
}
} else if (ZenCode.substring(0, 4) === "!if:") {
result = parseContents("!" + obj + "!", data, indexes);
if (result !== "undefined" || result !== "false" || result !== "") {
el = createHTMLBlock($, zo, data, functions, indexes);
}
ZenCode = ZenCode.substr(obj.length + 5 + forScope.length);
}
ZenObject.main = ZenCode;
} else if (ZenCode.charAt(0) === "(") {
paren = parseEnclosure(ZenCode, "(", ")");
inner = paren.substring(1, paren.length - 1);
ZenCode = ZenCode.substr(paren.length);
zo = ZenObject;
zo.main = inner;
el = createHTMLBlock($, zo, data, functions, indexes);
} else {
blocks = ZenCode.match(regZenTagDfn);
block = blocks[0];
if (block.length === 0) {
return "";
}
if (block.indexOf("@") >= 0) {
ZenCode = parseReferences(ZenCode, ZenObject);
zo = ZenObject;
zo.main = ZenCode;
return createHTMLBlock($, zo, data, functions, indexes);
}
block = parseContents(block, data, indexes);
blockClasses = parseClasses($, block);
if (regId.test(block)) {
blockId = regId.exec(block)[1];
}
blockAttrs = parseAttributes(block, data);
blockTag = (block.charAt(0) === "{" ? "span" : "div");
if (ZenCode.charAt(0) !== "#" && ZenCode.charAt(0) !== "." && ZenCode.charAt(0) !== "{") {
blockTag = regTag.exec(block)[1];
}
if (block.search(regCBrace) !== -1) {
blockHTML = block.match(regCBrace)[1];
}
blockAttrs = $.extend(blockAttrs, {
id: blockId,
"class": blockClasses,
html: blockHTML
});
el = $("<" + blockTag + ">", blockAttrs);
el.attr(blockAttrs);
el = bindEvents(block, el, functions);
el = bindData(block, el, data);
ZenCode = ZenCode.substr(blocks[0].length);
ZenObject.main = ZenCode;
}
if (ZenCode.length > 0) {
if (ZenCode.charAt(0) === ">") {
if (ZenCode.charAt(1) === "(") {
zc = parseEnclosure(ZenCode.substr(1), "(", ")");
ZenCode = ZenCode.substr(zc.length + 1);
} else if (ZenCode.charAt(1) === "!") {
obj = parseEnclosure(ZenCode.substr(1), "!");
forScope = parseVariableScope(ZenCode.substr(1));
zc = obj + forScope;
ZenCode = ZenCode.substr(zc.length + 1);
} else {
len = Math.max(ZenCode.indexOf("+"), ZenCode.length);
zc = ZenCode.substring(1, len);
ZenCode = ZenCode.substr(len);
}
zo = ZenObject;
zo.main = zc;
els = $(createHTMLBlock($, zo, data, functions, indexes));
els.appendTo(el);
}
if (ZenCode.charAt(0) === "+") {
zo = ZenObject;
zo.main = ZenCode.substr(1);
el2 = createHTMLBlock($, zo, data, functions, indexes);
$.each(el2, function(index, value) {
return el.push(value);
});
}
}
ret = el;
return ret;
};
bindData = function(ZenCode, el, data) {
var datas, i, split;
if (ZenCode.search(regDatas) === 0) {
return el;
}
datas = ZenCode.match(regDatas);
if (datas === null) {
return el;
}
i = 0;
while (i < datas.length) {
split = regData.exec(datas[i]);
if (split[3] === undefined) {
$(el).data(split[1], data[split[1]]);
} else {
$(el).data(split[1], data[split[3]]);
}
i++;
}
return el;
};
bindEvents = function(ZenCode, el, functions) {
var bindings, fn, i, split;
if (ZenCode.search(regEvents) === 0) {
return el;
}
bindings = ZenCode.match(regEvents);
if (bindings === null) {
return el;
}
i = 0;
while (i < bindings.length) {
split = regEvent.exec(bindings[i]);
if (split[2] === undefined) {
fn = functions[split[1]];
} else {
fn = functions[split[2]];
}
$(el).bind(split[1], fn);
i++;
}
return el;
};
parseAttributes = function(ZenBlock, data) {
var attrStrs, attrs, i, parts;
if (ZenBlock.search(regAttrDfn) === -1) {
return undefined;
}
attrStrs = ZenBlock.match(regAttrDfn);
attrs = {};
i = 0;
while (i < attrStrs.length) {
parts = regAttr.exec(attrStrs[i]);
attrs[parts[1]] = "";
if (parts[3] !== undefined) {
attrs[parts[1]] = parseContents(parts[3], data);
}
i++;
}
return attrs;
};
parseClasses = function($, ZenBlock) {
var classes, clsString, i;
ZenBlock = ZenBlock.match(regTagNotContent)[0];
if (ZenBlock.search(regClasses) === -1) {
return undefined;
}
classes = ZenBlock.match(regClasses);
clsString = "";
i = 0;
while (i < classes.length) {
clsString += " " + regClass.exec(classes[i])[1];
i++;
}
return $.trim(clsString);
};
parseContents = function(ZenBlock, data, indexes) {
var html;
if (indexes === undefined) {
indexes = {};
}
html = ZenBlock;
if (data === undefined) {
return html;
}
while (regExclamation.test(html)) {
html = html.replace(regExclamation, function(str, str2) {
var begChar, fn, val;
begChar = "";
if (str.indexOf("!for:") > 0 || str.indexOf("!if:") > 0) {
return str;
}
if (str.charAt(0) !== "!") {
begChar = str.charAt(0);
str = str.substring(2, str.length - 1);
}
fn = new Function("data", "indexes", "var r=undefined;" + "with(data){try{r=" + str + ";}catch(e){}}" + "with(indexes){try{if(r===undefined)r=" + str + ";}catch(e){}}" + "return r;");
val = unescape(fn(data, indexes));
return begChar + val;
});
}
html = html.replace(/\\./g, function(str) {
return str.charAt(1);
});
return unescape(html);
};
parseEnclosure = function(ZenCode, open, close, count) {
var index, ret;
if (close === undefined) {
close = open;
}
index = 1;
if (count === undefined) {
count = (ZenCode.charAt(0) === open ? 1 : 0);
}
if (count === 0) {
return;
}
while (count > 0 && index < ZenCode.length) {
if (ZenCode.charAt(index) === close && ZenCode.charAt(index - 1) !== "\\") {
count--;
} else {
if (ZenCode.charAt(index) === open && ZenCode.charAt(index - 1) !== "\\") {
count++;
}
}
index++;
}
ret = ZenCode.substring(0, index);
return ret;
};
parseReferences = function(ZenCode, ZenObject) {
ZenCode = ZenCode.replace(regReference, function(str) {
var fn;
str = str.substr(1);
fn = new Function("objs", "var r=\"\";" + "with(objs){try{" + "r=" + str + ";" + "}catch(e){}}" + "return r;");
return fn(ZenObject, parseReferences);
});
return ZenCode;
};
parseVariableScope = function(ZenCode) {
var forCode, rest, tag;
if (ZenCode.substring(0, 5) !== "!for:" && ZenCode.substring(0, 4) !== "!if:") {
return undefined;
}
forCode = parseEnclosure(ZenCode, "!");
ZenCode = ZenCode.substr(forCode.length);
if (ZenCode.charAt(0) === "(") {
return parseEnclosure(ZenCode, "(", ")");
}
tag = ZenCode.match(regZenTagDfn)[0];
ZenCode = ZenCode.substr(tag.length);
if (ZenCode.length === 0 || ZenCode.charAt(0) === "+") {
return tag;
} else if (ZenCode.charAt(0) === ">") {
rest = "";
rest = parseEnclosure(ZenCode.substr(1), "(", ")", 1);
return tag + ">" + rest;
}
return undefined;
};
regZenTagDfn = /([#\.\@]?[\w-]+|\[([\w-!?=:"']+(="([^"]|\\")+")? {0,})+\]|\~[\w$]+=[\w$]+|&[\w$]+(=[\w$]+)?|[#\.\@]?!([^!]|\\!)+!){0,}(\{([^\}]|\\\})+\})?/i;
regTag = /(\w+)/i;
regId = /(?:^|\b)#([\w-!]+)/i;
regTagNotContent = /((([#\.]?[\w-]+)?(\[([\w!]+(="([^"]|\\")+")? {0,})+\])?)+)/i;
/*
See lookahead syntax (?!) at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
*/
regClasses = /(\.[\w-]+)(?!["\w])/g;
regClass = /\.([\w-]+)/i;
regReference = /(@[\w$_][\w$_\d]+)/i;
regAttrDfn = /(\[([\w-!]+(="?([^"]|\\")+"?)? {0,})+\])/ig;
regAttrs = /([\w-!]+(="([^"]|\\")+")?)/g;
regAttr = /([\w-!]+)(="?((([\w]+(\[.*?\])+)|[^"\]]|\\")+)"?)?/i;
regCBrace = /\{(([^\}]|\\\})+)\}/i;
regExclamation = /(?:([^\\]|^))!([^!]|\\!)+!/g;
regEvents = /\~[\w$]+(=[\w$]+)?/g;
regEvent = /\~([\w$]+)=([\w$]+)/i;
regDatas = /&[\w$]+(=[\w$]+)?/g;
regData = /&([\w$]+)(=([\w$]+))?/i;
return createHTMLBlock;
})();
}).call(this);