autocomplete.js 8.9 KB

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