AutoComplete.spec.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import { mount } from "@vue/test-utils"
  2. import autocomplete from "../AutoComplete"
  3. const props = {
  4. placeholder: "",
  5. value: "",
  6. spellcheck: false,
  7. source: ["app", "apple", "appliance", "brian", "bob", "alice"],
  8. }
  9. // ["pp", "pple", "ppliance", "lice"]
  10. const suggestionStr = props.source
  11. .filter((str) => str.startsWith("a"))
  12. .map((str) => str.slice(1))
  13. const factory = (props) =>
  14. mount(autocomplete, {
  15. propsData: props,
  16. })
  17. describe("autocomplete", () => {
  18. test("mounts properly", () => {
  19. const wrapper = factory(props)
  20. expect(wrapper).toBeTruthy()
  21. })
  22. test("emits input event on text update [v-model compat]", async () => {
  23. const wrapper = factory(props)
  24. const input = wrapper.find("input")
  25. await input.setValue("testval")
  26. await wrapper.vm.$nextTick()
  27. expect(wrapper.emitted("input")).toBeTruthy()
  28. expect(wrapper.emitted("input").length).toEqual(1)
  29. })
  30. test("shows matching suggestions", async () => {
  31. const wrapper = factory(props)
  32. const input = wrapper.find("input")
  33. await input.setValue("a")
  34. await wrapper.vm.$nextTick()
  35. const suggestions = wrapper.findAll("li").wrappers.map((el) => el.text())
  36. suggestionStr.forEach((str) => expect(suggestions).toContain(str))
  37. })
  38. test("doesnt show non-matching suggestions", async () => {
  39. const wrapper = factory(props)
  40. const input = wrapper.find("input")
  41. await input.setValue("b")
  42. await wrapper.vm.$nextTick()
  43. const suggestions = wrapper.findAll("li").wrappers.map((el) => el.text())
  44. suggestionStr.forEach((str) => expect(suggestions).not.toContain(str))
  45. })
  46. test("updates suggestions on input", async () => {
  47. const wrapper = factory(props)
  48. const input = wrapper.find("input")
  49. await input.setValue("b")
  50. await wrapper.vm.$nextTick()
  51. const suggestions = wrapper.findAll("li").wrappers.map((el) => el.text())
  52. suggestionStr.forEach((str) => expect(suggestions).not.toContain(str))
  53. })
  54. test("applies suggestion on clicking", async () => {
  55. const wrapper = factory(props)
  56. const input = wrapper.find("input")
  57. await input.setValue("b")
  58. await wrapper.vm.$nextTick()
  59. const selectedSuggestion = wrapper.findAll("li").at(0)
  60. const selectedText = selectedSuggestion.text()
  61. await selectedSuggestion.trigger("click")
  62. await wrapper.vm.$nextTick()
  63. expect(input.element.value).toEqual(`b${selectedText}`)
  64. })
  65. test("hide selection on pressing ESC", async () => {
  66. const wrapper = factory(props)
  67. const input = wrapper.find("input")
  68. await input.setValue("b")
  69. await wrapper.vm.$nextTick()
  70. await input.trigger("keyup", { code: "Escape" })
  71. await wrapper.vm.$nextTick()
  72. expect(wrapper.find("ul").exists()).toEqual(false)
  73. })
  74. test("pressing up when nothing is selected selects the first in the list", async () => {
  75. const wrapper = factory(props)
  76. const input = wrapper.find("input")
  77. await input.setValue("a")
  78. await wrapper.vm.$nextTick()
  79. await input.trigger("keydown", {
  80. code: "ArrowUp",
  81. })
  82. await wrapper.vm.$nextTick()
  83. expect(
  84. wrapper.findAll("li").at(0).element.classList.contains("active")
  85. ).toEqual(true)
  86. })
  87. test("pressing down arrow when nothing is selected selects the first in the list", async () => {
  88. const wrapper = factory(props)
  89. const input = wrapper.find("input")
  90. await input.setValue("a")
  91. await wrapper.vm.$nextTick()
  92. await input.trigger("keydown", {
  93. code: "ArrowDown",
  94. })
  95. await wrapper.vm.$nextTick()
  96. expect(
  97. wrapper.findAll("li").at(0).element.classList.contains("active")
  98. ).toEqual(true)
  99. })
  100. test("pressing down arrow moves down the selection list", async () => {
  101. const wrapper = factory(props)
  102. const input = wrapper.find("input")
  103. await input.setValue("a")
  104. await wrapper.vm.$nextTick()
  105. await input.trigger("keydown", {
  106. code: "ArrowDown",
  107. })
  108. await wrapper.vm.$nextTick()
  109. await input.trigger("keydown", {
  110. code: "ArrowDown",
  111. })
  112. await wrapper.vm.$nextTick()
  113. expect(
  114. wrapper.findAll("li").at(1).element.classList.contains("active")
  115. ).toEqual(true)
  116. })
  117. test("pressing up arrow moves up the selection list", async () => {
  118. const wrapper = factory(props)
  119. const input = wrapper.find("input")
  120. await input.setValue("a")
  121. await wrapper.vm.$nextTick()
  122. await input.trigger("keydown", {
  123. code: "ArrowDown",
  124. })
  125. await wrapper.vm.$nextTick()
  126. await input.trigger("keydown", {
  127. code: "ArrowDown",
  128. })
  129. await wrapper.vm.$nextTick()
  130. await input.trigger("keydown", {
  131. code: "ArrowUp",
  132. })
  133. await wrapper.vm.$nextTick()
  134. expect(
  135. wrapper.findAll("li").at(0).element.classList.contains("active")
  136. ).toEqual(true)
  137. })
  138. test("pressing down arrow at the end of the list doesn't update the selection", async () => {
  139. const wrapper = factory(props)
  140. const input = wrapper.find("input")
  141. await input.setValue("b")
  142. await wrapper.vm.$nextTick()
  143. await input.trigger("keydown", {
  144. code: "ArrowDown",
  145. })
  146. await wrapper.vm.$nextTick()
  147. await input.trigger("keydown", {
  148. code: "ArrowDown",
  149. })
  150. await wrapper.vm.$nextTick()
  151. expect(
  152. wrapper.findAll("li").at(1).element.classList.contains("active")
  153. ).toEqual(true)
  154. await input.trigger("keydown", {
  155. code: "ArrowDown",
  156. })
  157. await wrapper.vm.$nextTick()
  158. expect(
  159. wrapper.findAll("li").at(1).element.classList.contains("active")
  160. ).toEqual(true)
  161. })
  162. test("pressing up arrow at the top of the list doesn't update the selection", async () => {
  163. const wrapper = factory(props)
  164. const input = wrapper.find("input")
  165. await input.setValue("b")
  166. await wrapper.vm.$nextTick()
  167. await input.trigger("keydown", {
  168. code: "ArrowDown",
  169. })
  170. await wrapper.vm.$nextTick()
  171. await input.trigger("keydown", {
  172. code: "ArrowUp",
  173. })
  174. await wrapper.vm.$nextTick()
  175. expect(
  176. wrapper.findAll("li").at(0).element.classList.contains("active")
  177. ).toEqual(true)
  178. await input.trigger("keydown", {
  179. code: "ArrowUp",
  180. })
  181. await wrapper.vm.$nextTick()
  182. expect(
  183. wrapper.findAll("li").at(0).element.classList.contains("active")
  184. ).toEqual(true)
  185. })
  186. test("pressing tab performs the current completion", async () => {
  187. const wrapper = factory(props)
  188. const input = wrapper.find("input")
  189. await input.setValue("a")
  190. await wrapper.vm.$nextTick()
  191. await input.trigger("keydown", {
  192. code: "ArrowDown",
  193. })
  194. await wrapper.vm.$nextTick()
  195. const selectedSuggestion = wrapper.find("li.active").text()
  196. await input.trigger("keydown", {
  197. code: "Tab",
  198. })
  199. await wrapper.vm.$nextTick()
  200. expect(input.element.value).toEqual(`a${selectedSuggestion}`)
  201. })
  202. test("pressing tab when nothing is selected selects the first suggestion", async () => {
  203. const wrapper = factory(props)
  204. const input = wrapper.find("input")
  205. await input.setValue("a")
  206. await wrapper.vm.$nextTick()
  207. const firstSuggestionText = wrapper.findAll("li").at(0).text()
  208. await input.trigger("keydown", {
  209. code: "Tab",
  210. })
  211. await wrapper.vm.$nextTick()
  212. expect(input.element.value).toEqual(`a${firstSuggestionText}`)
  213. })
  214. test("pressing any non-special key doesn't do anything", async () => {
  215. const wrapper = factory(props)
  216. const input = wrapper.find("input")
  217. await input.setValue("a")
  218. await wrapper.vm.$nextTick()
  219. await input.trigger("keydown", {
  220. code: "ArrowDown",
  221. })
  222. await wrapper.vm.$nextTick()
  223. const selectedSuggestion = wrapper.find("li.active").text()
  224. await input.trigger("keydown", {
  225. code: "Tab",
  226. })
  227. await wrapper.vm.$nextTick()
  228. expect(input.element.value).toEqual(`a${selectedSuggestion}`)
  229. })
  230. })