quasar 2.17.6 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/dist/api/QBtnDropdown.json +1 -1
  2. package/dist/api/QDialog.json +1 -1
  3. package/dist/api/QMenu.json +1 -1
  4. package/dist/api/QOptionGroup.json +1 -1
  5. package/dist/api/QSelect.json +1 -1
  6. package/dist/api/QTable.json +1 -1
  7. package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
  8. package/dist/icon-set/eva-icons.umd.prod.js +1 -1
  9. package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
  10. package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
  11. package/dist/icon-set/fontawesome-v6-pro.umd.prod.js +1 -1
  12. package/dist/icon-set/fontawesome-v6.umd.prod.js +1 -1
  13. package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
  14. package/dist/icon-set/line-awesome.umd.prod.js +1 -1
  15. package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
  16. package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
  17. package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
  18. package/dist/icon-set/material-icons.umd.prod.js +1 -1
  19. package/dist/icon-set/material-symbols-outlined.umd.prod.js +1 -1
  20. package/dist/icon-set/material-symbols-rounded.umd.prod.js +1 -1
  21. package/dist/icon-set/material-symbols-sharp.umd.prod.js +1 -1
  22. package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
  23. package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
  24. package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
  25. package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
  26. package/dist/icon-set/mdi-v7.umd.prod.js +1 -1
  27. package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
  28. package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
  29. package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
  30. package/dist/icon-set/svg-fontawesome-v6.umd.prod.js +1 -1
  31. package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
  32. package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
  33. package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
  34. package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
  35. package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
  36. package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
  37. package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
  38. package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
  39. package/dist/icon-set/svg-material-symbols-outlined.umd.prod.js +1 -1
  40. package/dist/icon-set/svg-material-symbols-rounded.umd.prod.js +1 -1
  41. package/dist/icon-set/svg-material-symbols-sharp.umd.prod.js +1 -1
  42. package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
  43. package/dist/icon-set/svg-mdi-v7.umd.prod.js +1 -1
  44. package/dist/icon-set/svg-themify.umd.prod.js +1 -1
  45. package/dist/icon-set/themify.umd.prod.js +1 -1
  46. package/dist/lang/ar-TN.umd.prod.js +2 -2
  47. package/dist/lang/ar.umd.prod.js +2 -2
  48. package/dist/lang/az-Latn.umd.prod.js +2 -2
  49. package/dist/lang/bg.umd.prod.js +2 -2
  50. package/dist/lang/bn.umd.prod.js +2 -2
  51. package/dist/lang/bs-BA.umd.prod.js +2 -2
  52. package/dist/lang/ca.umd.prod.js +2 -2
  53. package/dist/lang/cs.umd.prod.js +2 -2
  54. package/dist/lang/da.umd.prod.js +2 -2
  55. package/dist/lang/de-CH.umd.prod.js +2 -2
  56. package/dist/lang/de-DE.umd.prod.js +2 -2
  57. package/dist/lang/de.umd.prod.js +2 -2
  58. package/dist/lang/el.umd.prod.js +2 -2
  59. package/dist/lang/en-GB.umd.prod.js +2 -2
  60. package/dist/lang/en-US.umd.prod.js +2 -2
  61. package/dist/lang/eo.umd.prod.js +2 -2
  62. package/dist/lang/es.umd.prod.js +2 -2
  63. package/dist/lang/et.umd.prod.js +2 -2
  64. package/dist/lang/eu.umd.prod.js +2 -2
  65. package/dist/lang/fa-IR.umd.prod.js +2 -2
  66. package/dist/lang/fa.umd.prod.js +2 -2
  67. package/dist/lang/fi.umd.prod.js +2 -2
  68. package/dist/lang/fr.umd.prod.js +2 -2
  69. package/dist/lang/gn.umd.prod.js +2 -2
  70. package/dist/lang/he.umd.prod.js +2 -2
  71. package/dist/lang/hi.umd.prod.js +2 -2
  72. package/dist/lang/hr.umd.prod.js +2 -2
  73. package/dist/lang/hu.umd.prod.js +2 -2
  74. package/dist/lang/id.umd.prod.js +2 -2
  75. package/dist/lang/is.umd.prod.js +2 -2
  76. package/dist/lang/it.umd.prod.js +2 -2
  77. package/dist/lang/ja.umd.prod.js +2 -2
  78. package/dist/lang/kk.umd.prod.js +2 -2
  79. package/dist/lang/km.umd.prod.js +2 -2
  80. package/dist/lang/ko-KR.umd.prod.js +2 -2
  81. package/dist/lang/kur-CKB.umd.prod.js +2 -2
  82. package/dist/lang/lt.umd.prod.js +2 -2
  83. package/dist/lang/lu.umd.prod.js +2 -2
  84. package/dist/lang/lv.umd.prod.js +2 -2
  85. package/dist/lang/mk.umd.prod.js +2 -2
  86. package/dist/lang/ml.umd.prod.js +2 -2
  87. package/dist/lang/mm.umd.prod.js +2 -2
  88. package/dist/lang/ms-MY.umd.prod.js +2 -2
  89. package/dist/lang/ms.umd.prod.js +2 -2
  90. package/dist/lang/my.umd.prod.js +2 -2
  91. package/dist/lang/nb-NO.umd.prod.js +2 -2
  92. package/dist/lang/nl.umd.prod.js +2 -2
  93. package/dist/lang/pl.umd.prod.js +2 -2
  94. package/dist/lang/pt-BR.umd.prod.js +2 -2
  95. package/dist/lang/pt.umd.prod.js +2 -2
  96. package/dist/lang/ro.umd.prod.js +2 -2
  97. package/dist/lang/ru.umd.prod.js +2 -2
  98. package/dist/lang/sk.umd.prod.js +2 -2
  99. package/dist/lang/sl.umd.prod.js +2 -2
  100. package/dist/lang/sm.umd.prod.js +2 -2
  101. package/dist/lang/sr-CYR.umd.prod.js +2 -2
  102. package/dist/lang/sr.umd.prod.js +2 -2
  103. package/dist/lang/sv.umd.prod.js +2 -2
  104. package/dist/lang/ta.umd.prod.js +2 -2
  105. package/dist/lang/th.umd.prod.js +2 -2
  106. package/dist/lang/tl.umd.prod.js +2 -2
  107. package/dist/lang/tr.umd.prod.js +2 -2
  108. package/dist/lang/ug.umd.prod.js +1 -1
  109. package/dist/lang/uk.umd.prod.js +2 -2
  110. package/dist/lang/ur-PK.umd.prod.js +7 -0
  111. package/dist/lang/uz-Cyrl.umd.prod.js +2 -2
  112. package/dist/lang/uz-Latn.umd.prod.js +2 -2
  113. package/dist/lang/vi.umd.prod.js +2 -2
  114. package/dist/lang/zh-CN.umd.prod.js +2 -2
  115. package/dist/lang/zh-TW.umd.prod.js +2 -2
  116. package/dist/quasar.client.js +252 -179
  117. package/dist/quasar.css +1 -1
  118. package/dist/quasar.prod.css +1 -1
  119. package/dist/quasar.rtl.css +1 -1
  120. package/dist/quasar.rtl.prod.css +1 -1
  121. package/dist/quasar.sass +2 -2
  122. package/dist/quasar.server.prod.cjs +36 -36
  123. package/dist/quasar.server.prod.js +37 -37
  124. package/dist/quasar.umd.js +252 -179
  125. package/dist/quasar.umd.prod.js +42 -42
  126. package/dist/types/index.d.ts +86 -17
  127. package/dist/vetur/quasar-attributes.json +1 -1
  128. package/dist/vetur/quasar-tags.json +1 -1
  129. package/dist/web-types/web-types.json +1 -1
  130. package/lang/ar-TN.js +6 -0
  131. package/lang/ar.js +6 -0
  132. package/lang/az-Latn.js +6 -0
  133. package/lang/bg.js +6 -0
  134. package/lang/bn.js +6 -0
  135. package/lang/bs-BA.js +6 -0
  136. package/lang/ca.js +6 -0
  137. package/lang/cs.js +6 -0
  138. package/lang/da.js +6 -0
  139. package/lang/de-CH.js +6 -0
  140. package/lang/de-DE.js +6 -0
  141. package/lang/de.js +6 -0
  142. package/lang/el.js +6 -0
  143. package/lang/en-GB.js +6 -0
  144. package/lang/en-US.js +6 -0
  145. package/lang/eo.js +6 -0
  146. package/lang/es.js +6 -0
  147. package/lang/et.js +6 -0
  148. package/lang/eu.js +6 -0
  149. package/lang/fa-IR.js +6 -0
  150. package/lang/fa.js +6 -0
  151. package/lang/fi.js +6 -0
  152. package/lang/fr.js +6 -0
  153. package/lang/gn.js +6 -0
  154. package/lang/he.js +6 -0
  155. package/lang/hi.js +6 -0
  156. package/lang/hr.js +6 -0
  157. package/lang/hu.js +6 -0
  158. package/lang/id.js +6 -0
  159. package/lang/index.json +1 -1
  160. package/lang/is.js +6 -0
  161. package/lang/it.js +6 -0
  162. package/lang/ja.js +6 -0
  163. package/lang/kk.js +6 -0
  164. package/lang/km.js +6 -0
  165. package/lang/ko-KR.js +6 -0
  166. package/lang/kur-CKB.js +6 -0
  167. package/lang/lt.js +6 -0
  168. package/lang/lu.js +6 -0
  169. package/lang/lv.js +6 -0
  170. package/lang/mk.js +6 -0
  171. package/lang/ml.js +6 -0
  172. package/lang/mm.js +6 -0
  173. package/lang/ms-MY.js +6 -0
  174. package/lang/ms.js +6 -0
  175. package/lang/my.js +6 -0
  176. package/lang/nb-NO.js +6 -0
  177. package/lang/nl.js +6 -0
  178. package/lang/pl.js +6 -0
  179. package/lang/pt-BR.js +6 -0
  180. package/lang/pt.js +6 -0
  181. package/lang/ro.js +6 -0
  182. package/lang/ru.js +6 -0
  183. package/lang/sk.js +6 -0
  184. package/lang/sl.js +6 -0
  185. package/lang/sm.js +6 -0
  186. package/lang/sr-CYR.js +6 -0
  187. package/lang/sr.js +6 -0
  188. package/lang/sv.js +6 -0
  189. package/lang/ta.js +6 -0
  190. package/lang/th.js +6 -0
  191. package/lang/tl.js +6 -0
  192. package/lang/tr.js +6 -0
  193. package/lang/uk.js +6 -0
  194. package/lang/ur-PK.js +111 -0
  195. package/lang/uz-Cyrl.js +6 -0
  196. package/lang/uz-Latn.js +6 -0
  197. package/lang/vi.js +6 -0
  198. package/lang/zh-CN.js +6 -0
  199. package/lang/zh-TW.js +6 -0
  200. package/package.json +4 -4
  201. package/src/components/breadcrumbs/QBreadcrumbs.js +2 -2
  202. package/src/components/btn/QBtn.js +7 -8
  203. package/src/components/btn-dropdown/QBtnDropdown.js +10 -4
  204. package/src/components/btn-dropdown/QBtnDropdown.json +21 -0
  205. package/src/components/color/QColor.js +1 -1
  206. package/src/components/date/QDate.js +14 -7
  207. package/src/components/dialog/QDialog.js +2 -2
  208. package/src/components/dialog/QDialog.json +1 -1
  209. package/src/components/drawer/QDrawer.js +3 -5
  210. package/src/components/editor/QEditor.js +1 -1
  211. package/src/components/editor/editor-caret.js +1 -1
  212. package/src/components/editor/editor-utils.js +2 -2
  213. package/src/components/expansion-item/QExpansionItem.js +6 -3
  214. package/src/components/fab/QFab.js +2 -2
  215. package/src/components/form/QForm.js +2 -2
  216. package/src/components/form/QFormChildMixin.js +6 -4
  217. package/src/components/icon/QIcon.js +2 -2
  218. package/src/components/infinite-scroll/QInfiniteScroll.js +2 -4
  219. package/src/components/input/QInput.js +3 -3
  220. package/src/components/item/QItem.js +1 -1
  221. package/src/components/menu/QMenu.js +8 -5
  222. package/src/components/menu/QMenu.json +8 -1
  223. package/src/components/option-group/QOptionGroup.json +1 -17
  224. package/src/components/pagination/QPagination.js +8 -4
  225. package/src/components/parallax/QParallax.js +1 -1
  226. package/src/components/popup-edit/QPopupEdit.js +2 -2
  227. package/src/components/pull-to-refresh/QPullToRefresh.js +1 -1
  228. package/src/components/rating/QRating.sass +1 -1
  229. package/src/components/resize-observer/QResizeObserver.js +1 -1
  230. package/src/components/scroll-observer/QScrollObserver.js +2 -2
  231. package/src/components/select/QSelect.js +8 -6
  232. package/src/components/select/QSelect.json +2 -2
  233. package/src/components/slide-transition/QSlideTransition.js +2 -2
  234. package/src/components/stepper/StepHeader.js +1 -1
  235. package/src/components/table/QTable.js +84 -36
  236. package/src/components/table/QTable.json +138 -0
  237. package/src/components/table/QTr.js +4 -1
  238. package/src/components/table/table-sort.js +1 -1
  239. package/src/components/tabs/QTabs.js +2 -2
  240. package/src/components/tabs/use-tab.js +4 -4
  241. package/src/components/time/QTime.js +1 -1
  242. package/src/components/tree/QTree.js +2 -3
  243. package/src/components/virtual-scroll/use-virtual-scroll.js +3 -3
  244. package/src/composables/private.use-field/use-field.js +5 -5
  245. package/src/composables/private.use-file/use-file.js +6 -3
  246. package/src/composables/private.use-model-toggle/use-model-toggle.js +2 -2
  247. package/src/composables/private.use-refocus-target/use-refocus-target.js +6 -5
  248. package/src/composables/private.use-validate/use-validate.js +1 -1
  249. package/src/directives/intersection/Intersection.js +2 -2
  250. package/src/directives/morph/Morph.js +2 -2
  251. package/src/directives/mutation/Mutation.js +2 -2
  252. package/src/directives/touch-hold/TouchHold.js +2 -2
  253. package/src/directives/touch-pan/TouchPan.js +2 -2
  254. package/src/directives/touch-repeat/TouchRepeat.js +3 -3
  255. package/src/directives/touch-swipe/TouchSwipe.js +3 -3
  256. package/src/plugins/lang/Lang.test.js +12 -0
  257. package/src/plugins/loading/Loading.js +1 -1
  258. package/src/plugins/notify/Notify.js +1 -1
  259. package/src/plugins/private.body/Body.js +1 -1
  260. package/src/plugins/private.history/History.js +1 -1
  261. package/src/plugins/screen/Screen.js +1 -1
  262. package/src/utils/morph/morph.js +13 -10
  263. package/src/utils/open-url/open-url.js +3 -3
  264. package/src/utils/private.dialog/create-dialog.js +2 -2
  265. package/src/utils/private.portal/portal.js +1 -1
  266. package/src/components/date/__tests__/QDate.cy.js +0 -189
  267. package/src/components/date/__tests__/use-datetime.cy.js +0 -83
  268. package/src/components/editor/__tests__/QEditor.cy.js +0 -195
  269. package/src/components/field/__tests__/QField.cy.js +0 -156
  270. package/src/components/input/__tests__/QInput.cy.js +0 -786
  271. package/src/components/input/__tests__/use-mask.cy.js +0 -124
  272. package/src/components/menu/__tests__/QMenu.cy.js +0 -634
  273. package/src/components/menu/__tests__/WrapperOne.vue +0 -51
  274. package/src/components/menu/__tests__/WrapperTwo.vue +0 -38
  275. package/src/components/select/__tests__/QSelect.cy.js +0 -2018
  276. package/src/components/table/__tests__/QTable.cy.js +0 -635
  277. package/src/components/table/__tests__/QTd.cy.js +0 -35
  278. package/src/components/table/__tests__/QTh.cy.js +0 -27
  279. package/src/components/table/__tests__/QTr.cy.js +0 -27
  280. package/src/components/tabs/__tests__/QTab.cy.js +0 -79
  281. package/src/components/tabs/__tests__/QTabs.cy.js +0 -147
  282. package/src/components/uploader/__tests__/QUploader.cy.js +0 -191
  283. package/src/composables/__tests__/FieldWrapper.vue +0 -54
  284. package/src/composables/__tests__/use-anchor.cy.js +0 -98
  285. package/src/composables/__tests__/use-field.cy.js +0 -547
  286. package/src/composables/__tests__/use-file.cy.js +0 -69
  287. package/src/composables/__tests__/use-fullscreen.cy.js +0 -37
  288. package/src/composables/__tests__/use-model-toggle.cy.js +0 -350
  289. package/src/composables/__tests__/use-portal.cy.js +0 -4
  290. package/src/composables/__tests__/use-router-link.cy.js +0 -55
  291. package/src/composables/__tests__/use-validate.cy.js +0 -257
@@ -1,2018 +0,0 @@
1
- /* eslint-disable no-unused-expressions */
2
- import { vModelAdapter } from '@quasar/quasar-app-extension-testing-e2e-cypress'
3
- import { h, ref } from 'vue'
4
- import QSelect from '../QSelect.js'
5
-
6
- function getHostElement (extendedSelector = '') {
7
- // A majority of tests click on the select, so we ensure the select is visible before the click happens.
8
- // See https://github.com/cypress-io/cypress/discussions/14889
9
- // See https://www.cypress.io/blog/2020/08/17/when-can-the-test-navigate#visible-elements
10
- return extendedSelector ? cy.get(`.q-select ${ extendedSelector }`) : cy.get('.q-select').should('be.visible')
11
- }
12
-
13
- function mountQSelect (options = {}) {
14
- if (!options.props?.modelValue) {
15
- options.props = {
16
- modelValue: null,
17
- ...options.props ?? {}
18
- }
19
- }
20
-
21
- return cy.mount(QSelect, options)
22
- }
23
-
24
- // QSelect does not set the `data-cy` attribute on the root element, but on the `.q-field__native` element
25
- // This means we cannot use data-cy everywhere, but instead use a custom class `select-root` for this purpose
26
- describe('QSelect API', () => {
27
- describe('Props', () => {
28
- describe('Category: behavior', () => {
29
- describe('(prop): fill-input', () => {
30
- it.skip(' ', () => {
31
- //
32
- })
33
- })
34
- describe('(prop): new-value-mode', () => {
35
- it.skip(' ', () => {
36
- //
37
- })
38
- })
39
- describe('(prop): autocomplete', () => {
40
- it.skip(' ', () => {
41
- //
42
- })
43
- })
44
- describe('(prop): transition-show', () => {
45
- it.skip(' ', () => {
46
- //
47
- })
48
- })
49
- describe('(prop): transition-hide', () => {
50
- it.skip(' ', () => {
51
- //
52
- })
53
- })
54
- describe('(prop): transition-duration', () => {
55
- it.skip(' ', () => {
56
- //
57
- })
58
- })
59
- describe('(prop): behavior', () => {
60
- it.skip(' ', () => {
61
- //
62
- })
63
- })
64
- })
65
-
66
- describe('Category: content', () => {
67
- describe('(prop): dropdown-icon', () => {
68
- it('should use the dropdown-icon supplied', () => {
69
- const icon = 'map'
70
- mountQSelect({
71
- props: {
72
- dropdownIcon: icon
73
- }
74
- })
75
- getHostElement()
76
- .get(`div:contains(${ icon })`)
77
- .should('exist')
78
- })
79
- })
80
-
81
- describe('(prop): use-input', () => {
82
- it('should render an input inside the select', () => {
83
- mountQSelect({
84
- props: {
85
- useInput: true
86
- }
87
- })
88
- getHostElement()
89
- .get('input')
90
- .should('exist')
91
- })
92
-
93
- it('should render an input, but it shouldn\'t be visible', () => {
94
- mountQSelect()
95
-
96
- getHostElement()
97
- .get('input')
98
- .should('not.be.visible')
99
- })
100
-
101
- it.skip('should not render an input by default', () => {
102
- // Native input is now always rendered, due to having a target for autocomplete
103
- // Refer to commit: https://github.com/quasarframework/quasar/commit/21a3af0dfe01bac0da617737562b599edee397a2
104
- })
105
- })
106
-
107
- describe('(prop): input-debounce', () => {
108
- it('should use an input-debounce of 500ms by default', () => {
109
- const fn = cy.stub()
110
- const text = 'Hello there'
111
- mountQSelect({
112
- props: {
113
- useInput: true,
114
- onFilter: fn
115
- }
116
- })
117
- getHostElement()
118
- .get('input')
119
- .type(text)
120
- .then(() => {
121
- expect(fn).not.to.be.calledWith(text)
122
- })
123
- .wait(500)
124
- .then(() => {
125
- expect(fn).to.be.calledWith(text)
126
- })
127
- })
128
-
129
- it('should use a custom input-debounce', () => {
130
- const fn = cy.stub()
131
- const text = 'Hello there'
132
- mountQSelect({
133
- props: {
134
- useInput: true,
135
- onFilter: fn,
136
- inputDebounce: 800
137
- }
138
- })
139
- getHostElement()
140
- .get('input')
141
- .type(text)
142
- .wait(500)
143
- .then(() => {
144
- expect(fn).not.to.be.calledWith(text)
145
- })
146
- .wait(300)
147
- .then(() => {
148
- expect(fn).to.be.calledWith(text)
149
- })
150
- })
151
- })
152
- })
153
-
154
- describe('Category: content|behavior', () => {
155
- describe('(prop): hide-dropdown-icon', () => {
156
- it('should show the dropdown-icon when this property is not supplied', () => {
157
- mountQSelect()
158
- getHostElement()
159
- .get('.q-icon')
160
- .should('exist')
161
- })
162
-
163
- it('should hide the dropdown-icon when this property is true', () => {
164
- mountQSelect({
165
- props: {
166
- hideDropdownIcon: true
167
- }
168
- })
169
- getHostElement()
170
- .get('.q-icon')
171
- .should('not.exist')
172
- })
173
- })
174
- })
175
-
176
- describe('Category: general', () => {
177
- describe('(prop): tabindex', () => {
178
- it('should have a default tabindex of 0', () => {
179
- mountQSelect()
180
- getHostElement('[tabindex="0"]')
181
- .should('exist')
182
- })
183
-
184
- it('should set the tabindex to the supplied value', () => {
185
- const tabindex = 2
186
- mountQSelect({
187
- props: {
188
- tabindex
189
- }
190
- })
191
- getHostElement(`[tabindex="${ tabindex }"]`)
192
- .should('exist')
193
- getHostElement('[tabindex="0"]')
194
- .should('not.exist')
195
- })
196
- })
197
- })
198
-
199
- describe('Category: model', () => {
200
- describe('(prop): model-value', () => {
201
- it('should have the option selected passed in the model-value', () => {
202
- const modelValue = 'Option 1'
203
- mountQSelect({
204
- props: {
205
- modelValue,
206
- options: [ 'Option 1', 'Option 2', 'Option 3' ]
207
- }
208
- })
209
- getHostElement()
210
- .should('include.text', modelValue)
211
- })
212
- })
213
-
214
- describe('(prop): emit-value', () => {
215
- it('should emit the value under the value key, if options are objects', () => {
216
- const fn = cy.stub()
217
- mountQSelect({
218
- props: {
219
- emitValue: true,
220
- 'onUpdate:modelValue': fn,
221
- options: [ { label: 'Option 1', value: 1 }, { label: 'Option 2', value: 2 } ]
222
- }
223
- })
224
- getHostElement()
225
- .click()
226
- cy.get('.q-menu')
227
- .contains('Option 1')
228
- .should('be.visible')
229
- .click()
230
- cy.get('.q-menu')
231
- .then(() => {
232
- expect(fn).to.have.been.calledWith(1)
233
- })
234
- })
235
-
236
- it('should emit the whole object by default if options are objects', () => {
237
- const fn = cy.stub()
238
- const options = [ { label: 'Option 1', value: 1 }, { label: 'Option 2', value: 2 } ]
239
- mountQSelect({
240
- props: {
241
- 'onUpdate:modelValue': fn,
242
- options
243
- }
244
- })
245
- getHostElement()
246
- .click()
247
- cy.get('.q-menu')
248
- .contains('Option 1')
249
- .should('be.visible')
250
- .click()
251
- cy.get('.q-menu')
252
- .then(() => {
253
- expect(fn).to.have.been.calledWith(options[ 0 ])
254
- })
255
- })
256
- })
257
- })
258
-
259
- describe('Category: model|selection', () => {
260
- describe('(prop): multiple', () => {
261
- it('should select only one option by default', () => {
262
- const options = [ 'Option 1', 'Option 2' ]
263
- const model = ref(null)
264
- mountQSelect({
265
- props: {
266
- ...vModelAdapter(model),
267
- options
268
- }
269
- })
270
-
271
- getHostElement().click()
272
- cy.withinSelectMenu(() => {
273
- cy.contains('Option 1')
274
- .should('be.visible')
275
- .click()
276
- cy.contains('Option 1')
277
- .then(() => {
278
- expect(model.value).to.equal(options[ 0 ])
279
- })
280
- })
281
-
282
- getHostElement().click()
283
- cy.withinSelectMenu(() => {
284
- cy.contains('Option 2')
285
- .should('be.visible')
286
- .click()
287
- cy.contains('Option 2')
288
- .then(() => {
289
- expect(model.value).to.equal(options[ 1 ])
290
- })
291
- })
292
- })
293
-
294
- it('should select multiple options if multiple is true', () => {
295
- const options = [ 'Option 1', 'Option 2' ]
296
- const model = ref([])
297
- mountQSelect({
298
- props: {
299
- ...vModelAdapter(model),
300
- multiple: true,
301
- options
302
- }
303
- })
304
-
305
- getHostElement().click()
306
- cy.withinSelectMenu({
307
- persistent: true,
308
- fn: () => {
309
- cy.contains('Option 1')
310
- .should('be.visible')
311
- .click()
312
- cy.contains('Option 1')
313
- .then(() => {
314
- expect(model.value).to.eql([ options[ 0 ] ])
315
- })
316
-
317
- cy.contains('Option 2')
318
- .should('be.visible')
319
- .click()
320
- cy.contains('Option 2')
321
- .then(() => {
322
- expect(model.value).to.eql(options)
323
- })
324
- }
325
- })
326
- })
327
- })
328
- })
329
-
330
- describe('Category: options', () => {
331
- describe('(prop): options', () => {
332
- it('should show each option when opening the dropdown', () => {
333
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
334
- mountQSelect({
335
- props: {
336
- options
337
- }
338
- })
339
- getHostElement()
340
- .click()
341
- cy.get('.q-menu')
342
- .children()
343
- .should('contain', options[ 0 ])
344
- .and('contain', options[ 1 ])
345
- .and('contain', options[ 2 ])
346
- .and('contain', options[ 3 ])
347
- })
348
- })
349
-
350
- describe('(prop): option-value', () => {
351
- it('should use the value key as option-value by default', () => {
352
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
353
- const model = ref(null)
354
- mountQSelect({
355
- props: {
356
- ...vModelAdapter(model),
357
- options,
358
- emitValue: true
359
- }
360
- })
361
- getHostElement()
362
- .click()
363
- cy.get('.q-menu')
364
- .contains(options[ 0 ].label)
365
- .should('be.visible')
366
- .click()
367
- cy.get('.q-menu')
368
- .then(() => {
369
- expect(model.value).to.equal(options[ 0 ].value)
370
- })
371
- })
372
-
373
- it('should use a custom key supplied by option-value', () => {
374
- const options = [ { label: 'Option one', test: 1 }, { label: 'Option two', test: 2 } ]
375
- const model = ref(null)
376
- mountQSelect({
377
- props: {
378
- ...vModelAdapter(model),
379
- options,
380
- emitValue: true,
381
- optionValue: 'test'
382
- }
383
- })
384
- getHostElement()
385
- .click()
386
- cy.get('.q-menu')
387
- .contains(options[ 0 ].label)
388
- .should('be.visible')
389
- .click()
390
- cy.get('.q-menu')
391
- .then(() => {
392
- expect(model.value).to.equal(options[ 0 ].test)
393
- })
394
- })
395
-
396
- it('should accept a function as option-value', () => {
397
- const options = [ { label: 'Option one', test: 1 }, { label: 'Option two', test: 2 } ]
398
- const model = ref(null)
399
- mountQSelect({
400
- props: {
401
- ...vModelAdapter(model),
402
- options,
403
- emitValue: true,
404
- optionValue: (val) => val.test
405
- }
406
- })
407
- getHostElement()
408
- .click()
409
- cy.get('.q-menu')
410
- .contains(options[ 0 ].label)
411
- .should('be.visible')
412
- .click()
413
- cy.get('.q-menu')
414
- .then(() => {
415
- expect(model.value).to.equal(options[ 0 ].test)
416
- })
417
- })
418
- })
419
-
420
- describe('(prop): option-label', () => {
421
- it('should use the "label" key by default as option-label', () => {
422
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
423
- mountQSelect({
424
- props: {
425
- options
426
- }
427
- })
428
- getHostElement()
429
- .click()
430
- cy.get('.q-menu')
431
- .children()
432
- .should('contain', options[ 0 ].label)
433
- .and('contain', options[ 1 ].label)
434
- })
435
-
436
- it('should use the key supplied by option-label', () => {
437
- const options = [ { test: 'Option one', value: 1 }, { test: 'Option two', value: 2 } ]
438
- mountQSelect({
439
- props: {
440
- options,
441
- optionLabel: 'test'
442
- }
443
- })
444
- getHostElement()
445
- .click()
446
- cy.get('.q-menu')
447
- .children()
448
- .should('contain', options[ 0 ].test)
449
- .and('contain', options[ 1 ].test)
450
- })
451
-
452
- it('should accept a function as option-label', () => {
453
- const options = [ { test: 'Option one', value: 1 }, { test: 'Option two', value: 2 } ]
454
- mountQSelect({
455
- props: {
456
- options,
457
- optionLabel: (item) => (item === null ? 'Null' : item.test)
458
- }
459
- })
460
- getHostElement()
461
- .click()
462
- cy.get('.q-menu')
463
- .children()
464
- .should('contain', options[ 0 ].test)
465
- .and('contain', options[ 1 ].test)
466
- })
467
- })
468
- describe('(prop): option-disable', () => {
469
- it('should use the "disable" key by default as option-disable', () => {
470
- const options = [ { label: 'Option one', value: 1, disable: true }, { label: 'Option two', value: 2, disable: true } ]
471
- mountQSelect({
472
- props: {
473
- options
474
- }
475
- })
476
- getHostElement()
477
- .click()
478
- cy.get('.q-menu')
479
- .get('[role="option"][aria-disabled="true"]')
480
- .should('have.length', 2)
481
- })
482
-
483
- it('should use the key supplied by option-disable', () => {
484
- const options = [ { label: 'Option one', value: 1, test: true }, { label: 'Option two', value: 2, disable: true } ]
485
- mountQSelect({
486
- props: {
487
- options,
488
- optionDisable: 'test'
489
- }
490
- })
491
- getHostElement()
492
- .click()
493
- cy.get('.q-menu')
494
- .get('[role="option"][aria-disabled="true"]')
495
- .should('have.length', 1)
496
- .should('have.text', options[ 0 ].label)
497
- })
498
-
499
- it('should accept a function as option-disable', () => {
500
- const options = [ { label: 'Option one', value: 1, test: true }, { label: 'Option two', value: 2, disable: true } ]
501
- mountQSelect({
502
- props: {
503
- options,
504
- optionDisable: (item) => (item === null ? true : item.test)
505
- }
506
- })
507
- getHostElement()
508
- .click()
509
- cy.get('.q-menu')
510
- .get('[role="option"][aria-disabled="true"]')
511
- .should('have.length', 1)
512
- .should('have.text', options[ 0 ].label)
513
- })
514
- })
515
-
516
- describe('(prop): options-dense', () => {
517
- it('should show options list dense', () => {
518
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
519
- mountQSelect({
520
- props: {
521
- options,
522
- optionsDense: true
523
- }
524
- })
525
- getHostElement()
526
- .click()
527
- cy.get('.q-menu')
528
- .get('.q-item')
529
- .should('have.class', 'q-item--dense')
530
- })
531
- })
532
-
533
- describe('(prop): options-dark', () => {
534
- it('should show options list in dark mode', () => {
535
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
536
- mountQSelect({
537
- props: {
538
- options,
539
- optionsDark: true
540
- }
541
- })
542
- getHostElement()
543
- .click()
544
- cy.get('.q-menu')
545
- .get('.q-item')
546
- .should('have.class', 'q-item--dark')
547
- })
548
- })
549
-
550
- describe('(prop): options-selected-class', () => {
551
- it('should have text-{color} applied as selected by default', () => {
552
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
553
- mountQSelect({
554
- props: {
555
- options,
556
- modelValue: 'Option 1',
557
- color: 'orange'
558
- }
559
- })
560
- getHostElement()
561
- .click()
562
- cy.get('.q-menu')
563
- .contains('[role="option"]', options[ 0 ])
564
- .should('have.class', 'text-orange')
565
- })
566
-
567
- it('should not have default active class when passed option is empty', () => {
568
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
569
- mountQSelect({
570
- props: {
571
- options,
572
- modelValue: 'Option 1',
573
- optionsSelectedClass: '',
574
- color: 'orange'
575
- }
576
- })
577
- getHostElement()
578
- .click()
579
- cy.get('.q-menu')
580
- .contains('[role="option"]', options[ 0 ])
581
- .should('not.have.class', 'text-orange')
582
- })
583
-
584
- it('should have class name supplied by options-selected-class on active item', () => {
585
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
586
- mountQSelect({
587
- props: {
588
- options,
589
- modelValue: 'Option 1',
590
- optionsSelectedClass: 'test-class',
591
- color: 'orange'
592
- }
593
- })
594
- getHostElement()
595
- .click()
596
- cy.get('.q-menu')
597
- .contains('[role="option"]', options[ 0 ])
598
- .should('not.have.class', 'text-orange')
599
- .should('have.class', 'test-class')
600
- cy.get('.q-menu')
601
- .contains('[role="option"]', options[ 1 ])
602
- .should('not.have.class', 'text-orange')
603
- .should('not.have.class', 'test-class')
604
- })
605
- })
606
-
607
- describe('(prop): options-html', () => {
608
- it('should not render options with html by default', () => {
609
- const options = [ '<b style="color: red">Option 1</b>', 'Option 2' ]
610
- mountQSelect({
611
- props: {
612
- options
613
- }
614
- })
615
- getHostElement()
616
- .click()
617
- cy.get('.q-menu')
618
- .contains('Option 1')
619
- .should('have.color', 'black')
620
- .should('not.have.css', 'font-weight', '700')
621
- })
622
-
623
- it('should render options with html when options-html is true', () => {
624
- const options = [ '<b style="color: red">Option 1</b>', 'Option 2' ]
625
- mountQSelect({
626
- props: {
627
- options,
628
- optionsHtml: true
629
- }
630
- })
631
- getHostElement()
632
- .click()
633
- cy.get('.q-menu')
634
- .contains('Option 1')
635
- .should('have.color', 'red')
636
- .should('have.css', 'font-weight', '700')
637
- })
638
- })
639
-
640
- describe('(prop): options-cover', () => {
641
- it('should make the popup menu cover the select', (done) => {
642
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
643
- mountQSelect({
644
- props: {
645
- options,
646
- optionsCover: true
647
- }
648
- })
649
- getHostElement()
650
- .click()
651
- cy.get('.q-menu').should('be.visible')
652
- getHostElement()
653
- .isNotActionable(done)
654
- })
655
-
656
- it('should not make the popup menu cover the select when use-input is used', () => {
657
- const options = [ 'Option 1', 'Option 2', 'Option 3', 'Option 4' ]
658
- mountQSelect({
659
- props: {
660
- options,
661
- optionsCover: true,
662
- useInput: true
663
- }
664
- })
665
- getHostElement()
666
- .click()
667
- .click({ timeout: 100 })
668
- })
669
- })
670
-
671
- describe('(prop): menu-shrink', () => {
672
- it('should shrink the menu', () => {
673
- const options = [ '1', '2', '3', '4' ]
674
- mountQSelect({
675
- props: {
676
- options,
677
- menuShrink: true
678
- }
679
- })
680
- let selectWidth = 0
681
- getHostElement()
682
- .then(($el) => {
683
- selectWidth = $el[ 0 ].clientWidth
684
- })
685
- .click()
686
- cy.get('.q-menu')
687
- .then(($el) => {
688
- expect($el[ 0 ].clientWidth).to.below(selectWidth)
689
- })
690
- })
691
- })
692
-
693
- describe('(prop): map-options', () => {
694
- it('should display the label of the selected value instead of the value itself', () => {
695
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
696
- mountQSelect({
697
- props: {
698
- options,
699
- modelValue: 1,
700
- mapOptions: true
701
- }
702
- })
703
- getHostElement()
704
- .contains(options[ 0 ].label)
705
- })
706
-
707
- it('should display the selected value as string by default', () => {
708
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
709
- mountQSelect({
710
- props: {
711
- options,
712
- modelValue: 1
713
- }
714
- })
715
- getHostElement()
716
- .contains(options[ 0 ].value)
717
- })
718
- })
719
- })
720
-
721
- describe('Category: position', () => {
722
- describe.skip('(prop): menu-anchor', () => {
723
- // This is a menu property which is tested in QMenu.spec.js
724
- })
725
-
726
- describe.skip('(prop): menu-self', () => {
727
- // This is a menu property which is tested in QMenu.spec.js
728
- })
729
-
730
- describe.skip('(prop): menu-offset', () => {
731
- // This is a menu property which is tested in QMenu.spec.js
732
- })
733
- })
734
-
735
- describe('Category: selection', () => {
736
- describe('(prop): display-value', () => {
737
- it('should override the default selection string', () => {
738
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
739
- mountQSelect({
740
- props: {
741
- options,
742
- modelValue: 1,
743
- displayValue: 'Test'
744
- }
745
- })
746
- getHostElement()
747
- .should('not.contain', options[ 0 ].value)
748
- .should('contain', 'Test')
749
- })
750
-
751
- it('should not override the default selection string when using `use-chips`', () => {
752
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
753
- mountQSelect({
754
- props: {
755
- options,
756
- modelValue: 1,
757
- displayValue: 'Test',
758
- useChips: true
759
- }
760
- })
761
- getHostElement()
762
- .should('contain', options[ 0 ].value)
763
- .should('not.contain', 'Test')
764
- })
765
-
766
- it('should not override the default selection string when using `selected` slot', () => {
767
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
768
- mountQSelect({
769
- props: {
770
- options,
771
- modelValue: 1,
772
- displayValue: 'Test'
773
- },
774
- slots: {
775
- selected: () => 'Hello there'
776
- }
777
- })
778
- getHostElement()
779
- .should('not.contain', options[ 0 ].value)
780
- .should('not.contain', 'Test')
781
- .should('contain', 'Hello there')
782
- })
783
- })
784
-
785
- describe('(prop): display-value-html', () => {
786
- it('should render the selected option as html', () => {
787
- const options = [ '<b style="color: red">Option 1</b>', 'Option 2' ]
788
- mountQSelect({
789
- props: {
790
- options,
791
- modelValue: options[ 0 ],
792
- displayValueHtml: true
793
- }
794
- })
795
- getHostElement()
796
- .contains('Option 1')
797
- .should('have.color', 'red')
798
- .should('have.css', 'font-weight', '700')
799
- })
800
-
801
- it('should not render the selected option as html when using `selected` slot', () => {
802
- const html = '<b style="color: red">Option 1</b>'
803
- const options = [ 'Option 1', 'Option 2' ]
804
- mountQSelect({
805
- props: {
806
- options,
807
- modelValue: options[ 0 ],
808
- displayValueHtml: true
809
- },
810
- slots: {
811
- selected: () => html
812
- }
813
- })
814
- getHostElement()
815
- .contains(html)
816
- })
817
-
818
- it('should not render the selected option as html when using `selected-item` slot', () => {
819
- const html = '<b style="color: red">Option 1</b>'
820
- const options = [ 'Option 1', 'Option 2' ]
821
- mountQSelect({
822
- props: {
823
- options,
824
- modelValue: options[ 0 ],
825
- displayValueHtml: true
826
- },
827
- slots: {
828
- 'selected-item': () => html
829
- }
830
- })
831
- getHostElement()
832
- .contains(html)
833
- })
834
- })
835
-
836
- describe('(prop): hide-selected', () => {
837
- it('should not show the selected value', () => {
838
- const options = [ 'Option 1', 'Option 2' ]
839
- mountQSelect({
840
- props: {
841
- options,
842
- modelValue: options[ 0 ],
843
- hideSelected: true
844
- }
845
- })
846
- getHostElement()
847
- .should('not.contain', options[ 0 ])
848
- })
849
-
850
- it('should set the value on the underlying input when using hide-selected', () => {
851
- // Todo: it its not really clear from the docs that you need to use `useInput` and `fillInput` together with this prop to achieve this
852
- const options = [ 'Option 1', 'Option 2' ]
853
- mountQSelect({
854
- props: {
855
- options,
856
- modelValue: options[ 0 ],
857
- hideSelected: true,
858
- fillInput: true,
859
- useInput: true
860
- }
861
- })
862
- getHostElement()
863
- .get('input')
864
- .should('have.value', options[ 0 ])
865
- })
866
- })
867
-
868
- describe('(prop): max-values', () => {
869
- it('should allow a maximum number of selections', () => {
870
- const max = 3
871
- const options = [ '1', '2', '3', '4', '5' ]
872
- const model = ref([])
873
- mountQSelect({
874
- props: {
875
- ...vModelAdapter(model),
876
- options,
877
- maxValues: max,
878
- multiple: true
879
- }
880
- })
881
- getHostElement()
882
- .click()
883
- cy.get('.q-menu')
884
- .get('[role="option"]')
885
- .should('be.visible')
886
- .as('clicked')
887
- .click({ multiple: true })
888
- cy.get('@clicked')
889
- .then(() => {
890
- expect(model.value.length).to.equal(max)
891
- })
892
- })
893
- })
894
-
895
- describe('(prop): use-chips', () => {
896
- it('should use QChips to show the selected value', () => {
897
- const options = [ 'Option 1', 'Option 2' ]
898
- mountQSelect({
899
- props: {
900
- options,
901
- modelValue: options[ 0 ],
902
- useChips: true
903
- }
904
- })
905
- getHostElement()
906
- .get('.q-chip')
907
- .should('contain', options[ 0 ])
908
- })
909
- })
910
- })
911
-
912
- describe('Category: style', () => {
913
- describe('(prop): popup-content-class', () => {
914
- it('should apply the class to the popup element', () => {
915
- const className = 'test-class'
916
- mountQSelect({
917
- props: {
918
- options: [ '1', '2 ' ],
919
- popupContentClass: className
920
- }
921
- })
922
- getHostElement()
923
- .click()
924
- cy.get('.q-menu')
925
- .should('have.class', className)
926
- })
927
- })
928
-
929
- describe('(prop): popup-content-style', () => {
930
- it('should apply the style definitions to the popup element', () => {
931
- const style = 'background: red;'
932
- mountQSelect({
933
- props: {
934
- options: [ '1', '2 ' ],
935
- popupContentStyle: style
936
- }
937
- })
938
- getHostElement()
939
- .click()
940
- cy.get('.q-menu')
941
- .should('have.backgroundColor', 'red')
942
- })
943
- })
944
-
945
- describe('(prop): input-class', () => {
946
- it('should apply a class to the input element when using `useInput`', () => {
947
- const className = 'test-class'
948
- mountQSelect({
949
- props: {
950
- useInput: true,
951
- inputClass: className
952
- }
953
- })
954
- getHostElement()
955
- .get('input')
956
- .should('have.class', className)
957
- })
958
- })
959
-
960
- describe('(prop): input-style', () => {
961
- it('should apply a style to the input element when using `useInput`', () => {
962
- const style = 'font-size: 30px'
963
- mountQSelect({
964
- props: {
965
- useInput: true,
966
- inputStyle: style
967
- }
968
- })
969
- getHostElement()
970
- .get('input')
971
- .should('have.css', 'font-size', '30px')
972
- })
973
- })
974
- })
975
- })
976
-
977
- describe('Slots', () => {
978
- describe('(slot): selected', () => {
979
- it('should display when something is selected', () => {
980
- const selectedString = 'Test slot selected'
981
- const options = [ 'Option 1', 'Option 2' ]
982
- mountQSelect({
983
- props: {
984
- options,
985
- modelValue: options[ 0 ]
986
- },
987
- slots: {
988
- selected: () => selectedString
989
- }
990
- })
991
- getHostElement()
992
- .should('contain', selectedString)
993
- })
994
- })
995
-
996
- describe('(slot): loading', () => {
997
- it('should display when element is loading', () => {
998
- const loadingString = 'Test slot loading'
999
- mountQSelect({
1000
- props: {
1001
- loading: true
1002
- },
1003
- slots: {
1004
- loading: () => loadingString
1005
- }
1006
- })
1007
- getHostElement()
1008
- .should('contain', loadingString)
1009
- })
1010
-
1011
- it('should not display when element is loading', () => {
1012
- const loadingString = 'Test slot loading'
1013
- mountQSelect({
1014
- props: {
1015
- loading: false
1016
- },
1017
- slots: {
1018
- loading: () => loadingString
1019
- }
1020
- })
1021
- getHostElement()
1022
- .should('not.contain', loadingString)
1023
- })
1024
- })
1025
-
1026
- describe('(slot): before-options', () => {
1027
- it('should display the slot content before the options', () => {
1028
- mountQSelect({
1029
- props: {
1030
- options: [ '1', '2', '3' ]
1031
- },
1032
- slots: {
1033
- 'before-options': () => h('div', { class: 'dummyClass' }, 'Hello')
1034
- }
1035
- })
1036
- getHostElement()
1037
- .click()
1038
- cy.get('.q-menu')
1039
- .children().first()
1040
- .should('have.class', 'dummyClass')
1041
- })
1042
- })
1043
-
1044
- describe('(slot): after-options', () => {
1045
- it('should display the slot content after the options', () => {
1046
- mountQSelect({
1047
- props: {
1048
- options: [ '1', '2', '3' ]
1049
- },
1050
- slots: {
1051
- 'after-options': () => h('div', { class: 'dummyClass' }, 'Hello')
1052
- }
1053
- })
1054
- getHostElement()
1055
- .click()
1056
- cy.get('.q-menu')
1057
- .children().last()
1058
- .should('have.class', 'dummyClass')
1059
- })
1060
- })
1061
-
1062
- describe('(slot): no-option', () => {
1063
- it('should display the slot content when there are no options', () => {
1064
- const compareString = 'No options :('
1065
- mountQSelect({
1066
- props: {
1067
- options: [ ]
1068
- },
1069
- slots: {
1070
- 'no-option': () => compareString
1071
- }
1072
- })
1073
- getHostElement()
1074
- .click()
1075
- cy.get('.q-menu')
1076
- .should('contain', compareString)
1077
- })
1078
-
1079
- it('should pass the inputValue to the slot scope', () => {
1080
- const compareString = 'No options :('
1081
- mountQSelect({
1082
- props: {
1083
- options: [ ],
1084
- useInput: true
1085
- },
1086
- slots: {
1087
- 'no-option': (scope) => compareString + scope.inputValue
1088
- }
1089
- })
1090
- getHostElement()
1091
- .click()
1092
- .type('Hello')
1093
- cy.get('.q-menu')
1094
- .should('contain', compareString + 'Hello')
1095
- })
1096
-
1097
- it('should not display the slot content when there are options', () => {
1098
- const compareString = 'No options :('
1099
- mountQSelect({
1100
- props: {
1101
- options: [ '1', '2', '3' ]
1102
- },
1103
- slots: {
1104
- 'no-option': () => compareString
1105
- }
1106
- })
1107
- getHostElement()
1108
- .click()
1109
- cy.get('.q-menu')
1110
- .should('not.contain', compareString)
1111
- })
1112
- })
1113
-
1114
- describe('(slot): selected-item', () => {
1115
- it('should override the default selection slot', () => {
1116
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
1117
- mountQSelect({
1118
- props: {
1119
- options,
1120
- modelValue: 1
1121
- },
1122
- slots: {
1123
- 'selected-item': () => 'Test'
1124
- }
1125
- })
1126
- getHostElement()
1127
- .should('not.contain', options[ 0 ].value)
1128
- .should('contain', 'Test')
1129
- })
1130
-
1131
- it('should pass the selected option index to the slot scope', () => {
1132
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
1133
- mountQSelect({
1134
- props: {
1135
- options,
1136
- modelValue: 1
1137
- },
1138
- slots: {
1139
- 'selected-item': (scope) => 'Test' + scope.index
1140
- }
1141
- })
1142
- getHostElement()
1143
- .should('contain', 'Test0')
1144
- })
1145
-
1146
- it('should pass the selected option value to the slot scope', () => {
1147
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
1148
- mountQSelect({
1149
- props: {
1150
- options,
1151
- modelValue: 1
1152
- },
1153
- slots: {
1154
- 'selected-item': (scope) => 'Test' + scope.opt
1155
- }
1156
- })
1157
- getHostElement()
1158
- .should('contain', 'Test1')
1159
- })
1160
-
1161
- it('should pass a removeAtIndex function to the slot scope', () => {
1162
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
1163
- const model = ref(1)
1164
- mountQSelect({
1165
- props: {
1166
- ...vModelAdapter(model),
1167
- options
1168
- },
1169
- slots: {
1170
- 'selected-item': (scope) => h('button', { class: 'remove', onClick: () => scope.removeAtIndex(scope.index) }, 'Remove')
1171
- }
1172
- })
1173
- getHostElement()
1174
- .get('button.remove')
1175
- .click()
1176
- getHostElement()
1177
- .get('button.remove')
1178
- .should('not.exist')
1179
- })
1180
-
1181
- it('should pass a toggleOption function to the slot scope', () => {
1182
- const options = [ { label: 'Option one', value: 1 }, { label: 'Option two', value: 2 } ]
1183
- const model = ref(1)
1184
- mountQSelect({
1185
- props: {
1186
- ...vModelAdapter(model),
1187
- options
1188
- },
1189
- slots: {
1190
- 'selected-item': (scope) => h('button', { class: 'toggle', onClick: () => scope.toggleOption(2) }, 'Toggle' + scope.opt)
1191
- }
1192
- })
1193
- getHostElement()
1194
- .get('button.toggle')
1195
- .should('contain', 'Toggle1')
1196
- .click()
1197
- getHostElement()
1198
- .get('button.toggle')
1199
- .should('contain', 'Toggle2')
1200
- })
1201
- })
1202
-
1203
- describe('(slot): option', () => {
1204
- it('should render a list of the provided slot as options', () => {
1205
- const options = [ '1', '2', '3' ]
1206
- mountQSelect({
1207
- props: {
1208
- options
1209
- },
1210
- slots: {
1211
- option: (scope) => h('div', { class: 'custom-option' }, scope.opt)
1212
- }
1213
- })
1214
- getHostElement()
1215
- .click()
1216
- cy.get('.q-menu')
1217
- .get('.custom-option')
1218
- .should('have.length', options.length)
1219
- })
1220
-
1221
- it('should have a selected property in the scope', () => {
1222
- const options = [ '1', '2', '3' ]
1223
- mountQSelect({
1224
- props: {
1225
- modelValue: '1',
1226
- options
1227
- },
1228
- slots: {
1229
- option: (scope) => h('div', { class: `custom-option-${ scope.selected }` }, scope.opt + scope.selected)
1230
- }
1231
- })
1232
- getHostElement()
1233
- .click()
1234
- cy.get('.q-menu')
1235
- .get('.custom-option-true')
1236
- .should('have.length', 1)
1237
- .should('contain', options[ 0 ])
1238
- })
1239
- })
1240
- })
1241
-
1242
- describe('Events', () => {
1243
- describe('(event): update:model-value', () => {
1244
- it('should emit event when model value changes', () => {
1245
- const fn = cy.stub()
1246
- mountQSelect({
1247
- props: {
1248
- options: [ '1', '2', '3' ],
1249
- modelValue: null,
1250
- 'onUpdate:modelValue': fn
1251
- }
1252
- })
1253
-
1254
- expect(fn).not.to.be.called
1255
- getHostElement()
1256
- .click()
1257
- cy.get('.q-menu')
1258
- .get('[role="option"]')
1259
- .first()
1260
- .should('be.visible')
1261
- .as('clicked')
1262
- .click()
1263
- cy.get('@clicked')
1264
- .then(() => {
1265
- expect(fn).to.be.calledWith('1')
1266
- })
1267
- })
1268
- })
1269
-
1270
- describe('(event): input-value', () => {
1271
- it('should emit event when text input changes', () => {
1272
- const fn = cy.stub()
1273
- mountQSelect({
1274
- props: {
1275
- modelValue: null,
1276
- onInputValue: fn,
1277
- useInput: true,
1278
- inputDebounce: 0
1279
- }
1280
- })
1281
-
1282
- expect(fn).not.to.be.called
1283
- getHostElement()
1284
- .get('input')
1285
- .type('h')
1286
- .then(() => {
1287
- expect(fn).to.be.calledWith('h')
1288
- })
1289
- })
1290
- })
1291
-
1292
- describe('(event): remove', () => {
1293
- it('should emit event when a selected item is removed from selection', () => {
1294
- const fn = cy.stub()
1295
- const model = ref([ '2', '3' ])
1296
- mountQSelect({
1297
- props: {
1298
- ...vModelAdapter(model),
1299
- onRemove: fn,
1300
- multiple: true,
1301
- options: [ '1', '2', '3' ]
1302
- }
1303
- })
1304
-
1305
- expect(fn).not.to.be.called
1306
- getHostElement()
1307
- .click()
1308
- cy.get('.q-menu')
1309
- .get('[role="option"]')
1310
- .first()
1311
- .should('be.visible')
1312
- .as('clicked')
1313
- .click()
1314
- cy.get('@clicked')
1315
- .then(() => {
1316
- expect(fn).not.to.be.called
1317
- })
1318
- cy.get('.q-menu')
1319
- .get('[role="option"]')
1320
- .first()
1321
- .should('be.visible')
1322
- .as('clicked')
1323
- .click()
1324
- cy.get('@clicked')
1325
- .then(() => {
1326
- // Item is added in the previous step at the end of the array, so at index 2
1327
- expect(fn).to.be.calledWith({ index: 2, value: '1' })
1328
- })
1329
- })
1330
- })
1331
-
1332
- describe('(event): add', () => {
1333
- it('should emit event when an option is added to the selection', () => {
1334
- const fn = cy.stub()
1335
- const model = ref([ '2' ])
1336
- mountQSelect({
1337
- props: {
1338
- ...vModelAdapter(model),
1339
- onAdd: fn,
1340
- multiple: true,
1341
- options: [ '1', '2', '3' ]
1342
- }
1343
- })
1344
-
1345
- expect(fn).not.to.be.called
1346
- getHostElement()
1347
- .click()
1348
- cy.get('.q-menu')
1349
- .get('[role="option"]')
1350
- .first()
1351
- .should('be.visible')
1352
- .as('clicked')
1353
- .click()
1354
- cy.get('@clicked')
1355
- .then(() => {
1356
- // Item is added in the previous step at the end of the array, so at index 2
1357
- expect(fn).to.be.calledWith({ index: 1, value: '1' })
1358
- })
1359
- })
1360
- })
1361
-
1362
- describe('(event): new-value', () => {
1363
- it('should emit event when something is typed into the input field and enter is pressed', () => {
1364
- const fn = cy.stub()
1365
- const model = ref([ '2' ])
1366
- mountQSelect({
1367
- props: {
1368
- ...vModelAdapter(model),
1369
- onNewValue: fn,
1370
- multiple: true,
1371
- useInput: true,
1372
- hideDropdownIcon: true
1373
- }
1374
- })
1375
-
1376
- expect(fn).not.to.be.called
1377
- getHostElement()
1378
- .get('input')
1379
- .type('100')
1380
- .then(() => {
1381
- expect(fn).not.to.be.called
1382
- })
1383
- .type('{enter}')
1384
- .then(() => {
1385
- expect(fn).to.be.calledWith('100')
1386
- })
1387
- })
1388
-
1389
- it('should add the value to the model when the doneFn is called', () => {
1390
- const model = ref([ '2' ])
1391
- mountQSelect({
1392
- props: {
1393
- ...vModelAdapter(model),
1394
- onNewValue: (val, doneFn) => {
1395
- doneFn(val)
1396
- },
1397
- multiple: true,
1398
- useInput: true,
1399
- hideDropdownIcon: true
1400
- }
1401
- })
1402
-
1403
- getHostElement()
1404
- .get('input')
1405
- .type('100')
1406
- .type('{enter}')
1407
- .then(() => {
1408
- expect(model.value).includes('100')
1409
- })
1410
- })
1411
- })
1412
-
1413
- describe('(event): filter', () => {
1414
- it('should emit event when something is typed into the input field', () => {
1415
- const fn = cy.stub()
1416
- mountQSelect({
1417
- props: {
1418
- onFilter: fn,
1419
- useInput: true,
1420
- inputDebounce: 0
1421
- }
1422
- })
1423
-
1424
- expect(fn).not.to.be.called
1425
- getHostElement()
1426
- .get('input')
1427
- .type('h')
1428
- .then(() => {
1429
- expect(fn).to.be.calledWith('h')
1430
- })
1431
- })
1432
- })
1433
-
1434
- describe('(event): filter-abort', () => {
1435
- it('should emit event when the filterFn has not called the doneFn yet and a new filter is requested', () => {
1436
- const fn = cy.stub()
1437
- const filterFn = cy.stub()
1438
- mountQSelect({
1439
- props: {
1440
- onFilter: filterFn,
1441
- onFilterAbort: fn,
1442
- useInput: true,
1443
- inputDebounce: 0
1444
- }
1445
- })
1446
-
1447
- expect(fn).not.to.be.called
1448
- getHostElement()
1449
- .get('input')
1450
- .click()
1451
- .then(() => {
1452
- expect(filterFn).to.be.calledOnce
1453
- expect(fn).not.to.be.called
1454
- })
1455
- .type('h')
1456
- .then(() => {
1457
- expect(fn).to.be.calledOnce
1458
- })
1459
- })
1460
-
1461
- it('should not emit event when the filter has called its doneFn', () => {
1462
- const fn = cy.stub()
1463
- mountQSelect({
1464
- props: {
1465
- onFilter: (val, doneFn) => {
1466
- doneFn()
1467
- },
1468
- onFilterAbort: fn,
1469
- useInput: true,
1470
- inputDebounce: 0
1471
- }
1472
- })
1473
-
1474
- expect(fn).not.to.be.called
1475
- getHostElement()
1476
- .get('input')
1477
- .click()
1478
- .then(() => {
1479
- expect(fn).not.to.be.called
1480
- })
1481
- .type('h')
1482
- .then(() => {
1483
- expect(fn).not.to.be.called
1484
- })
1485
- })
1486
- })
1487
-
1488
- describe('(event): popup-show', () => {
1489
- it('should emit event when the options are shown', () => {
1490
- const fn = cy.stub()
1491
- mountQSelect({
1492
- props: {
1493
- onPopupShow: fn,
1494
- options: [ '1', '2', '3' ]
1495
- }
1496
- })
1497
-
1498
- expect(fn).not.to.be.called
1499
- getHostElement()
1500
- .click()
1501
- .then(() => {
1502
- expect(fn).to.be.called
1503
- })
1504
- })
1505
- })
1506
-
1507
- describe('(event): popup-hide', () => {
1508
- it('should emit event when the options are hidden', () => {
1509
- const fn = cy.stub()
1510
- mountQSelect({
1511
- props: {
1512
- onPopupHide: fn,
1513
- options: [ '1', '2', '3' ]
1514
- }
1515
- })
1516
-
1517
- expect(fn).not.to.be.called
1518
- getHostElement()
1519
- .click()
1520
- .then(() => {
1521
- expect(fn).not.to.be.called
1522
- })
1523
- .type('{esc}')
1524
- .then(() => {
1525
- expect(fn).to.be.called
1526
- })
1527
- })
1528
- })
1529
-
1530
- describe('(event): virtual-scroll', () => {
1531
- it.skip('', () => {
1532
- // The virtual scroll code is tested as a composable
1533
- // The property is included in the QSelect.json to add typings
1534
- // for the QSelect ref passed in this event.
1535
- // I think testing the component ref that is passed is of type QSelect is out of scope for unit tests.
1536
- })
1537
- })
1538
- })
1539
-
1540
- describe('Methods', () => {
1541
- describe('(method): focus', () => {
1542
- it('should focus the component', () => {
1543
- mountQSelect()
1544
-
1545
- getHostElement()
1546
- .get('[tabindex="0"]')
1547
- .should('not.have.focus')
1548
- getHostElement()
1549
- .then(() => {
1550
- Cypress.vueWrapper.vm.focus()
1551
- })
1552
- getHostElement()
1553
- .get('[tabindex="0"]')
1554
- .should('have.focus')
1555
- })
1556
- })
1557
-
1558
- describe('(method): showPopup', () => {
1559
- it('should open the popup and focus the component', () => {
1560
- mountQSelect({
1561
- props: {
1562
- options: [ '1', '2' ]
1563
- }
1564
- })
1565
-
1566
- getHostElement()
1567
- cy.get('.q-menu')
1568
- .should('not.exist')
1569
- .then(() => {
1570
- Cypress.vueWrapper.vm.showPopup()
1571
- })
1572
- cy.get('.q-menu')
1573
- .should('be.visible')
1574
- getHostElement()
1575
- .get('[tabindex="0"]')
1576
- .should('have.focus')
1577
- })
1578
- })
1579
-
1580
- describe('(method): hidePopup', () => {
1581
- it('should hide the popup', () => {
1582
- mountQSelect({
1583
- props: {
1584
- options: [ '1', '2' ]
1585
- }
1586
- })
1587
-
1588
- getHostElement()
1589
- .click()
1590
- cy.get('.q-menu')
1591
- .should('be.visible')
1592
- .then(() => {
1593
- Cypress.vueWrapper.vm.hidePopup()
1594
- })
1595
- cy.get('.q-menu')
1596
- .should('not.exist')
1597
- })
1598
- })
1599
-
1600
- describe('(method): removeAtIndex', () => {
1601
- it('should remove a selected option at the correct index', () => {
1602
- const options = [ '1', '2', '3', '4' ]
1603
- const model = ref([ '1', '2', '4' ])
1604
- mountQSelect({
1605
- props: {
1606
- ...vModelAdapter(model),
1607
- multiple: true,
1608
- options
1609
- }
1610
- })
1611
- .then(() => {
1612
- expect(model.value.includes('4')).to.be.true
1613
- Cypress.vueWrapper.vm.removeAtIndex(2)
1614
- expect(model.value.includes('4')).to.be.false
1615
- })
1616
- })
1617
- })
1618
-
1619
- describe('(method): add', () => {
1620
- it('should add a selected option', () => {
1621
- const model = ref([ '1', '2' ])
1622
- mountQSelect({
1623
- props: {
1624
- ...vModelAdapter(model),
1625
- multiple: true
1626
- }
1627
- })
1628
- .then(() => {
1629
- expect(model.value.includes('100')).to.be.false
1630
- Cypress.vueWrapper.vm.add('100')
1631
- expect(model.value.includes('100')).to.be.true
1632
- })
1633
- })
1634
-
1635
- it('should not add a duplicate option when unique is true', () => {
1636
- const model = ref([ '1', '2' ])
1637
- mountQSelect({
1638
- props: {
1639
- ...vModelAdapter(model),
1640
- multiple: true
1641
- }
1642
- })
1643
- .then(() => {
1644
- expect(model.value.length).to.be.equal(2)
1645
- Cypress.vueWrapper.vm.add('2', true)
1646
- expect(model.value.length).to.be.equal(2)
1647
- Cypress.vueWrapper.vm.add('2')
1648
- expect(model.value.length).to.be.equal(3)
1649
- })
1650
- })
1651
- })
1652
-
1653
- describe('(method): toggleOption', () => {
1654
- it('should toggle an option', () => {
1655
- const model = ref([ '1', '2' ])
1656
- mountQSelect({
1657
- props: {
1658
- ...vModelAdapter(model),
1659
- multiple: true
1660
- }
1661
- })
1662
- .then(() => {
1663
- expect(model.value.length).to.be.equal(2)
1664
- Cypress.vueWrapper.vm.toggleOption('2')
1665
- expect(model.value.length).to.be.equal(1)
1666
- })
1667
- // When not using this wait this test will succeed on `open-ct` but fail on `run-ct`
1668
- .wait(50)
1669
- .then(() => {
1670
- Cypress.vueWrapper.vm.toggleOption('2')
1671
- expect(model.value.length).to.be.equal(2)
1672
- })
1673
- })
1674
-
1675
- // Todo: toggleOption argument keepOpen only does something when using single select. This is not clear from the docs.
1676
- // should this be consistent? E.g. use `true` as argument when multiple is true by default but make sure it can be overridden.
1677
- it('should close the menu and clear the filter', () => {
1678
- const model = ref('1')
1679
- mountQSelect({
1680
- props: {
1681
- ...vModelAdapter(model),
1682
- options: [ '1', '2' ],
1683
- useInput: true
1684
- }
1685
- })
1686
-
1687
- getHostElement()
1688
- .click()
1689
- .get('input')
1690
- .type('h')
1691
- cy.get('.q-menu')
1692
- .should('be.visible')
1693
- .then(() => {
1694
- Cypress.vueWrapper.vm.toggleOption('2')
1695
- })
1696
- cy.get('.q-menu')
1697
- .should('not.exist')
1698
- cy.get('input')
1699
- .should('have.value', '')
1700
- })
1701
-
1702
- it('should not close the menu and clear the filter when keepOpen is true', () => {
1703
- const model = ref('1')
1704
- mountQSelect({
1705
- props: {
1706
- ...vModelAdapter(model),
1707
- options: [ '1', '2' ],
1708
- useInput: true
1709
- }
1710
- })
1711
-
1712
- getHostElement()
1713
- .click()
1714
- .get('input')
1715
- .type('h')
1716
- cy.get('.q-menu')
1717
- .should('be.visible')
1718
- .then(() => {
1719
- Cypress.vueWrapper.vm.toggleOption('2', true)
1720
- })
1721
- cy.get('.q-menu')
1722
- .should('be.visible')
1723
- cy.get('input')
1724
- .should('have.value', 'h')
1725
- })
1726
- })
1727
-
1728
- describe('(method): setOptionIndex', () => {
1729
- it('should set an option from the menu dropdown as focused', () => {
1730
- const options = [ '1', '2', '3', '4' ]
1731
- mountQSelect({
1732
- props: {
1733
- options
1734
- }
1735
- })
1736
- getHostElement()
1737
- .click()
1738
- .then(() => {
1739
- Cypress.vueWrapper.vm.setOptionIndex(0)
1740
- })
1741
- .get('[role="option"]')
1742
- .first()
1743
- .should('have.class', 'q-manual-focusable--focused')
1744
- })
1745
- })
1746
-
1747
- describe('(method): moveOptionSelection', () => {
1748
- it('should move the optionSelection by some index offset', () => {
1749
- const options = [ '1', '2', '3', '4' ]
1750
- mountQSelect({
1751
- props: {
1752
- options
1753
- }
1754
- })
1755
- getHostElement()
1756
- .click()
1757
- .then(() => {
1758
- Cypress.vueWrapper.vm.setOptionIndex(0)
1759
- })
1760
- .get('[role="option"]')
1761
- .first()
1762
- .should('have.class', 'q-manual-focusable--focused')
1763
- .then(() => {
1764
- Cypress.vueWrapper.vm.moveOptionSelection(3)
1765
- })
1766
- .get('[role="option"]')
1767
- .last()
1768
- .should('have.class', 'q-manual-focusable--focused')
1769
- })
1770
- })
1771
-
1772
- describe('(method): filter', () => {
1773
- it('should filter the options list', () => {
1774
- const options = [ '1', '2', '3', '4' ]
1775
- const fn = cy.stub()
1776
- const text = 'test'
1777
- mountQSelect({
1778
- props: {
1779
- options,
1780
- useInput: true,
1781
- onFilter: fn
1782
- }
1783
- })
1784
- getHostElement()
1785
- .click()
1786
- .then(() => {
1787
- expect(fn).not.to.be.calledWith(text)
1788
- Cypress.vueWrapper.vm.filter(text)
1789
- expect(fn).to.be.calledWith(text)
1790
- })
1791
- })
1792
- })
1793
-
1794
- describe('(method): updateMenuPosition', () => {
1795
- it.skip(' ', () => {
1796
- // Not sure in what scenario this is needed, there is also some auto repositioning going on
1797
- })
1798
- })
1799
-
1800
- describe('(method): updateInputValue', () => {
1801
- it('should update the input value', () => {
1802
- const options = [ '1', '2', '3', '4' ]
1803
- const fn = cy.stub()
1804
- const text = 'test'
1805
- mountQSelect({
1806
- props: {
1807
- options,
1808
- useInput: true,
1809
- onFilter: fn
1810
- }
1811
- })
1812
- getHostElement()
1813
- .click()
1814
- .then(() => {
1815
- expect(fn).not.to.be.calledWith(text)
1816
- Cypress.vueWrapper.vm.updateInputValue(text)
1817
- expect(fn).to.be.calledWith(text)
1818
- })
1819
- .get('input')
1820
- .should('have.value', text)
1821
- })
1822
-
1823
- it('should not trigger the filter when specified', () => {
1824
- const options = [ '1', '2', '3', '4' ]
1825
- const fn = cy.stub()
1826
- const text = 'test'
1827
- mountQSelect({
1828
- props: {
1829
- options,
1830
- useInput: true,
1831
- onFilter: fn
1832
- }
1833
- })
1834
- getHostElement()
1835
- .click()
1836
- .then(() => {
1837
- expect(fn).not.to.be.calledWith(text)
1838
- Cypress.vueWrapper.vm.updateInputValue(text, true)
1839
- expect(fn).not.to.be.calledWith(text)
1840
- })
1841
- .get('input')
1842
- .should('have.value', text)
1843
- })
1844
- })
1845
-
1846
- describe('(method): isOptionSelected', () => {
1847
- it('should tell when an option is selected', () => {
1848
- const options = [ '1', '2', '3', '4' ]
1849
- const modelValue = [ '1', '2', '4' ]
1850
- mountQSelect({
1851
- props: {
1852
- modelValue,
1853
- multiple: true,
1854
- options
1855
- }
1856
- })
1857
- .then(() => {
1858
- expect(Cypress.vueWrapper.vm.isOptionSelected(options[ 0 ])).to.be.true
1859
- expect(Cypress.vueWrapper.vm.isOptionSelected(options[ 2 ])).to.be.false
1860
- })
1861
- })
1862
- })
1863
-
1864
- describe('(method): getEmittingOptionValue', () => {
1865
- it('should return the emit value with plain options', () => {
1866
- const options = [ '1', '2', '3', '4' ]
1867
- const modelValue = '1'
1868
- mountQSelect({
1869
- props: {
1870
- modelValue,
1871
- options
1872
- }
1873
- })
1874
- .then(() => {
1875
- expect(Cypress.vueWrapper.vm.getEmittingOptionValue(options[ 2 ])).to.equal(options[ 2 ])
1876
- })
1877
- })
1878
-
1879
- it('should return the emit value with object options', () => {
1880
- const options = [ { label: '1', value: 1 }, { label: '2', value: 2 }, { label: '3', value: 3 } ]
1881
- const modelValue = options[ 0 ]
1882
- mountQSelect({
1883
- props: {
1884
- modelValue,
1885
- options
1886
- }
1887
- })
1888
- .then(() => {
1889
- expect(Cypress.vueWrapper.vm.getEmittingOptionValue(options[ 2 ])).to.equal(options[ 2 ])
1890
- })
1891
- })
1892
-
1893
- it('should respect emit-value when using options', () => {
1894
- const options = [ { label: '1', value: 1 }, { label: '2', value: 2 }, { label: '3', value: 3 } ]
1895
- const modelValue = options[ 0 ]
1896
- mountQSelect({
1897
- props: {
1898
- modelValue,
1899
- options,
1900
- emitValue: true
1901
- }
1902
- })
1903
- .then(() => {
1904
- expect(Cypress.vueWrapper.vm.getEmittingOptionValue(options[ 2 ])).to.equal(options[ 2 ].value)
1905
- })
1906
- })
1907
- })
1908
-
1909
- describe('(method): getOptionValue', () => {
1910
- it('should return the option value with plain options', () => {
1911
- const options = [ '1', '2', '3', '4' ]
1912
- const modelValue = '1'
1913
- mountQSelect({
1914
- props: {
1915
- modelValue,
1916
- options
1917
- }
1918
- })
1919
- .then(() => {
1920
- expect(Cypress.vueWrapper.vm.getOptionValue(options[ 2 ])).to.equal(options[ 2 ])
1921
- })
1922
- })
1923
-
1924
- it('should return the option value with object options (value by default)', () => {
1925
- const options = [ { label: '1', value: 1 }, { label: '2', value: 2 }, { label: '3', value: 3 } ]
1926
- const modelValue = options[ 0 ]
1927
- mountQSelect({
1928
- props: {
1929
- modelValue,
1930
- options
1931
- }
1932
- })
1933
- .then(() => {
1934
- expect(Cypress.vueWrapper.vm.getOptionValue(options[ 2 ])).to.equal(options[ 2 ].value)
1935
- })
1936
- })
1937
-
1938
- it('should respect the option-value option', () => {
1939
- const options = [ { label: '1', test: 1 }, { label: '2', test: 2 }, { label: '3', test: 3 } ]
1940
- const modelValue = options[ 0 ]
1941
- mountQSelect({
1942
- props: {
1943
- modelValue,
1944
- options,
1945
- optionValue: 'test'
1946
- }
1947
- })
1948
- .then(() => {
1949
- expect(Cypress.vueWrapper.vm.getOptionValue(options[ 2 ])).to.equal(options[ 2 ].test)
1950
- })
1951
- })
1952
- })
1953
-
1954
- describe('(method): getOptionLabel', () => {
1955
- it('should return the option label with plain options', () => {
1956
- const options = [ '1', '2', '3', '4' ]
1957
- const modelValue = '1'
1958
- mountQSelect({
1959
- props: {
1960
- modelValue,
1961
- options
1962
- }
1963
- })
1964
- .then(() => {
1965
- expect(Cypress.vueWrapper.vm.getOptionLabel(options[ 2 ])).to.equal(options[ 2 ])
1966
- })
1967
- })
1968
-
1969
- it('should return the option label with object options (label by default)', () => {
1970
- const options = [ { label: '1', value: 1 }, { label: '2', value: 2 }, { label: '3', value: 3 } ]
1971
- const modelValue = options[ 0 ]
1972
- mountQSelect({
1973
- props: {
1974
- modelValue,
1975
- options
1976
- }
1977
- })
1978
- .then(() => {
1979
- expect(Cypress.vueWrapper.vm.getOptionLabel(options[ 2 ])).to.equal(options[ 2 ].label)
1980
- })
1981
- })
1982
-
1983
- it('should respect the option-value option', () => {
1984
- const options = [ { test: '1', value: 1 }, { test: '2', value: 2 }, { test: '3', value: 3 } ]
1985
- const modelValue = options[ 0 ]
1986
- mountQSelect({
1987
- props: {
1988
- modelValue,
1989
- options,
1990
- optionLabel: 'test'
1991
- }
1992
- })
1993
- .then(() => {
1994
- expect(Cypress.vueWrapper.vm.getOptionLabel(options[ 2 ])).to.equal(options[ 2 ].test)
1995
- })
1996
- })
1997
- })
1998
-
1999
- describe('(method): isOptionDisabled', () => {
2000
- it('should return if an option is disabled correctly', () => {
2001
- const options = [ { label: '1', value: 1, disable: true }, { label: '2', value: 2 }, { label: '3', value: 3 } ]
2002
- const modelValue = options[ 0 ]
2003
- mountQSelect({
2004
- props: {
2005
- modelValue,
2006
- options
2007
- }
2008
- })
2009
- .then(() => {
2010
- expect(Cypress.vueWrapper.vm.isOptionDisabled(options[ 0 ])).to.be.true
2011
- // This currently fails: https://github.com/quasarframework/quasar/issues/12046
2012
- // expect(Cypress.vueWrapper.vm.isOptionDisabled(options[ 1 ])).to.be.false
2013
- // expect(Cypress.vueWrapper.vm.isOptionDisabled(options[ 2 ])).to.be.false
2014
- })
2015
- })
2016
- })
2017
- })
2018
- })