autocomplete.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*global mock, converse */
  2. const $pres = converse.env.$pres;
  3. const $msg = converse.env.$msg;
  4. const Strophe = converse.env.Strophe;
  5. const u = converse.env.utils;
  6. describe("The nickname autocomplete feature", function () {
  7. it("shows all autocompletion options when the user presses @",
  8. mock.initConverse(
  9. ['rosterGroupsFetched', 'chatBoxesFetched'], {},
  10. async function (done, _converse) {
  11. await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'tom');
  12. const view = _converse.chatboxviews.get('lounge@montague.lit');
  13. // Nicknames from presences
  14. ['dick', 'harry'].forEach((nick) => {
  15. _converse.connection._dataRecv(mock.createRequest(
  16. $pres({
  17. 'to': 'tom@montague.lit/resource',
  18. 'from': `lounge@montague.lit/${nick}`
  19. })
  20. .c('x', {xmlns: Strophe.NS.MUC_USER})
  21. .c('item', {
  22. 'affiliation': 'none',
  23. 'jid': `${nick}@montague.lit/resource`,
  24. 'role': 'participant'
  25. })));
  26. });
  27. // Nicknames from messages
  28. const msg = $msg({
  29. from: 'lounge@montague.lit/jane',
  30. id: u.getUniqueId(),
  31. to: 'romeo@montague.lit',
  32. type: 'groupchat'
  33. }).c('body').t('Hello world').tree();
  34. await view.model.handleMessageStanza(msg);
  35. // Test that pressing @ brings up all options
  36. const textarea = view.el.querySelector('textarea.chat-textarea');
  37. const at_event = {
  38. 'target': textarea,
  39. 'preventDefault': function preventDefault () {},
  40. 'stopPropagation': function stopPropagation () {},
  41. 'keyCode': 50,
  42. 'key': '@'
  43. };
  44. view.onKeyDown(at_event);
  45. textarea.value = '@';
  46. view.onKeyUp(at_event);
  47. await u.waitUntil(() => view.el.querySelectorAll('.suggestion-box__results li').length === 4);
  48. expect(view.el.querySelector('.suggestion-box__results li:first-child').textContent).toBe('dick');
  49. expect(view.el.querySelector('.suggestion-box__results li:nth-child(2)').textContent).toBe('harry');
  50. expect(view.el.querySelector('.suggestion-box__results li:nth-child(3)').textContent).toBe('jane');
  51. expect(view.el.querySelector('.suggestion-box__results li:nth-child(4)').textContent).toBe('tom');
  52. done();
  53. }));
  54. it("autocompletes when the user presses tab",
  55. mock.initConverse(
  56. ['rosterGroupsFetched', 'chatBoxesFetched'], {},
  57. async function (done, _converse) {
  58. await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
  59. const view = _converse.chatboxviews.get('lounge@montague.lit');
  60. expect(view.model.occupants.length).toBe(1);
  61. let presence = $pres({
  62. 'to': 'romeo@montague.lit/orchard',
  63. 'from': 'lounge@montague.lit/some1'
  64. })
  65. .c('x', {xmlns: Strophe.NS.MUC_USER})
  66. .c('item', {
  67. 'affiliation': 'none',
  68. 'jid': 'some1@montague.lit/resource',
  69. 'role': 'participant'
  70. });
  71. _converse.connection._dataRecv(mock.createRequest(presence));
  72. expect(view.model.occupants.length).toBe(2);
  73. const textarea = view.el.querySelector('textarea.chat-textarea');
  74. textarea.value = "hello som";
  75. // Press tab
  76. const tab_event = {
  77. 'target': textarea,
  78. 'preventDefault': function preventDefault () {},
  79. 'stopPropagation': function stopPropagation () {},
  80. 'keyCode': 9,
  81. 'key': 'Tab'
  82. }
  83. view.onKeyDown(tab_event);
  84. view.onKeyUp(tab_event);
  85. await u.waitUntil(() => view.el.querySelector('.suggestion-box__results').hidden === false);
  86. expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(1);
  87. expect(view.el.querySelector('.suggestion-box__results li').textContent).toBe('some1');
  88. const backspace_event = {
  89. 'target': textarea,
  90. 'preventDefault': function preventDefault () {},
  91. 'keyCode': 8
  92. }
  93. for (var i=0; i<3; i++) {
  94. // Press backspace 3 times to remove "som"
  95. view.onKeyDown(backspace_event);
  96. textarea.value = textarea.value.slice(0, textarea.value.length-1)
  97. view.onKeyUp(backspace_event);
  98. }
  99. await u.waitUntil(() => view.el.querySelector('.suggestion-box__results').hidden === true);
  100. presence = $pres({
  101. 'to': 'romeo@montague.lit/orchard',
  102. 'from': 'lounge@montague.lit/some2'
  103. })
  104. .c('x', {xmlns: Strophe.NS.MUC_USER})
  105. .c('item', {
  106. 'affiliation': 'none',
  107. 'jid': 'some2@montague.lit/resource',
  108. 'role': 'participant'
  109. });
  110. _converse.connection._dataRecv(mock.createRequest(presence));
  111. textarea.value = "hello s s";
  112. view.onKeyDown(tab_event);
  113. view.onKeyUp(tab_event);
  114. await u.waitUntil(() => view.el.querySelector('.suggestion-box__results').hidden === false);
  115. expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(2);
  116. const up_arrow_event = {
  117. 'target': textarea,
  118. 'preventDefault': () => (up_arrow_event.defaultPrevented = true),
  119. 'stopPropagation': function stopPropagation () {},
  120. 'keyCode': 38
  121. }
  122. view.onKeyDown(up_arrow_event);
  123. view.onKeyUp(up_arrow_event);
  124. expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(2);
  125. expect(view.el.querySelector('.suggestion-box__results li[aria-selected="false"]').textContent).toBe('some1');
  126. expect(view.el.querySelector('.suggestion-box__results li[aria-selected="true"]').textContent).toBe('some2');
  127. view.onKeyDown({
  128. 'target': textarea,
  129. 'preventDefault': function preventDefault () {},
  130. 'stopPropagation': function stopPropagation () {},
  131. 'keyCode': 13 // Enter
  132. });
  133. expect(textarea.value).toBe('hello s @some2 ');
  134. // Test that pressing tab twice selects
  135. presence = $pres({
  136. 'to': 'romeo@montague.lit/orchard',
  137. 'from': 'lounge@montague.lit/z3r0'
  138. })
  139. .c('x', {xmlns: Strophe.NS.MUC_USER})
  140. .c('item', {
  141. 'affiliation': 'none',
  142. 'jid': 'z3r0@montague.lit/resource',
  143. 'role': 'participant'
  144. });
  145. _converse.connection._dataRecv(mock.createRequest(presence));
  146. textarea.value = "hello z";
  147. view.onKeyDown(tab_event);
  148. view.onKeyUp(tab_event);
  149. await u.waitUntil(() => view.el.querySelector('.suggestion-box__results').hidden === false);
  150. view.onKeyDown(tab_event);
  151. view.onKeyUp(tab_event);
  152. await u.waitUntil(() => textarea.value === 'hello @z3r0 ');
  153. done();
  154. }));
  155. it("autocompletes when the user presses backspace",
  156. mock.initConverse(
  157. ['rosterGroupsFetched'], {},
  158. async function (done, _converse) {
  159. await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo');
  160. const view = _converse.chatboxviews.get('lounge@montague.lit');
  161. expect(view.model.occupants.length).toBe(1);
  162. const presence = $pres({
  163. 'to': 'romeo@montague.lit/orchard',
  164. 'from': 'lounge@montague.lit/some1'
  165. })
  166. .c('x', {xmlns: Strophe.NS.MUC_USER})
  167. .c('item', {
  168. 'affiliation': 'none',
  169. 'jid': 'some1@montague.lit/resource',
  170. 'role': 'participant'
  171. });
  172. _converse.connection._dataRecv(mock.createRequest(presence));
  173. expect(view.model.occupants.length).toBe(2);
  174. const textarea = view.el.querySelector('textarea.chat-textarea');
  175. textarea.value = "hello @some1 ";
  176. // Press backspace
  177. const backspace_event = {
  178. 'target': textarea,
  179. 'preventDefault': function preventDefault () {},
  180. 'stopPropagation': function stopPropagation () {},
  181. 'keyCode': 8,
  182. 'key': 'Backspace'
  183. }
  184. view.onKeyDown(backspace_event);
  185. textarea.value = "hello @some1"; // Mimic backspace
  186. view.onKeyUp(backspace_event);
  187. await u.waitUntil(() => view.el.querySelector('.suggestion-box__results').hidden === false);
  188. expect(view.el.querySelectorAll('.suggestion-box__results li').length).toBe(1);
  189. expect(view.el.querySelector('.suggestion-box__results li').textContent).toBe('some1');
  190. done();
  191. }));
  192. });