autocomplete.spec.js 7.6 KB

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