autocomplete.js 9.4 KB

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