quasar 2.4.11 → 2.5.1
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.
- package/dist/api/BottomSheet.json +4 -0
- package/dist/api/Dialog.json +5 -1
- package/dist/api/Notify.json +20 -10
- package/dist/api/QBtnDropdown.json +4 -2
- package/dist/api/QCheckbox.json +27 -0
- package/dist/api/QEditor.json +4 -2
- package/dist/api/QExpansionItem.json +6 -3
- package/dist/api/QFab.json +4 -2
- package/dist/api/QFabAction.json +4 -2
- package/dist/api/QFile.json +4 -2
- package/dist/api/QImg.json +1 -2
- package/dist/api/QInnerLoading.json +2 -1
- package/dist/api/QInput.json +4 -2
- package/dist/api/QPagination.json +4 -2
- package/dist/api/QRadio.json +18 -0
- package/dist/api/QRange.json +9 -0
- package/dist/api/QScrollArea.json +13 -5
- package/dist/api/QSelect.json +6 -3
- package/dist/api/QSlider.json +9 -0
- package/dist/api/QSplitter.json +8 -4
- package/dist/api/QTable.json +9 -0
- package/dist/api/QTime.json +8 -2
- package/dist/api/QToggle.json +24 -24
- package/dist/icon-set/bootstrap-icons.umd.prod.js +1 -1
- package/dist/icon-set/eva-icons.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v5-pro.umd.prod.js +1 -1
- package/dist/icon-set/fontawesome-v5.umd.prod.js +1 -1
- package/dist/icon-set/ionicons-v4.umd.prod.js +1 -1
- package/dist/icon-set/line-awesome.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-outlined.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-round.umd.prod.js +1 -1
- package/dist/icon-set/material-icons-sharp.umd.prod.js +1 -1
- package/dist/icon-set/material-icons.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v3.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v4.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v5.umd.prod.js +1 -1
- package/dist/icon-set/mdi-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-bootstrap-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-eva-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-fontawesome-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v4.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-ionicons-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-line-awesome.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-outlined.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-round.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons-sharp.umd.prod.js +1 -1
- package/dist/icon-set/svg-material-icons.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v4.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v5.umd.prod.js +1 -1
- package/dist/icon-set/svg-mdi-v6.umd.prod.js +1 -1
- package/dist/icon-set/svg-themify.umd.prod.js +1 -1
- package/dist/icon-set/themify.umd.prod.js +1 -1
- package/dist/lang/ar.umd.prod.js +1 -1
- package/dist/lang/az-Latn.umd.prod.js +1 -1
- package/dist/lang/bg.umd.prod.js +1 -1
- package/dist/lang/bn.umd.prod.js +1 -1
- package/dist/lang/ca.umd.prod.js +1 -1
- package/dist/lang/cs.umd.prod.js +1 -1
- package/dist/lang/da.umd.prod.js +1 -1
- package/dist/lang/de.umd.prod.js +1 -1
- package/dist/lang/el.umd.prod.js +1 -1
- package/dist/lang/en-GB.umd.prod.js +1 -1
- package/dist/lang/en-US.umd.prod.js +1 -1
- package/dist/lang/eo.umd.prod.js +1 -1
- package/dist/lang/es.umd.prod.js +1 -1
- package/dist/lang/et.umd.prod.js +1 -1
- package/dist/lang/fa-IR.umd.prod.js +1 -1
- package/dist/lang/fa.umd.prod.js +1 -1
- package/dist/lang/fi.umd.prod.js +1 -1
- package/dist/lang/fr.umd.prod.js +1 -1
- package/dist/lang/gn.umd.prod.js +1 -1
- package/dist/lang/he.umd.prod.js +1 -1
- package/dist/lang/hr.umd.prod.js +1 -1
- package/dist/lang/hu.umd.prod.js +1 -1
- package/dist/lang/id.umd.prod.js +1 -1
- package/dist/lang/is.umd.prod.js +1 -1
- package/dist/lang/it.umd.prod.js +1 -1
- package/dist/lang/ja.umd.prod.js +1 -1
- package/dist/lang/km.umd.prod.js +1 -1
- package/dist/lang/ko-KR.umd.prod.js +1 -1
- package/dist/lang/kur-CKB.umd.prod.js +1 -1
- package/dist/lang/lt.umd.prod.js +1 -1
- package/dist/lang/lu.umd.prod.js +1 -1
- package/dist/lang/lv.umd.prod.js +1 -1
- package/dist/lang/ml.umd.prod.js +1 -1
- package/dist/lang/ms.umd.prod.js +1 -1
- package/dist/lang/my.umd.prod.js +1 -1
- package/dist/lang/nb-NO.umd.prod.js +1 -1
- package/dist/lang/nl.umd.prod.js +1 -1
- package/dist/lang/pl.umd.prod.js +1 -1
- package/dist/lang/pt-BR.umd.prod.js +1 -1
- package/dist/lang/pt.umd.prod.js +1 -1
- package/dist/lang/ro.umd.prod.js +1 -1
- package/dist/lang/ru.umd.prod.js +1 -1
- package/dist/lang/sk.umd.prod.js +1 -1
- package/dist/lang/sl.umd.prod.js +1 -1
- package/dist/lang/sr-CYR.umd.prod.js +1 -1
- package/dist/lang/sr.umd.prod.js +1 -1
- package/dist/lang/sv.umd.prod.js +1 -1
- package/dist/lang/ta.umd.prod.js +1 -1
- package/dist/lang/th.umd.prod.js +1 -1
- package/dist/lang/tr.umd.prod.js +1 -1
- package/dist/lang/ug.umd.prod.js +1 -1
- package/dist/lang/uk.umd.prod.js +1 -1
- package/dist/lang/vi.umd.prod.js +1 -1
- package/dist/lang/zh-CN.umd.prod.js +1 -1
- package/dist/lang/zh-TW.umd.prod.js +1 -1
- package/dist/quasar.cjs.prod.js +2 -2
- package/dist/quasar.css +43 -10
- package/dist/quasar.esm.prod.js +2 -2
- package/dist/quasar.prod.css +1 -1
- package/dist/quasar.rtl.css +60 -23
- package/dist/quasar.rtl.prod.css +1 -1
- package/dist/quasar.sass +34 -11
- package/dist/quasar.umd.js +314 -157
- package/dist/quasar.umd.prod.js +2 -2
- package/dist/ssr-directives/Morph.js +1 -1
- package/dist/transforms/auto-import.json +39 -3
- package/dist/transforms/import-map.json +18 -0
- package/dist/types/api/slider.d.ts +6 -7
- package/dist/types/api/vue-prop-types.ts +15 -0
- package/dist/types/api.d.ts +1 -0
- package/dist/types/index.d.ts +110 -184
- package/dist/types/utils/date.d.ts +25 -13
- package/dist/types/utils/dom.d.ts +4 -2
- package/dist/types/utils.d.ts +3 -1
- package/dist/vetur/quasar-attributes.json +62 -42
- package/dist/vetur/quasar-tags.json +8 -3
- package/dist/web-types/web-types.json +103 -58
- package/package.json +13 -3
- package/src/components/avatar/__tests__/QAvatar.spec.js +121 -0
- package/src/components/badge/__tests__/QBadge.spec.js +74 -0
- package/src/components/breadcrumbs/QBreadcrumbs.js +1 -1
- package/src/components/btn/__tests__/QBtn.spec.js +55 -0
- package/src/components/btn/__tests__/use-btn.spec.js +189 -0
- package/src/components/btn-dropdown/QBtnDropdown.json +4 -2
- package/src/components/checkbox/QCheckbox.js +34 -3
- package/src/components/checkbox/QCheckbox.json +17 -0
- package/src/components/checkbox/QCheckbox.sass +17 -5
- package/src/components/checkbox/use-checkbox.js +4 -0
- package/src/components/checkbox/use-checkbox.json +18 -0
- package/src/components/chip/__tests__/QChip.spec.js +155 -0
- package/src/components/date/__tests__/QDate.spec.js +189 -0
- package/src/components/date/__tests__/use-datetime.spec.js +83 -0
- package/src/components/dialog/QDialog.js +1 -1
- package/src/components/dialog/__tests__/QDialog.spec.js +129 -0
- package/src/components/editor/QEditor.js +1 -1
- package/src/components/editor/QEditor.json +3 -1
- package/src/components/editor/__tests__/QEditor.spec.js +195 -0
- package/src/components/expansion-item/QExpansionItem.json +6 -3
- package/src/components/fab/use-fab.json +4 -2
- package/src/components/field/QField.sass +2 -0
- package/src/components/file/QFile.json +4 -2
- package/src/components/form/QForm.js +27 -25
- package/src/components/img/QImg.json +2 -3
- package/src/components/inner-loading/QInnerLoading.json +2 -1
- package/src/components/input/QInput.js +10 -1
- package/src/components/input/QInput.json +4 -2
- package/src/components/input/__tests__/QInput.spec.js +105 -0
- package/src/components/input/__tests__/use-mask.spec.js +29 -0
- package/src/components/menu/QMenu.js +2 -1
- package/src/components/menu/__tests__/QMenu.spec.js +610 -0
- package/src/components/menu/__tests__/WrapperOne.vue +51 -0
- package/src/components/menu/__tests__/WrapperTwo.vue +38 -0
- package/src/components/pagination/QPagination.json +4 -2
- package/src/components/radio/QRadio.js +26 -1
- package/src/components/radio/QRadio.json +16 -0
- package/src/components/radio/QRadio.sass +17 -6
- package/src/components/scroll-area/QScrollArea.json +13 -5
- package/src/components/select/QSelect.js +13 -9
- package/src/components/select/QSelect.json +6 -3
- package/src/components/select/QSelect.sass +1 -0
- package/src/components/select/__tests__/QSelect.spec.js +2003 -0
- package/src/components/select/__tests__/WrapperOne.vue +28 -0
- package/src/components/slider/use-slider.json +9 -0
- package/src/components/splitter/QSplitter.json +8 -4
- package/src/components/stepper/QStep.js +19 -14
- package/src/components/stepper/QStepper.sass +3 -0
- package/src/components/table/QTable.json +9 -0
- package/src/components/table/__tests__/QTable.spec.js +635 -0
- package/src/components/table/__tests__/QTd.spec.js +35 -0
- package/src/components/table/__tests__/QTh.spec.js +27 -0
- package/src/components/table/__tests__/QTr.spec.js +27 -0
- package/src/components/tabs/__tests__/QRouteTab.spec.js +9 -0
- package/src/components/tabs/__tests__/QTab.spec.js +79 -0
- package/src/components/tabs/__tests__/QTabs.spec.js +147 -0
- package/src/components/time/QTime.json +2 -2
- package/src/components/toggle/QToggle.js +5 -13
- package/src/components/toggle/QToggle.json +3 -12
- package/src/components/uploader/__tests__/QUploader.spec.js +161 -0
- package/src/components/virtual-scroll/use-virtual-scroll.js +9 -6
- package/src/composables/private/__tests__/FieldWrapper.vue +39 -0
- package/src/composables/private/__tests__/use-anchor.spec.js +99 -0
- package/src/composables/private/__tests__/use-field.spec.js +351 -0
- package/src/composables/private/__tests__/use-file.spec.js +69 -0
- package/src/composables/private/__tests__/use-form.spec.js +11 -0
- package/src/composables/private/__tests__/use-fullscreen.spec.js +37 -0
- package/src/composables/private/__tests__/use-model-toggle.spec.js +306 -0
- package/src/composables/private/__tests__/use-portal.spec.js +4 -0
- package/src/composables/private/__tests__/use-router-link.spec.js +55 -0
- package/src/composables/private/__tests__/use-size.spec.js +37 -0
- package/src/composables/private/__tests__/use-transition.spec.js +108 -0
- package/src/composables/private/__tests__/use-validate.spec.js +111 -0
- package/src/composables/private/use-field.js +5 -8
- package/src/composables/private/use-fullscreen.js +1 -1
- package/src/composables/private/use-model-toggle.js +1 -1
- package/src/composables/private/use-validate.js +22 -22
- package/src/plugins/BottomSheet.json +1 -0
- package/src/plugins/Dialog.json +1 -0
- package/src/plugins/Meta.js +1 -1
- package/src/plugins/Notify.json +20 -10
- package/src/plugins/Screen.js +11 -8
- package/src/utils/date.js +111 -32
- package/src/utils/private/global-dialog.json +3 -0
- package/src/utils/private/vm.js +14 -8
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
/* eslint-disable no-unused-expressions */
|
|
2
|
+
import { mount } from '@cypress/vue'
|
|
3
|
+
import WrapperOne from './WrapperOne.vue'
|
|
4
|
+
import WrapperTwo from './WrapperTwo.vue'
|
|
5
|
+
|
|
6
|
+
describe('Menu API', () => {
|
|
7
|
+
describe('Props', () => {
|
|
8
|
+
describe('Category: behavior', () => {
|
|
9
|
+
describe('(prop): scroll-target', () => {
|
|
10
|
+
it.skip(' ', () => {
|
|
11
|
+
// Todo: Check if test for this needs to be added.
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
describe('(prop): touch-position', () => {
|
|
16
|
+
it('should show menu at the position of the click', () => {
|
|
17
|
+
mount(WrapperOne, {
|
|
18
|
+
attrs: {
|
|
19
|
+
'touch-position': true
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const mouseX = 75
|
|
24
|
+
const mouseY = 25
|
|
25
|
+
let elementX = 0
|
|
26
|
+
let elementY = 0
|
|
27
|
+
|
|
28
|
+
cy.dataCy('wrapper')
|
|
29
|
+
.then(($el) => {
|
|
30
|
+
const rect = $el[ 0 ].getBoundingClientRect()
|
|
31
|
+
elementX = rect.left
|
|
32
|
+
elementY = rect.top
|
|
33
|
+
})
|
|
34
|
+
.click(mouseX, mouseY)
|
|
35
|
+
cy.dataCy('menu')
|
|
36
|
+
.should('exist')
|
|
37
|
+
.then(($el) => {
|
|
38
|
+
expect($el[ 0 ].offsetLeft).to.equal(mouseX + elementX)
|
|
39
|
+
// TODO: check if the Y position being off by 1 is intentional
|
|
40
|
+
expect($el[ 0 ].offsetTop).to.equal(mouseY + 1 + elementY)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('(prop): persistent', () => {
|
|
46
|
+
it('should close the menu when clicking outside the menu', () => {
|
|
47
|
+
mount(WrapperOne)
|
|
48
|
+
|
|
49
|
+
cy.dataCy('wrapper')
|
|
50
|
+
.click()
|
|
51
|
+
cy.dataCy('menu')
|
|
52
|
+
.should('exist')
|
|
53
|
+
cy.get('body')
|
|
54
|
+
.click(499, 0)
|
|
55
|
+
.dataCy('menu')
|
|
56
|
+
.should('not.exist')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should close the menu when hitting the escape key', () => {
|
|
60
|
+
mount(WrapperOne)
|
|
61
|
+
|
|
62
|
+
cy.dataCy('wrapper')
|
|
63
|
+
.click()
|
|
64
|
+
cy.dataCy('menu')
|
|
65
|
+
.should('exist')
|
|
66
|
+
cy.get('body')
|
|
67
|
+
.type('{esc}')
|
|
68
|
+
.dataCy('menu')
|
|
69
|
+
.should('not.exist')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('should not close the menu when clicking outside the menu when persistent', () => {
|
|
73
|
+
mount(WrapperOne, {
|
|
74
|
+
attrs: {
|
|
75
|
+
persistent: true
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
cy.dataCy('wrapper')
|
|
80
|
+
.click()
|
|
81
|
+
cy.dataCy('menu')
|
|
82
|
+
.should('exist')
|
|
83
|
+
cy.get('body')
|
|
84
|
+
.click(499, 0)
|
|
85
|
+
.wait(300) // Await menu animation otherwise it always passes
|
|
86
|
+
.dataCy('menu')
|
|
87
|
+
.should('exist')
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should not close the menu when hitting the escape key when persistent', () => {
|
|
91
|
+
mount(WrapperOne, {
|
|
92
|
+
attrs: {
|
|
93
|
+
persistent: true
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
cy.dataCy('wrapper')
|
|
98
|
+
.click()
|
|
99
|
+
cy.dataCy('menu')
|
|
100
|
+
.should('exist')
|
|
101
|
+
cy.get('body')
|
|
102
|
+
.type('{esc}')
|
|
103
|
+
.wait(300) // Await menu animation otherwise it always passes
|
|
104
|
+
.dataCy('menu')
|
|
105
|
+
.should('exist')
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
describe('(prop): no-route-dismiss', () => {
|
|
110
|
+
it.skip(' ', () => {
|
|
111
|
+
// This needs a vue-router, not possible with a unit test
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
describe('(prop): auto-close', () => {
|
|
116
|
+
it('should not close the menu when clicking a menu child without v-close-popup', () => {
|
|
117
|
+
mount(WrapperOne)
|
|
118
|
+
|
|
119
|
+
cy.dataCy('wrapper')
|
|
120
|
+
.click()
|
|
121
|
+
cy.dataCy('menu')
|
|
122
|
+
.should('exist')
|
|
123
|
+
.dataCy('keep-open')
|
|
124
|
+
.click()
|
|
125
|
+
.wait(300) // Await menu animation otherwise it always passes
|
|
126
|
+
cy.dataCy('menu')
|
|
127
|
+
.should('exist')
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
it('should close the menu when clicking a menu child without v-close-popup when auto-close is true', () => {
|
|
131
|
+
mount(WrapperOne, {
|
|
132
|
+
attrs: {
|
|
133
|
+
'auto-close': true
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
cy.dataCy('wrapper')
|
|
138
|
+
.click()
|
|
139
|
+
cy.dataCy('menu')
|
|
140
|
+
.should('exist')
|
|
141
|
+
.dataCy('keep-open')
|
|
142
|
+
.click()
|
|
143
|
+
.wait(300) // Await menu animation otherwise it always passes
|
|
144
|
+
cy.dataCy('menu')
|
|
145
|
+
.should('not.exist')
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
describe('(prop): separate-close-popup', () => {
|
|
150
|
+
it.skip(' ', () => {
|
|
151
|
+
// Todo: Check if this needs to be tested
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
describe('(prop): no-refocus', () => {
|
|
156
|
+
// TODO: it is not clear from the docs that refocussing does not happen when clicking outside or closing by escape/programatticaly. Should this be added?
|
|
157
|
+
it('should switch focus back to parent element when closing', () => {
|
|
158
|
+
mount(WrapperOne)
|
|
159
|
+
|
|
160
|
+
cy.dataCy('wrapper')
|
|
161
|
+
.focus()
|
|
162
|
+
.should('have.focus')
|
|
163
|
+
.click()
|
|
164
|
+
cy.dataCy('menu')
|
|
165
|
+
.should('exist')
|
|
166
|
+
.should('have.focus')
|
|
167
|
+
.dataCy('close-popup')
|
|
168
|
+
.click()
|
|
169
|
+
.wait(300) // Wait for menu transition
|
|
170
|
+
cy.dataCy('wrapper')
|
|
171
|
+
.get('.q-focus-helper')
|
|
172
|
+
.should('have.focus')
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('should not switch focus back to parent element when closing if no-refocus is true', () => {
|
|
176
|
+
mount(WrapperOne, {
|
|
177
|
+
attrs: {
|
|
178
|
+
'no-refocus': true
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
cy.dataCy('wrapper')
|
|
183
|
+
.focus()
|
|
184
|
+
.should('have.focus')
|
|
185
|
+
.click()
|
|
186
|
+
cy.dataCy('menu')
|
|
187
|
+
.should('exist')
|
|
188
|
+
.should('have.focus')
|
|
189
|
+
.dataCy('close-popup')
|
|
190
|
+
.click()
|
|
191
|
+
.wait(300) // Wait for menu transition
|
|
192
|
+
cy.dataCy('wrapper')
|
|
193
|
+
.get('.q-focus-helper')
|
|
194
|
+
.should('not.have.focus')
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
describe('(prop): no-focus', () => {
|
|
199
|
+
it('should switch focus to the menu when opening', () => {
|
|
200
|
+
mount(WrapperOne)
|
|
201
|
+
|
|
202
|
+
cy.dataCy('wrapper')
|
|
203
|
+
.click()
|
|
204
|
+
cy.dataCy('menu')
|
|
205
|
+
.should('exist')
|
|
206
|
+
.should('have.focus')
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('should no switch focus to the menu when opening with no-focus is true', () => {
|
|
210
|
+
mount(WrapperOne, {
|
|
211
|
+
attrs: {
|
|
212
|
+
'no-focus': true
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
cy.dataCy('wrapper')
|
|
217
|
+
.click()
|
|
218
|
+
cy.dataCy('menu')
|
|
219
|
+
.should('exist')
|
|
220
|
+
.should('not.have.focus')
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
describe('Category: position', () => {
|
|
226
|
+
describe('(prop): fit', () => {
|
|
227
|
+
it('should show a menu that matches the full with of the target when fit is supplied', () => {
|
|
228
|
+
mount(WrapperOne, {
|
|
229
|
+
attrs: {
|
|
230
|
+
target: '.other-target',
|
|
231
|
+
fit: true
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
let targetWidth = 0
|
|
235
|
+
cy.dataCy('other-target')
|
|
236
|
+
.then(($el) => {
|
|
237
|
+
targetWidth = $el[ 0 ].clientWidth
|
|
238
|
+
})
|
|
239
|
+
.click()
|
|
240
|
+
cy.dataCy('menu')
|
|
241
|
+
.then(($el) => {
|
|
242
|
+
expect($el[ 0 ].clientWidth).to.equal(targetWidth)
|
|
243
|
+
})
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it('should show a menu that not matches the full with of the target when fit is false', () => {
|
|
247
|
+
mount(WrapperOne, {
|
|
248
|
+
attrs: {
|
|
249
|
+
target: '.other-target',
|
|
250
|
+
fit: false
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
let targetWidth = 0
|
|
254
|
+
cy.dataCy('other-target')
|
|
255
|
+
.then(($el) => {
|
|
256
|
+
targetWidth = $el[ 0 ].clientWidth
|
|
257
|
+
})
|
|
258
|
+
.click()
|
|
259
|
+
cy.dataCy('menu')
|
|
260
|
+
.then(($el) => {
|
|
261
|
+
expect($el[ 0 ].clientWidth).not.to.equal(targetWidth)
|
|
262
|
+
})
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
describe('(prop): cover', () => {
|
|
267
|
+
it('should show a menu that overlays the target when using cover', () => {
|
|
268
|
+
mount(WrapperOne, {
|
|
269
|
+
attrs: {
|
|
270
|
+
cover: true
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
cy.dataCy('wrapper')
|
|
274
|
+
.click()
|
|
275
|
+
cy.dataCy('menu')
|
|
276
|
+
.checkVerticalPosition('wrapper', 'center', 'center')
|
|
277
|
+
.checkHorizontalPosition('wrapper', 'middle', 'middle')
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
it('should show a menu that overlays the target when using cover', () => {
|
|
281
|
+
mount(WrapperOne, {
|
|
282
|
+
attrs: {
|
|
283
|
+
cover: true,
|
|
284
|
+
target: '.other-target'
|
|
285
|
+
}
|
|
286
|
+
})
|
|
287
|
+
cy.dataCy('other-target')
|
|
288
|
+
.click()
|
|
289
|
+
cy.dataCy('menu')
|
|
290
|
+
.checkVerticalPosition('other-target', 'center', 'center')
|
|
291
|
+
.checkHorizontalPosition('other-target', 'middle', 'middle')
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
it('should ignore self property when using cover', () => {
|
|
295
|
+
mount(WrapperOne, {
|
|
296
|
+
attrs: {
|
|
297
|
+
cover: true,
|
|
298
|
+
self: 'center right',
|
|
299
|
+
target: '.other-target'
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
cy.dataCy('other-target')
|
|
303
|
+
.click()
|
|
304
|
+
cy.dataCy('menu')
|
|
305
|
+
.checkVerticalPosition('other-target', 'center', 'center')
|
|
306
|
+
.checkHorizontalPosition('other-target', 'middle', 'middle')
|
|
307
|
+
})
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
describe('(prop): anchor & self', () => {
|
|
311
|
+
it('should show a menu at anchor: bottom left and self: top left by default', () => {
|
|
312
|
+
mount(WrapperOne)
|
|
313
|
+
|
|
314
|
+
cy.dataCy('wrapper')
|
|
315
|
+
.click()
|
|
316
|
+
cy.dataCy('menu')
|
|
317
|
+
.checkVerticalPosition('wrapper', 'bottom', 'top')
|
|
318
|
+
.checkHorizontalPosition('wrapper', 'left', 'left')
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
const verticalAnchor = [ 'top', 'center', 'bottom' ]
|
|
322
|
+
const horizontalAnchor = [ 'left', 'middle', 'right' ]
|
|
323
|
+
const verticalSelf = [ 'top', 'center', 'bottom' ]
|
|
324
|
+
const horizontalSelf = [ 'left', 'middle', 'right' ]
|
|
325
|
+
verticalAnchor.forEach((vA) => {
|
|
326
|
+
horizontalAnchor.forEach((hA) => {
|
|
327
|
+
verticalSelf.forEach((vS) => {
|
|
328
|
+
horizontalSelf.forEach((hS) => {
|
|
329
|
+
it(`should position Anchor(${ vA } ${ hA }) & Self(${ vS } ${ hS }) correctly`, () => {
|
|
330
|
+
mount(WrapperOne, {
|
|
331
|
+
attrs: {
|
|
332
|
+
anchor: `${ vA } ${ hA }`,
|
|
333
|
+
self: `${ vS } ${ hS }`
|
|
334
|
+
}
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
cy.dataCy('wrapper')
|
|
338
|
+
.click()
|
|
339
|
+
cy.dataCy('menu')
|
|
340
|
+
.checkVerticalPosition('wrapper', vA, vS)
|
|
341
|
+
.checkHorizontalPosition('wrapper', hA, hS)
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
})
|
|
345
|
+
})
|
|
346
|
+
})
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
describe.skip('(prop): self', () => {
|
|
350
|
+
// This property is tested together with anchor above
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
describe('(prop): offset', () => {
|
|
354
|
+
const verticalAnchor = [ 'top', 'center', 'bottom' ]
|
|
355
|
+
const verticalSelf = [ 'top', 'center', 'bottom' ]
|
|
356
|
+
verticalAnchor.forEach((vA) => {
|
|
357
|
+
verticalSelf.forEach((vS) => {
|
|
358
|
+
it(`should offset vertical position Anchor(${ vA } left) & Self(${ vS } left) correctly`, () => {
|
|
359
|
+
mount(WrapperOne, {
|
|
360
|
+
attrs: {
|
|
361
|
+
anchor: `${ vA } left`,
|
|
362
|
+
self: `${ vS } left`,
|
|
363
|
+
offset: [ 0, 20 ]
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
cy.dataCy('wrapper')
|
|
368
|
+
.click()
|
|
369
|
+
cy.dataCy('menu')
|
|
370
|
+
.checkVerticalPosition('wrapper', vA, vS, 20)
|
|
371
|
+
})
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
const horizontalAnchor = [ 'left', 'middle', 'right' ]
|
|
376
|
+
const horizontalSelf = [ 'left', 'middle', 'right' ]
|
|
377
|
+
horizontalAnchor.forEach((hA) => {
|
|
378
|
+
horizontalSelf.forEach((hS) => {
|
|
379
|
+
it(`should offset horizontal position Anchor(top ${ hA }) & Self(top ${ hS }) correctly`, () => {
|
|
380
|
+
mount(WrapperOne, {
|
|
381
|
+
attrs: {
|
|
382
|
+
anchor: `top ${ hA }`,
|
|
383
|
+
self: `top ${ hS }`,
|
|
384
|
+
offset: [ 20, 0 ]
|
|
385
|
+
}
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
cy.dataCy('wrapper')
|
|
389
|
+
.click()
|
|
390
|
+
cy.dataCy('menu')
|
|
391
|
+
.checkHorizontalPosition('wrapper', hA, hS, 20)
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
})
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
describe('Category: style', () => {
|
|
399
|
+
describe('(prop): dark', () => {
|
|
400
|
+
it('should set the --q-dark color as background and white text color', () => {
|
|
401
|
+
mount(WrapperOne, {
|
|
402
|
+
attrs: {
|
|
403
|
+
dark: true
|
|
404
|
+
}
|
|
405
|
+
})
|
|
406
|
+
cy.dataCy('wrapper')
|
|
407
|
+
.click()
|
|
408
|
+
cy.dataCy('menu')
|
|
409
|
+
.should('have.color', 'white')
|
|
410
|
+
.should('have.backgroundColor', 'var(--q-dark)')
|
|
411
|
+
})
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
describe('(prop): square', () => {
|
|
415
|
+
it('should not have border-radius when using this prop', () => {
|
|
416
|
+
mount(WrapperOne, {
|
|
417
|
+
attrs: {
|
|
418
|
+
square: true
|
|
419
|
+
}
|
|
420
|
+
})
|
|
421
|
+
cy.dataCy('wrapper')
|
|
422
|
+
.click()
|
|
423
|
+
cy.dataCy('menu')
|
|
424
|
+
.should('have.css', 'border-radius', '0px')
|
|
425
|
+
})
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
describe('(prop): max-height', () => {
|
|
429
|
+
it('should specify a max-height when setting this prop', () => {
|
|
430
|
+
const maxHeight = '30px'
|
|
431
|
+
mount(WrapperOne, {
|
|
432
|
+
attrs: {
|
|
433
|
+
maxHeight
|
|
434
|
+
}
|
|
435
|
+
})
|
|
436
|
+
cy.dataCy('wrapper')
|
|
437
|
+
.click()
|
|
438
|
+
cy.dataCy('menu')
|
|
439
|
+
.should('have.css', 'max-height', maxHeight)
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
describe('(prop): max-width', () => {
|
|
444
|
+
it('should specify a max-width when setting this prop', () => {
|
|
445
|
+
const maxWidth = '30px'
|
|
446
|
+
mount(WrapperOne, {
|
|
447
|
+
attrs: {
|
|
448
|
+
maxWidth
|
|
449
|
+
}
|
|
450
|
+
})
|
|
451
|
+
cy.dataCy('wrapper')
|
|
452
|
+
.click()
|
|
453
|
+
cy.dataCy('menu')
|
|
454
|
+
.should('have.css', 'max-width', maxWidth)
|
|
455
|
+
})
|
|
456
|
+
})
|
|
457
|
+
})
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
describe('Slots', () => {
|
|
461
|
+
describe('(slot): default', () => {
|
|
462
|
+
it.skip(' ', () => {
|
|
463
|
+
//
|
|
464
|
+
})
|
|
465
|
+
})
|
|
466
|
+
})
|
|
467
|
+
|
|
468
|
+
describe('Events', () => {
|
|
469
|
+
describe('(event): escape-key', () => {
|
|
470
|
+
it('should emit @escape-key event when escape key is pressed', () => {
|
|
471
|
+
const fn = cy.stub()
|
|
472
|
+
mount(WrapperOne, {
|
|
473
|
+
attrs: {
|
|
474
|
+
onEscapeKey: fn
|
|
475
|
+
}
|
|
476
|
+
})
|
|
477
|
+
|
|
478
|
+
expect(fn).not.to.be.called
|
|
479
|
+
cy.dataCy('wrapper')
|
|
480
|
+
.click()
|
|
481
|
+
cy.dataCy('menu')
|
|
482
|
+
.should('exist')
|
|
483
|
+
.then(() => {
|
|
484
|
+
expect(fn).not.to.be.called
|
|
485
|
+
})
|
|
486
|
+
cy.get('body')
|
|
487
|
+
.type('{esc}')
|
|
488
|
+
.then(() => {
|
|
489
|
+
expect(fn).to.be.called
|
|
490
|
+
})
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
it('should not emit @escape-key event when menu is persistent', () => {
|
|
494
|
+
const fn = cy.stub()
|
|
495
|
+
mount(WrapperOne, {
|
|
496
|
+
attrs: {
|
|
497
|
+
onEscapeKey: fn,
|
|
498
|
+
persistent: true
|
|
499
|
+
}
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
expect(fn).not.to.be.called
|
|
503
|
+
cy.dataCy('wrapper')
|
|
504
|
+
.click()
|
|
505
|
+
cy.dataCy('menu')
|
|
506
|
+
.should('exist')
|
|
507
|
+
.then(() => {
|
|
508
|
+
expect(fn).not.to.be.called
|
|
509
|
+
})
|
|
510
|
+
cy.get('body')
|
|
511
|
+
.type('{esc}')
|
|
512
|
+
.then(() => {
|
|
513
|
+
expect(fn).not.to.be.called
|
|
514
|
+
})
|
|
515
|
+
})
|
|
516
|
+
})
|
|
517
|
+
})
|
|
518
|
+
|
|
519
|
+
describe('Methods', () => {
|
|
520
|
+
describe('(method): updatePosition', () => {
|
|
521
|
+
it('should reposition the menu when it is no longer in correct position', () => {
|
|
522
|
+
mount(WrapperTwo, {
|
|
523
|
+
attrs: {
|
|
524
|
+
anchor: 'bottom left',
|
|
525
|
+
self: 'bottom left'
|
|
526
|
+
}
|
|
527
|
+
})
|
|
528
|
+
|
|
529
|
+
let bottom = null
|
|
530
|
+
let left = null
|
|
531
|
+
|
|
532
|
+
cy.dataCy('wrapper')
|
|
533
|
+
.click()
|
|
534
|
+
.wait(300)
|
|
535
|
+
cy.dataCy('menu')
|
|
536
|
+
.should('exist')
|
|
537
|
+
.checkVerticalPosition('wrapper', 'bottom', 'bottom')
|
|
538
|
+
.checkHorizontalPosition('wrapper', 'left', 'left')
|
|
539
|
+
.then(($el) => {
|
|
540
|
+
const rect = $el[ 0 ].getBoundingClientRect()
|
|
541
|
+
bottom = rect.bottom
|
|
542
|
+
left = rect.left
|
|
543
|
+
})
|
|
544
|
+
cy.dataCy('div')
|
|
545
|
+
.then(($el) => {
|
|
546
|
+
$el[ 0 ].style.height = '100px'
|
|
547
|
+
cy.dataCy('menu')
|
|
548
|
+
.then(($el) => {
|
|
549
|
+
const rect = $el[ 0 ].getBoundingClientRect()
|
|
550
|
+
expect(rect.bottom).to.equal(bottom - 100)
|
|
551
|
+
expect(rect.left).to.equal(left)
|
|
552
|
+
})
|
|
553
|
+
cy.dataCy('wrapper')
|
|
554
|
+
.then(() => {
|
|
555
|
+
Cypress.vueWrapper.vm.updatePosition()
|
|
556
|
+
})
|
|
557
|
+
cy.dataCy('menu')
|
|
558
|
+
.checkVerticalPosition('wrapper', 'bottom', 'bottom')
|
|
559
|
+
.checkHorizontalPosition('wrapper', 'left', 'left')
|
|
560
|
+
})
|
|
561
|
+
})
|
|
562
|
+
})
|
|
563
|
+
|
|
564
|
+
describe('(method): focus', () => {
|
|
565
|
+
it('should focus the menu', () => {
|
|
566
|
+
mount(WrapperOne, {
|
|
567
|
+
attrs: {
|
|
568
|
+
'no-focus': true
|
|
569
|
+
}
|
|
570
|
+
})
|
|
571
|
+
|
|
572
|
+
cy.dataCy('wrapper')
|
|
573
|
+
.click()
|
|
574
|
+
cy.dataCy('menu')
|
|
575
|
+
.should('exist')
|
|
576
|
+
.should('not.have.focus')
|
|
577
|
+
cy.dataCy('wrapper')
|
|
578
|
+
.then(() => {
|
|
579
|
+
// Need to call method from wrapper
|
|
580
|
+
// Click a button closes the menu
|
|
581
|
+
Cypress.vueWrapper.vm.focusMethod()
|
|
582
|
+
})
|
|
583
|
+
cy.dataCy('menu')
|
|
584
|
+
.should('have.focus')
|
|
585
|
+
})
|
|
586
|
+
|
|
587
|
+
it('should focus the autofocus element inside the menu', () => {
|
|
588
|
+
mount(WrapperTwo, {
|
|
589
|
+
attrs: {
|
|
590
|
+
'no-focus': true
|
|
591
|
+
}
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
cy.dataCy('wrapper')
|
|
595
|
+
.click()
|
|
596
|
+
cy.dataCy('menu')
|
|
597
|
+
.should('exist')
|
|
598
|
+
.should('not.have.focus')
|
|
599
|
+
cy.dataCy('wrapper')
|
|
600
|
+
.then(() => {
|
|
601
|
+
// Need to call method from wrapper
|
|
602
|
+
// Click a button closes the menu
|
|
603
|
+
Cypress.vueWrapper.vm.focusMethod()
|
|
604
|
+
})
|
|
605
|
+
cy.dataCy('input-2')
|
|
606
|
+
.should('have.focus')
|
|
607
|
+
})
|
|
608
|
+
})
|
|
609
|
+
})
|
|
610
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div style="margin: 150px auto" class="row justify-center">
|
|
3
|
+
<q-btn color="primary" data-cy="wrapper" label="Wrapper" style="width: 100px;">
|
|
4
|
+
<q-menu v-bind="$attrs" data-cy="menu" ref="menuRef">
|
|
5
|
+
<q-list style="min-width: 120px">
|
|
6
|
+
<q-item clickable v-close-popup data-cy="close-popup">
|
|
7
|
+
<q-item-section>VClosePopup</q-item-section>
|
|
8
|
+
</q-item>
|
|
9
|
+
<q-item clickable data-cy="keep-open">
|
|
10
|
+
<q-item-section>KeepOpen</q-item-section>
|
|
11
|
+
</q-item>
|
|
12
|
+
</q-list>
|
|
13
|
+
</q-menu>
|
|
14
|
+
</q-btn>
|
|
15
|
+
</div>
|
|
16
|
+
<div data-cy="other-target" class="col-12 other-target bg-red q-pa-lg text-white">Other target</div>
|
|
17
|
+
<q-btn class="hidden" data-cy="method-show" @click="show"/>
|
|
18
|
+
<q-btn class="hidden" data-cy="method-hide" @click="hide"/>
|
|
19
|
+
<q-btn class="hidden" data-cy="method-toggle" @click="toggle"/>
|
|
20
|
+
<q-btn class="hidden" data-cy="method-focus" @click="focusMethod"/>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script>
|
|
24
|
+
import { defineComponent, ref } from 'vue'
|
|
25
|
+
|
|
26
|
+
export default defineComponent({
|
|
27
|
+
inheritAttrs: false,
|
|
28
|
+
setup () {
|
|
29
|
+
const menuRef = ref(null)
|
|
30
|
+
|
|
31
|
+
function show () {
|
|
32
|
+
menuRef.value.show()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function hide () {
|
|
36
|
+
menuRef.value.hide()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function toggle () {
|
|
40
|
+
menuRef.value.toggle()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function focusMethod () {
|
|
44
|
+
menuRef.value.focus()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return { menuRef, show, hide, toggle, focusMethod }
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
</script>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div style="margin: 200px auto" class="row justify-center">
|
|
3
|
+
<q-btn color="primary" data-cy="wrapper" label="Wrapper" style="width: 100px;">
|
|
4
|
+
<q-menu v-bind="$attrs" data-cy="menu" ref="menuRef">
|
|
5
|
+
<q-form data-cy="div" style="height: 200px">
|
|
6
|
+
<q-input label="input" data-cy="input"></q-input>
|
|
7
|
+
<q-input label="input" data-cy="input-2" autofocus></q-input>
|
|
8
|
+
</q-form>
|
|
9
|
+
</q-menu>
|
|
10
|
+
</q-btn>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
import { defineComponent, ref } from 'vue'
|
|
16
|
+
|
|
17
|
+
export default defineComponent({
|
|
18
|
+
inheritAttrs: false,
|
|
19
|
+
setup () {
|
|
20
|
+
const menuRef = ref(null)
|
|
21
|
+
|
|
22
|
+
function toggle () {
|
|
23
|
+
menuRef.value.toggle()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function focusMethod () {
|
|
27
|
+
menuRef.value.focus()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function updatePosition () {
|
|
31
|
+
menuRef.value.updatePosition()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { menuRef, toggle, focusMethod, updatePosition }
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
</script>
|