xmpp.chapril.org-conversejs/spec/autocomplete.js

374 lines
16 KiB
JavaScript
Raw Normal View History

/*global mock, converse */
2020-04-22 13:11:48 +02:00
const $pres = converse.env.$pres;
const $msg = converse.env.$msg;
const Strophe = converse.env.Strophe;
const u = converse.env.utils;
2020-04-22 13:11:48 +02:00
describe("The nickname autocomplete feature", function () {
it("shows all autocompletion options when the user presses @",
2021-01-29 14:15:27 +01:00
mock.initConverse(['chatBoxesFetched'], {},
async function (done, _converse) {
2020-04-22 13:11:48 +02:00
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit');
// Nicknames from presences
['dick', 'harry'].forEach((nick) => {
_converse.connection._dataRecv(mock.createRequest(
$pres({
'to': 'tom@montague.lit/resource',
'from': `lounge@montague.lit/${nick}`
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
2020-04-22 13:11:48 +02:00
'jid': `${nick}@montague.lit/resource`,
'role': 'participant'
2020-04-22 13:11:48 +02:00
})));
});
// Nicknames from messages
const msg = $msg({
from: 'lounge@montague.lit/jane',
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('Hello world').tree();
await view.model.handleMessageStanza(msg);
await u.waitUntil(() => view.model.messages.last()?.get('received'));
2020-04-22 13:11:48 +02:00
// Test that pressing @ brings up all options
const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea'));
2020-04-22 13:11:48 +02:00
const at_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 50,
'key': '@'
};
const bottom_panel = view.querySelector('converse-muc-bottom-panel');
bottom_panel.onKeyDown(at_event);
2020-04-22 13:11:48 +02:00
textarea.value = '@';
bottom_panel.onKeyUp(at_event);
2020-04-22 13:11:48 +02:00
await u.waitUntil(() => view.querySelectorAll('.suggestion-box__results li').length === 4);
expect(view.querySelector('.suggestion-box__results li:first-child').textContent).toBe('dick');
expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('harry');
expect(view.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('jane');
expect(view.querySelector('.suggestion-box__results li:nth-child(4)').textContent).toBe('tom');
done();
}));
it("shows all autocompletion options when the user presses @ right after a new line",
2021-01-29 14:15:27 +01:00
mock.initConverse(['chatBoxesFetched'], {},
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit');
// Nicknames from presences
['dick', 'harry'].forEach((nick) => {
_converse.connection._dataRecv(mock.createRequest(
$pres({
'to': 'tom@montague.lit/resource',
'from': `lounge@montague.lit/${nick}`
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': `${nick}@montague.lit/resource`,
'role': 'participant'
})));
});
// Nicknames from messages
const msg = $msg({
from: 'lounge@montague.lit/jane',
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('Hello world').tree();
await view.model.handleMessageStanza(msg);
await u.waitUntil(() => view.model.messages.last()?.get('received'));
// Test that pressing @ brings up all options
const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea'));
const at_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 50,
'key': '@'
};
const bottom_panel = view.querySelector('converse-muc-bottom-panel');
textarea.value = '\n'
bottom_panel.onKeyDown(at_event);
textarea.value = '\n@';
bottom_panel.onKeyUp(at_event);
await u.waitUntil(() => view.querySelectorAll('.suggestion-box__results li').length === 4);
expect(view.querySelector('.suggestion-box__results li:first-child').textContent).toBe('dick');
expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('harry');
expect(view.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('jane');
expect(view.querySelector('.suggestion-box__results li:nth-child(4)').textContent).toBe('tom');
done();
}));
it("shows all autocompletion options when the user presses @ right after an allowed character",
mock.initConverse(
2021-01-29 14:15:27 +01:00
['chatBoxesFetched'], {'opening_mention_characters':['(']},
async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit');
// Nicknames from presences
['dick', 'harry'].forEach((nick) => {
_converse.connection._dataRecv(mock.createRequest(
$pres({
'to': 'tom@montague.lit/resource',
'from': `lounge@montague.lit/${nick}`
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': `${nick}@montague.lit/resource`,
'role': 'participant'
})));
});
// Nicknames from messages
const msg = $msg({
from: 'lounge@montague.lit/jane',
id: u.getUniqueId(),
to: 'romeo@montague.lit',
type: 'groupchat'
}).c('body').t('Hello world').tree();
await view.model.handleMessageStanza(msg);
await u.waitUntil(() => view.model.messages.last()?.get('received'));
// Test that pressing @ brings up all options
const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea'));
const at_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 50,
'key': '@'
};
textarea.value = '('
const bottom_panel = view.querySelector('converse-muc-bottom-panel');
bottom_panel.onKeyDown(at_event);
textarea.value = '(@';
bottom_panel.onKeyUp(at_event);
await u.waitUntil(() => view.querySelectorAll('.suggestion-box__results li').length === 4);
expect(view.querySelector('.suggestion-box__results li:first-child').textContent).toBe('dick');
expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('harry');
expect(view.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('jane');
expect(view.querySelector('.suggestion-box__results li:nth-child(4)').textContent).toBe('tom');
2020-04-22 13:11:48 +02:00
done();
}));
it("should order by query index position and length", mock.initConverse(
2021-01-29 14:15:27 +01:00
['chatBoxesFetched'], {}, async function (done, _converse) {
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
const view = _converse.chatboxviews.get('lounge@montague.lit');
// Nicknames from presences
['bernard', 'naber', 'helberlo', 'john', 'jones'].forEach((nick) => {
_converse.connection._dataRecv(mock.createRequest(
$pres({
'to': 'tom@montague.lit/resource',
'from': `lounge@montague.lit/${nick}`
})
.c('x', { xmlns: Strophe.NS.MUC_USER })
.c('item', {
'affiliation': 'none',
'jid': `${nick}@montague.lit/resource`,
'role': 'participant'
})));
});
const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea'));
const at_event = {
'target': textarea,
'preventDefault': function preventDefault() { },
'stopPropagation': function stopPropagation() { },
'keyCode': 50,
'key': '@'
};
const bottom_panel = view.querySelector('converse-muc-bottom-panel');
// Test that results are sorted by query index
bottom_panel.onKeyDown(at_event);
textarea.value = '@ber';
bottom_panel.onKeyUp(at_event);
await u.waitUntil(() => view.querySelectorAll('.suggestion-box__results li').length === 3);
expect(view.querySelector('.suggestion-box__results li:first-child').textContent).toBe('bernard');
expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('naber');
expect(view.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('helberlo');
// Test that when the query index is equal, results should be sorted by length
textarea.value = '@jo';
bottom_panel.onKeyUp(at_event);
await u.waitUntil(() => view.querySelectorAll('.suggestion-box__results li').length === 2);
expect(view.querySelector('.suggestion-box__results li:first-child').textContent).toBe('john');
expect(view.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('jones');
done();
}));
2020-04-22 13:11:48 +02:00
it("autocompletes when the user presses tab",
2021-01-29 14:15:27 +01:00
mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
2020-04-22 13:11:48 +02:00
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
const view = _converse.chatboxviews.get('lounge@montague.lit');
expect(view.model.occupants.length).toBe(1);
let presence = $pres({
'to': 'romeo@montague.lit/orchard',
'from': 'lounge@montague.lit/some1'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'some1@montague.lit/resource',
'role': 'participant'
});
_converse.connection._dataRecv(mock.createRequest(presence));
expect(view.model.occupants.length).toBe(2);
const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea'));
2020-04-22 13:11:48 +02:00
textarea.value = "hello som";
// Press tab
const tab_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 9,
'key': 'Tab'
}
const bottom_panel = view.querySelector('converse-muc-bottom-panel');
bottom_panel.onKeyDown(tab_event);
bottom_panel.onKeyUp(tab_event);
await u.waitUntil(() => view.querySelector('.suggestion-box__results').hidden === false);
expect(view.querySelectorAll('.suggestion-box__results li').length).toBe(1);
expect(view.querySelector('.suggestion-box__results li').textContent).toBe('some1');
2020-04-22 13:11:48 +02:00
const backspace_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'keyCode': 8
}
for (var i=0; i<3; i++) {
// Press backspace 3 times to remove "som"
bottom_panel.onKeyDown(backspace_event);
2020-04-22 13:11:48 +02:00
textarea.value = textarea.value.slice(0, textarea.value.length-1)
bottom_panel.onKeyUp(backspace_event);
2020-04-22 13:11:48 +02:00
}
await u.waitUntil(() => view.querySelector('.suggestion-box__results').hidden === true);
2020-04-22 13:11:48 +02:00
presence = $pres({
'to': 'romeo@montague.lit/orchard',
'from': 'lounge@montague.lit/some2'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'some2@montague.lit/resource',
'role': 'participant'
});
_converse.connection._dataRecv(mock.createRequest(presence));
textarea.value = "hello s s";
bottom_panel.onKeyDown(tab_event);
bottom_panel.onKeyUp(tab_event);
await u.waitUntil(() => view.querySelector('.suggestion-box__results').hidden === false);
expect(view.querySelectorAll('.suggestion-box__results li').length).toBe(2);
2020-04-22 13:11:48 +02:00
const up_arrow_event = {
'target': textarea,
'preventDefault': () => (up_arrow_event.defaultPrevented = true),
'stopPropagation': function stopPropagation () {},
'keyCode': 38
}
bottom_panel.onKeyDown(up_arrow_event);
bottom_panel.onKeyUp(up_arrow_event);
expect(view.querySelectorAll('.suggestion-box__results li').length).toBe(2);
expect(view.querySelector('.suggestion-box__results li[aria-selected="false"]').textContent).toBe('some1');
expect(view.querySelector('.suggestion-box__results li[aria-selected="true"]').textContent).toBe('some2');
2020-04-22 13:11:48 +02:00
bottom_panel.onKeyDown({
2020-04-22 13:11:48 +02:00
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 13 // Enter
});
expect(textarea.value).toBe('hello s @some2 ');
// Test that pressing tab twice selects
presence = $pres({
'to': 'romeo@montague.lit/orchard',
'from': 'lounge@montague.lit/z3r0'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'z3r0@montague.lit/resource',
'role': 'participant'
});
_converse.connection._dataRecv(mock.createRequest(presence));
textarea.value = "hello z";
bottom_panel.onKeyDown(tab_event);
bottom_panel.onKeyUp(tab_event);
await u.waitUntil(() => view.querySelector('.suggestion-box__results').hidden === false);
2020-04-22 13:11:48 +02:00
bottom_panel.onKeyDown(tab_event);
bottom_panel.onKeyUp(tab_event);
2020-04-22 13:11:48 +02:00
await u.waitUntil(() => textarea.value === 'hello @z3r0 ');
done();
}));
it("autocompletes when the user presses backspace",
2021-01-29 14:15:27 +01:00
mock.initConverse([], {}, async function (done, _converse) {
2020-04-22 13:11:48 +02:00
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
const view = _converse.chatboxviews.get('lounge@montague.lit');
expect(view.model.occupants.length).toBe(1);
const presence = $pres({
'to': 'romeo@montague.lit/orchard',
'from': 'lounge@montague.lit/some1'
})
.c('x', {xmlns: Strophe.NS.MUC_USER})
.c('item', {
'affiliation': 'none',
'jid': 'some1@montague.lit/resource',
'role': 'participant'
});
_converse.connection._dataRecv(mock.createRequest(presence));
expect(view.model.occupants.length).toBe(2);
const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea'));
2020-04-22 13:11:48 +02:00
textarea.value = "hello @some1 ";
// Press backspace
const backspace_event = {
'target': textarea,
'preventDefault': function preventDefault () {},
'stopPropagation': function stopPropagation () {},
'keyCode': 8,
'key': 'Backspace'
}
const bottom_panel = view.querySelector('converse-muc-bottom-panel');
bottom_panel.onKeyDown(backspace_event);
2020-04-22 13:11:48 +02:00
textarea.value = "hello @some1"; // Mimic backspace
bottom_panel.onKeyUp(backspace_event);
await u.waitUntil(() => view.querySelector('.suggestion-box__results').hidden === false);
expect(view.querySelectorAll('.suggestion-box__results li').length).toBe(1);
expect(view.querySelector('.suggestion-box__results li').textContent).toBe('some1');
2020-04-22 13:11:48 +02:00
done();
}));
});