autocomplete.js 9.6 KB

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