mirror of https://github.com/zulip/zulip.git
565 lines
12 KiB
JavaScript
565 lines
12 KiB
JavaScript
set_global('$', global.make_zjquery());
|
|
zrequire('input_pill');
|
|
|
|
set_global('Handlebars', global.make_handlebars());
|
|
zrequire('templates');
|
|
|
|
set_global('document', {});
|
|
|
|
const noop = function () {};
|
|
const example_img_link = 'http://example.com/example.png';
|
|
|
|
set_global('ui_util', {
|
|
place_caret_at_end: noop,
|
|
});
|
|
|
|
set_global('getSelection', () => {
|
|
return {
|
|
anchorOffset: 0,
|
|
};
|
|
});
|
|
|
|
let id_seq = 0;
|
|
run_test('set_up_ids', () => {
|
|
// just get coverage on a simple one-liner:
|
|
input_pill.random_id();
|
|
|
|
input_pill.random_id = function () {
|
|
id_seq += 1;
|
|
return 'some_id' + id_seq;
|
|
};
|
|
});
|
|
|
|
function pill_html(value, data_id, img_src) {
|
|
const has_image = img_src !== undefined;
|
|
|
|
const opts = {
|
|
id: data_id,
|
|
display_value: value,
|
|
has_image: has_image,
|
|
};
|
|
|
|
if (has_image) {
|
|
opts.img_src = img_src;
|
|
}
|
|
|
|
return require('../../static/templates/input_pill.hbs')(opts);
|
|
}
|
|
|
|
run_test('basics', () => {
|
|
const config = {};
|
|
|
|
blueslip.expect('error', 'Pill needs container.');
|
|
input_pill.create(config);
|
|
|
|
const pill_input = $.create('pill_input');
|
|
const container = $.create('container');
|
|
container.set_find_results('.input', pill_input);
|
|
|
|
blueslip.expect('error', 'Pill needs create_item_from_text');
|
|
config.container = container;
|
|
input_pill.create(config);
|
|
|
|
blueslip.expect('error', 'Pill needs get_text_from_item');
|
|
config.create_item_from_text = noop;
|
|
input_pill.create(config);
|
|
|
|
config.get_text_from_item = noop;
|
|
const widget = input_pill.create(config);
|
|
|
|
const item = {
|
|
display_value: 'JavaScript',
|
|
language: 'js',
|
|
img_src: example_img_link,
|
|
};
|
|
|
|
let inserted_before;
|
|
const expected_html = pill_html('JavaScript', 'some_id1', example_img_link);
|
|
|
|
pill_input.before = function (elem) {
|
|
inserted_before = true;
|
|
assert.equal(elem.html(), expected_html);
|
|
};
|
|
|
|
widget.appendValidatedData(item);
|
|
assert(inserted_before);
|
|
|
|
assert.deepEqual(widget.items(), [item]);
|
|
});
|
|
|
|
function set_up() {
|
|
set_global('$', global.make_zjquery());
|
|
const items = {
|
|
blue: {
|
|
display_value: 'BLUE',
|
|
description: 'color of the sky',
|
|
img_src: example_img_link,
|
|
},
|
|
|
|
red: {
|
|
display_value: 'RED',
|
|
description: 'color of stop signs',
|
|
},
|
|
|
|
yellow: {
|
|
display_value: 'YELLOW',
|
|
description: 'color of bananas',
|
|
},
|
|
};
|
|
|
|
const pill_input = $.create('pill_input');
|
|
|
|
pill_input.before = () => {};
|
|
|
|
const create_item_from_text = function (text) {
|
|
return items[text];
|
|
};
|
|
|
|
const container = $.create('container');
|
|
container.set_find_results('.input', pill_input);
|
|
|
|
const config = {
|
|
container: container,
|
|
create_item_from_text: create_item_from_text,
|
|
get_text_from_item: (item) => item.display_value,
|
|
};
|
|
|
|
id_seq = 0;
|
|
|
|
return {
|
|
config: config,
|
|
pill_input: pill_input,
|
|
items: items,
|
|
container: container,
|
|
};
|
|
}
|
|
|
|
run_test('copy from pill', () => {
|
|
const info = set_up();
|
|
const config = info.config;
|
|
const container = info.container;
|
|
|
|
const widget = input_pill.create(config);
|
|
widget.appendValue('blue,red');
|
|
|
|
const copy_handler = container.get_on_handler('copy', '.pill');
|
|
|
|
let copied_text;
|
|
|
|
const pill_stub = {
|
|
data: (field) => {
|
|
assert.equal(field, 'id');
|
|
return 'some_id2';
|
|
},
|
|
};
|
|
|
|
const e = {
|
|
originalEvent: {
|
|
clipboardData: {
|
|
setData: (format, text) => {
|
|
assert.equal(format, 'text/plain');
|
|
copied_text = text;
|
|
},
|
|
},
|
|
},
|
|
preventDefault: noop,
|
|
};
|
|
|
|
container.set_find_results(':focus', pill_stub);
|
|
|
|
copy_handler(e);
|
|
|
|
assert.equal(copied_text, 'RED');
|
|
});
|
|
|
|
run_test('paste to input', () => {
|
|
const info = set_up();
|
|
const config = info.config;
|
|
const container = info.container;
|
|
const items = info.items;
|
|
|
|
const widget = input_pill.create(config);
|
|
|
|
const paste_handler = container.get_on_handler('paste', '.input');
|
|
|
|
const paste_text = 'blue,yellow';
|
|
|
|
const e = {
|
|
originalEvent: {
|
|
clipboardData: {
|
|
getData: (format) => {
|
|
assert.equal(format, 'text/plain');
|
|
return paste_text;
|
|
},
|
|
},
|
|
},
|
|
preventDefault: noop,
|
|
};
|
|
|
|
document.execCommand = (cmd, _, text) => {
|
|
assert.equal(cmd, 'insertText');
|
|
container.find('.input').text(text);
|
|
};
|
|
|
|
paste_handler(e);
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.yellow,
|
|
]);
|
|
});
|
|
|
|
run_test('arrows on pills', () => {
|
|
const info = set_up();
|
|
const config = info.config;
|
|
const container = info.container;
|
|
|
|
const widget = input_pill.create(config);
|
|
widget.appendValue('blue,red');
|
|
|
|
const key_handler = container.get_on_handler('keydown', '.pill');
|
|
|
|
function test_key(c) {
|
|
key_handler({
|
|
charCode: c,
|
|
});
|
|
}
|
|
|
|
const LEFT_ARROW = 37;
|
|
const RIGHT_ARROW = 39;
|
|
|
|
let prev_focused = false;
|
|
let next_focused = false;
|
|
|
|
const pill_stub = {
|
|
prev: () => {
|
|
return {
|
|
focus: () => {
|
|
prev_focused = true;
|
|
},
|
|
};
|
|
},
|
|
next: () => {
|
|
return {
|
|
focus: () => {
|
|
next_focused = true;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
|
|
container.set_find_results('.pill:focus', pill_stub);
|
|
|
|
// We use the same stub to test both arrows, since we don't
|
|
// actually cause any real state changes here. We stub out
|
|
// the only interaction, which is to move the focus.
|
|
test_key(LEFT_ARROW);
|
|
assert(prev_focused);
|
|
|
|
test_key(RIGHT_ARROW);
|
|
assert(next_focused);
|
|
});
|
|
|
|
run_test('left arrow on input', () => {
|
|
const info = set_up();
|
|
const config = info.config;
|
|
const container = info.container;
|
|
|
|
const widget = input_pill.create(config);
|
|
widget.appendValue('blue,red');
|
|
|
|
const LEFT_ARROW = 37;
|
|
const key_handler = container.get_on_handler('keydown', '.input');
|
|
|
|
let last_pill_focused = false;
|
|
|
|
container.set_find_results('.pill', {
|
|
last: () => {
|
|
return {
|
|
focus: () => {
|
|
last_pill_focused = true;
|
|
},
|
|
};
|
|
},
|
|
});
|
|
|
|
key_handler({
|
|
keyCode: LEFT_ARROW,
|
|
});
|
|
|
|
assert(last_pill_focused);
|
|
});
|
|
|
|
run_test('comma', () => {
|
|
const info = set_up();
|
|
const config = info.config;
|
|
const items = info.items;
|
|
const pill_input = info.pill_input;
|
|
const container = info.container;
|
|
|
|
const widget = input_pill.create(config);
|
|
widget.appendValue('blue,red');
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.red,
|
|
]);
|
|
|
|
const COMMA = 188;
|
|
const key_handler = container.get_on_handler('keydown', '.input');
|
|
|
|
pill_input.text = () => ' yel';
|
|
|
|
key_handler({
|
|
keyCode: COMMA,
|
|
preventDefault: noop,
|
|
});
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.red,
|
|
]);
|
|
|
|
pill_input.text = () => ' yellow';
|
|
|
|
key_handler({
|
|
keyCode: COMMA,
|
|
});
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.red,
|
|
items.yellow,
|
|
]);
|
|
});
|
|
|
|
run_test('enter key with text', () => {
|
|
const info = set_up();
|
|
const config = info.config;
|
|
const items = info.items;
|
|
const container = info.container;
|
|
|
|
const widget = input_pill.create(config);
|
|
widget.appendValue('blue,red');
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.red,
|
|
]);
|
|
|
|
const ENTER = 13;
|
|
const key_handler = container.get_on_handler('keydown', '.input');
|
|
|
|
key_handler({
|
|
keyCode: ENTER,
|
|
preventDefault: noop,
|
|
stopPropagation: noop,
|
|
target: {
|
|
innerText: ' yellow ',
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.red,
|
|
items.yellow,
|
|
]);
|
|
});
|
|
|
|
run_test('insert_remove', () => {
|
|
const info = set_up();
|
|
|
|
const config = info.config;
|
|
const pill_input = info.pill_input;
|
|
const items = info.items;
|
|
const container = info.container;
|
|
|
|
const inserted_html = [];
|
|
pill_input.before = function (elem) {
|
|
inserted_html.push(elem.html());
|
|
};
|
|
|
|
const widget = input_pill.create(config);
|
|
|
|
let created;
|
|
let removed;
|
|
|
|
widget.onPillCreate(function () {
|
|
created = true;
|
|
});
|
|
|
|
widget.onPillRemove(function () {
|
|
removed = true;
|
|
});
|
|
|
|
widget.appendValue('blue,chartreuse,red,yellow,mauve');
|
|
|
|
assert(created);
|
|
assert(!removed);
|
|
|
|
assert.deepEqual(inserted_html, [
|
|
pill_html('BLUE', 'some_id1', example_img_link),
|
|
pill_html('RED', 'some_id2'),
|
|
pill_html('YELLOW', 'some_id3'),
|
|
]);
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.red,
|
|
items.yellow,
|
|
]);
|
|
|
|
assert.equal(pill_input.text(), 'chartreuse, mauve');
|
|
|
|
assert.equal(widget.is_pending(), true);
|
|
widget.clear_text();
|
|
assert.equal(pill_input.text(), '');
|
|
assert.equal(widget.is_pending(), false);
|
|
|
|
const BACKSPACE = 8;
|
|
let key_handler = container.get_on_handler('keydown', '.input');
|
|
|
|
key_handler({
|
|
keyCode: BACKSPACE,
|
|
target: {
|
|
innerText: '',
|
|
},
|
|
preventDefault: noop,
|
|
});
|
|
|
|
assert(removed);
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.blue,
|
|
items.red,
|
|
]);
|
|
|
|
let next_pill_focused = false;
|
|
|
|
const next_pill_stub = {
|
|
focus: () => {
|
|
next_pill_focused = true;
|
|
},
|
|
};
|
|
|
|
const focus_pill_stub = {
|
|
next: () => next_pill_stub,
|
|
data: (field) => {
|
|
assert.equal(field, 'id');
|
|
return 'some_id1';
|
|
},
|
|
};
|
|
|
|
container.set_find_results('.pill:focus', focus_pill_stub);
|
|
|
|
key_handler = container.get_on_handler('keydown', '.pill');
|
|
key_handler({
|
|
keyCode: BACKSPACE,
|
|
preventDefault: noop,
|
|
});
|
|
|
|
assert(next_pill_focused);
|
|
});
|
|
|
|
run_test('exit button on pill', () => {
|
|
const info = set_up();
|
|
|
|
const config = info.config;
|
|
const items = info.items;
|
|
const container = info.container;
|
|
|
|
const widget = input_pill.create(config);
|
|
|
|
widget.appendValue('blue,red');
|
|
|
|
let next_pill_focused = false;
|
|
|
|
const next_pill_stub = {
|
|
focus: () => {
|
|
next_pill_focused = true;
|
|
},
|
|
};
|
|
|
|
const curr_pill_stub = {
|
|
next: () => next_pill_stub,
|
|
data: (field) => {
|
|
assert.equal(field, 'id');
|
|
return 'some_id1';
|
|
},
|
|
};
|
|
|
|
const exit_button_stub = {
|
|
to_$: () => {
|
|
return {
|
|
closest: (sel) => {
|
|
assert.equal(sel, '.pill');
|
|
return curr_pill_stub;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
|
|
const e = {
|
|
stopPropagation: noop,
|
|
};
|
|
const exit_click_handler = container.get_on_handler('click', '.exit');
|
|
|
|
exit_click_handler.call(exit_button_stub, e);
|
|
|
|
assert(next_pill_focused);
|
|
|
|
assert.deepEqual(widget.items(), [
|
|
items.red,
|
|
]);
|
|
|
|
});
|
|
|
|
run_test('misc things', () => {
|
|
const info = set_up();
|
|
|
|
const config = info.config;
|
|
const container = info.container;
|
|
const pill_input = info.pill_input;
|
|
|
|
const widget = input_pill.create(config);
|
|
|
|
// animation
|
|
const animation_end_handler = container.get_on_handler('animationend', '.input');
|
|
|
|
let shake_class_removed = false;
|
|
|
|
const input_stub = {
|
|
to_$: () => {
|
|
return {
|
|
removeClass: (cls) => {
|
|
assert.equal(cls, 'shake');
|
|
shake_class_removed = true;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
|
|
animation_end_handler.call(input_stub);
|
|
assert(shake_class_removed);
|
|
|
|
// bad data
|
|
blueslip.expect('error', 'no display_value returned');
|
|
widget.appendValidatedData('this-has-no-item-attribute');
|
|
|
|
// click on container
|
|
const container_click_handler = container.get_on_handler('click');
|
|
|
|
const stub = $.create('the-pill-container');
|
|
stub.set_find_results('.input', pill_input);
|
|
stub.is = (sel) => {
|
|
assert.equal(sel, '.pill-container');
|
|
return true;
|
|
};
|
|
|
|
const this_ = {
|
|
to_$: () => stub,
|
|
};
|
|
|
|
container_click_handler.call(this_, {target: this_});
|
|
});
|