@peter.naydenov/shortcuts 3.5.2 → 4.0.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/API.md +939 -0
- package/CODE_OF_CONDUCT.md +84 -0
- package/CONTRIBUTING.md +476 -0
- package/Changelog.md +32 -2
- package/How.to.create.plugins.md +929 -0
- package/Migration.guide.md +48 -0
- package/README.md +396 -24
- package/dist/main.d.ts +54 -2
- package/dist/methods/_normalizeWithPlugins.d.ts +63 -1
- package/dist/methods/_readShortcutWithPlugins.d.ts +8 -1
- package/dist/methods/_setupPlugin.d.ts +9 -0
- package/dist/methods/_systemAction.d.ts +8 -1
- package/dist/methods/changeContext.d.ts +8 -1
- package/dist/methods/index.d.ts +2 -0
- package/dist/methods/listShortcuts.d.ts +1 -16
- package/dist/methods/load.d.ts +8 -1
- package/dist/methods/unload.d.ts +8 -1
- package/dist/plugins/click/_findTarget.d.ts +9 -1
- package/dist/plugins/click/_listenDOM.d.ts +76 -3
- package/dist/plugins/click/_normalizeShortcutName.d.ts +7 -1
- package/dist/plugins/click/_registerShortcutEvents.d.ts +26 -0
- package/dist/plugins/click/index.d.ts +6 -31
- package/dist/plugins/form/_defaults.d.ts +13 -1
- package/dist/plugins/form/_listenDOM.d.ts +66 -3
- package/dist/plugins/form/_registerShortcutEvents.d.ts +95 -1
- package/dist/plugins/form/index.d.ts +2 -29
- package/dist/plugins/hover/_findTarget.d.ts +10 -0
- package/dist/plugins/hover/_listenDOM.d.ts +68 -0
- package/dist/plugins/hover/_normalizeShortcutName.d.ts +2 -0
- package/dist/plugins/hover/_registerShortcutEvents.d.ts +28 -0
- package/dist/plugins/hover/index.d.ts +14 -0
- package/dist/plugins/key/_listenDOM.d.ts +61 -3
- package/dist/plugins/key/_registerShortcutEvents.d.ts +26 -0
- package/dist/plugins/key/_specialChars.d.ts +6 -31
- package/dist/plugins/key/index.d.ts +2 -29
- package/dist/plugins/scroll/_listenDOM.d.ts +58 -0
- package/dist/plugins/scroll/_normalizeShortcutName.d.ts +2 -0
- package/dist/plugins/scroll/_registerShortcutEvents.d.ts +28 -0
- package/dist/plugins/scroll/index.d.ts +16 -0
- package/dist/shortcuts.cjs +1 -1
- package/dist/shortcuts.esm.mjs +1 -1
- package/dist/shortcuts.umd.js +1 -1
- package/dist/src/main.d.ts +172 -0
- package/dist/src/methods/_normalizeWithPlugins.d.ts +64 -0
- package/dist/src/methods/_readShortcutWithPlugins.d.ts +9 -0
- package/dist/src/methods/_setupPlugin.d.ts +9 -0
- package/dist/src/methods/_systemAction.d.ts +9 -0
- package/dist/src/methods/changeContext.d.ts +9 -0
- package/dist/src/methods/index.d.ts +19 -0
- package/dist/src/methods/listShortcuts.d.ts +2 -0
- package/dist/src/methods/load.d.ts +9 -0
- package/dist/src/methods/unload.d.ts +9 -0
- package/dist/src/plugins/click/_findTarget.d.ts +10 -0
- package/dist/src/plugins/click/_listenDOM.d.ts +78 -0
- package/dist/src/plugins/click/_normalizeShortcutName.d.ts +8 -0
- package/dist/src/plugins/click/_readClickEvent.d.ts +2 -0
- package/dist/src/plugins/click/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/click/index.d.ts +16 -0
- package/dist/src/plugins/form/_defaults.d.ts +17 -0
- package/dist/src/plugins/form/_listenDOM.d.ts +68 -0
- package/dist/src/plugins/form/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/form/_registerShortcutEvents.d.ts +96 -0
- package/dist/src/plugins/form/index.d.ts +9 -0
- package/dist/src/plugins/hover/_findTarget.d.ts +10 -0
- package/dist/src/plugins/hover/_listenDOM.d.ts +68 -0
- package/dist/src/plugins/hover/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/hover/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/hover/index.d.ts +14 -0
- package/dist/src/plugins/key/_listenDOM.d.ts +63 -0
- package/dist/src/plugins/key/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/key/_readKeyEvent.d.ts +2 -0
- package/dist/src/plugins/key/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/key/_specialChars.d.ts +7 -0
- package/dist/src/plugins/key/index.d.ts +14 -0
- package/dist/src/plugins/scroll/_listenDOM.d.ts +58 -0
- package/dist/src/plugins/scroll/_normalizeShortcutName.d.ts +2 -0
- package/dist/src/plugins/scroll/_registerShortcutEvents.d.ts +28 -0
- package/dist/src/plugins/scroll/index.d.ts +16 -0
- package/eslint.config.js +80 -0
- package/html/assets/index-COTh6lXR.css +1 -0
- package/html/assets/index-DOkKC3NI.js +53 -0
- package/html/bg.png +0 -0
- package/html/favicon.ico +0 -0
- package/html/favicon.svg +5 -0
- package/html/html.meta.json.gz +0 -0
- package/html/index.html +32 -0
- package/package.json +24 -19
- package/shortcuts.png +0 -0
- package/src/main.js +52 -22
- package/src/methods/_normalizeWithPlugins.js +26 -2
- package/src/methods/_readShortcutWithPlugins.js +9 -2
- package/src/methods/_setupPlugin.js +93 -0
- package/src/methods/_systemAction.js +12 -4
- package/src/methods/changeContext.js +11 -3
- package/src/methods/index.js +2 -0
- package/src/methods/listShortcuts.js +5 -12
- package/src/methods/load.js +11 -4
- package/src/methods/unload.js +8 -1
- package/src/plugins/click/_findTarget.js +11 -5
- package/src/plugins/click/_listenDOM.js +58 -20
- package/src/plugins/click/_normalizeShortcutName.js +11 -4
- package/src/plugins/click/_readClickEvent.js +1 -1
- package/src/plugins/click/_registerShortcutEvents.js +33 -5
- package/src/plugins/click/index.js +33 -60
- package/src/plugins/form/_defaults.js +13 -3
- package/src/plugins/form/_listenDOM.js +46 -9
- package/src/plugins/form/_normalizeShortcutName.js +2 -2
- package/src/plugins/form/_registerShortcutEvents.js +93 -17
- package/src/plugins/form/index.js +25 -56
- package/src/plugins/hover/_findTarget.js +26 -0
- package/src/plugins/hover/_listenDOM.js +154 -0
- package/src/plugins/hover/_normalizeShortcutName.js +21 -0
- package/src/plugins/hover/_registerShortcutEvents.js +51 -0
- package/src/plugins/hover/index.js +71 -0
- package/src/plugins/key/_listenDOM.js +67 -33
- package/src/plugins/key/_normalizeShortcutName.js +4 -3
- package/src/plugins/key/_readKeyEvent.js +1 -1
- package/src/plugins/key/_registerShortcutEvents.js +34 -5
- package/src/plugins/key/_specialChars.js +5 -0
- package/src/plugins/key/index.js +34 -59
- package/src/plugins/scroll/_listenDOM.js +141 -0
- package/src/plugins/scroll/_normalizeShortcutName.js +21 -0
- package/src/plugins/scroll/_registerShortcutEvents.js +50 -0
- package/src/plugins/scroll/index.js +61 -0
- package/test/01-general.test.js +92 -23
- package/test/02-key.test.js +241 -40
- package/test/03-click.test.js +291 -47
- package/test/04-form.test.js +241 -47
- package/test/05-hover.test.js +463 -0
- package/test/06-scroll.test.js +374 -0
- package/test-helpers/Block.jsx +3 -2
- package/test-helpers/style.css +6 -1
- package/tsconfig.json +2 -1
- package/vitest.config.js +13 -11
- package/How..to.make.plugins.md +0 -41
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest'
|
|
2
|
+
import { userEvent } from 'vitest/browser'
|
|
3
|
+
import {
|
|
4
|
+
getByLabelText,
|
|
5
|
+
getByText,
|
|
6
|
+
getByTestId,
|
|
7
|
+
queryByTestId,
|
|
8
|
+
fireEvent,
|
|
9
|
+
// Tip: all queries are also exposed on an object
|
|
10
|
+
// called "queries" which you could import here as well
|
|
11
|
+
waitFor
|
|
12
|
+
} from '@testing-library/dom'
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import '../test-helpers/style.css'
|
|
17
|
+
import Block from '../test-helpers/Block.jsx'
|
|
18
|
+
import VisaulController from '@peter.naydenov/visual-controller-for-react'
|
|
19
|
+
import wait from '../test-helpers/wait.js'
|
|
20
|
+
import {
|
|
21
|
+
shortcuts
|
|
22
|
+
, pluginKey
|
|
23
|
+
, pluginClick
|
|
24
|
+
, pluginForm
|
|
25
|
+
, pluginHover
|
|
26
|
+
} from '../src/main.js'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const html = new VisaulController ();
|
|
31
|
+
let
|
|
32
|
+
a = false
|
|
33
|
+
, b = false
|
|
34
|
+
, c = null
|
|
35
|
+
;
|
|
36
|
+
|
|
37
|
+
const contextDefinition = {
|
|
38
|
+
general : {
|
|
39
|
+
' key : shift+a': [
|
|
40
|
+
() => a = true,
|
|
41
|
+
() => c = 'triggered'
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
, touch : {
|
|
45
|
+
// Mouse on
|
|
46
|
+
' hover : on': ({ target }) => {
|
|
47
|
+
b = true
|
|
48
|
+
// Named argument 'target' should be available
|
|
49
|
+
if ( target?.dataset?.hover ) c = target?.dataset?.hover
|
|
50
|
+
},
|
|
51
|
+
// Mouse off
|
|
52
|
+
'hover: off': ({ target }) => {
|
|
53
|
+
b = false
|
|
54
|
+
if ( target?.dataset?.hover ) c = target.dataset.hover
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
, extra : {
|
|
58
|
+
'key : p,r,o,b,a': () => b = true
|
|
59
|
+
}
|
|
60
|
+
, extend : {
|
|
61
|
+
'form : watch' : () => 'input'
|
|
62
|
+
, 'form : define' : () => 'input'
|
|
63
|
+
, 'form : action' : () => [
|
|
64
|
+
{
|
|
65
|
+
fn : (e) => e.target
|
|
66
|
+
, type : 'input'
|
|
67
|
+
, timing : 'in'
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
const short = shortcuts ();
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
describe ( 'Hover plugin', () => {
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
beforeEach ( async () => {
|
|
83
|
+
short.load ( contextDefinition )
|
|
84
|
+
const container = document.createElement ( 'div' );
|
|
85
|
+
container.id = 'app'
|
|
86
|
+
document.body.appendChild ( container )
|
|
87
|
+
await html.publish ( Block, {}, 'app' )
|
|
88
|
+
a = false, b = false
|
|
89
|
+
}) // beforeEach
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
afterEach ( async () => {
|
|
93
|
+
short.reset ();
|
|
94
|
+
short.disablePlugin ( 'hover' )
|
|
95
|
+
html.destroy ()
|
|
96
|
+
a = false, b = false, c = null;
|
|
97
|
+
document.body.querySelector ( '#app' ).remove ()
|
|
98
|
+
}) // afterEach
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
afterEach ( async () => {
|
|
103
|
+
short.reset ();
|
|
104
|
+
a = false, b = false, c = null;
|
|
105
|
+
}) // afterEach
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
it ( 'No "hover" plugin installed', async () => {
|
|
110
|
+
const r = short.listShortcuts ('touch');
|
|
111
|
+
// Shortcuts are untouched if plugin is not installed
|
|
112
|
+
expect ( r[0]).to.equal ( ' hover : on' )
|
|
113
|
+
}) // it no 'hover' plugin installed
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
it ( 'Hover plugin installed', async () => {
|
|
118
|
+
short.enablePlugin ( pluginHover )
|
|
119
|
+
const r = short.listShortcuts ( 'touch' );
|
|
120
|
+
// Shortcuts are normalized
|
|
121
|
+
expect ( r[0]).to.equal ( 'HOVER:ON' )
|
|
122
|
+
}) // it hover plugin installed
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
it ( 'Mouse on', async () => {
|
|
127
|
+
expect ( b ).to.equal ( false )
|
|
128
|
+
short.enablePlugin ( pluginHover )
|
|
129
|
+
short.changeContext ( 'touch' )
|
|
130
|
+
await userEvent.hover ( document.querySelector ( '#rspan' ) )
|
|
131
|
+
await wait ( 320 )
|
|
132
|
+
await waitFor ( () => {
|
|
133
|
+
expect ( b ).to.equal ( true )
|
|
134
|
+
// Target is a element that contains data-hover property!
|
|
135
|
+
expect ( c ).to.equal ( 'red' )
|
|
136
|
+
// We hovered on span, but target is the parent element
|
|
137
|
+
// that contains data-hover property
|
|
138
|
+
}, { timeout: 1000, interval: 12 })
|
|
139
|
+
}) // it mouse on
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
it ( 'Mouse off', async () => {
|
|
144
|
+
short.enablePlugin ( pluginHover )
|
|
145
|
+
short.changeContext ( 'touch' )
|
|
146
|
+
const hoverElement = document.querySelector ( '#rspan' );
|
|
147
|
+
await userEvent.hover ( hoverElement )
|
|
148
|
+
await wait ( 320 )
|
|
149
|
+
await waitFor ( () => {
|
|
150
|
+
expect ( b ).to.equal ( true )
|
|
151
|
+
expect ( c ).to.equal ( 'red' )
|
|
152
|
+
}, { timeout: 1000, interval: 12 })
|
|
153
|
+
// Simulate off by hovering another element
|
|
154
|
+
// await userEvent.hover ( document.body )
|
|
155
|
+
const unhoverToInput = document.querySelector ( '#name' );
|
|
156
|
+
await userEvent.hover ( unhoverToInput )
|
|
157
|
+
await wait ( 320 )
|
|
158
|
+
await waitFor ( () => {
|
|
159
|
+
expect ( b ).to.equal ( false )
|
|
160
|
+
expect ( c ).to.equal ( 'red' )
|
|
161
|
+
}, { timeout: 1000, interval: 12 })
|
|
162
|
+
}) // it mouse off
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
it ( 'Arguments of hover handler', async () => {
|
|
167
|
+
/**
|
|
168
|
+
* Need to know arguments for 'hover' handler
|
|
169
|
+
* function myHoverHandler ({
|
|
170
|
+
* context // (string) Name of the current context;
|
|
171
|
+
* , note // (string) Name of the note or null if note isn't set;
|
|
172
|
+
* , dependencies // (object) Object with dependencies that you have set by calling `setDependencies` method;
|
|
173
|
+
* , target // (DOM element). Target element of the hover event;
|
|
174
|
+
* , targetProps // (object). Coordinates of the target element (top, left, right, bottom, width, height) or null if target element is not available;
|
|
175
|
+
* , x // (number). X coordinate of the target element;
|
|
176
|
+
* , y // (number). Y coordinate of the target element;
|
|
177
|
+
* , event // (object). Original hover event object;
|
|
178
|
+
* }) {
|
|
179
|
+
* // Body of the handler. Do something...
|
|
180
|
+
* }
|
|
181
|
+
*/
|
|
182
|
+
// Ensure clean state for this test
|
|
183
|
+
const megaBtn = document.querySelector ( '[data-click="mega"]' )
|
|
184
|
+
const test = [];
|
|
185
|
+
let i = 0;
|
|
186
|
+
short.enablePlugin ( pluginHover )
|
|
187
|
+
short.setDependencies ({ test })
|
|
188
|
+
short.load ({
|
|
189
|
+
'local' : {
|
|
190
|
+
'hover : on' : ({
|
|
191
|
+
dependencies
|
|
192
|
+
, target
|
|
193
|
+
, x
|
|
194
|
+
, y
|
|
195
|
+
, targetProps
|
|
196
|
+
, context
|
|
197
|
+
}) => {
|
|
198
|
+
const
|
|
199
|
+
{ test } = dependencies
|
|
200
|
+
, result = {
|
|
201
|
+
x
|
|
202
|
+
, y
|
|
203
|
+
, targetProps
|
|
204
|
+
, context
|
|
205
|
+
}
|
|
206
|
+
;
|
|
207
|
+
result.target = target.dataset.hover
|
|
208
|
+
test.push ( result )
|
|
209
|
+
i++
|
|
210
|
+
}
|
|
211
|
+
} // local
|
|
212
|
+
})
|
|
213
|
+
short.changeContext ( 'local' )
|
|
214
|
+
expect ( megaBtn ).to.not.be.null
|
|
215
|
+
await userEvent.hover ( megaBtn )
|
|
216
|
+
await wait ( 340 ) // Wait for hover processing
|
|
217
|
+
await waitFor ( () => {
|
|
218
|
+
expect ( i ).to.be.equal ( 1 )
|
|
219
|
+
const result = test[0];
|
|
220
|
+
expect ( result.target ).to.be.equal ( 'blue' )
|
|
221
|
+
expect ( result.context ).to.be.equal ( 'local' )
|
|
222
|
+
}, { timeout: 1000, interval: 12 })
|
|
223
|
+
}) // it arguments of hover handler
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
it ( 'Hover on anchor', async () => {
|
|
228
|
+
// Hover on anchor that don't have hover-data attribute.
|
|
229
|
+
let result = 'none';
|
|
230
|
+
short.enablePlugin ( pluginHover )
|
|
231
|
+
short.load ({ 'extra' : {
|
|
232
|
+
'hover : on' : ({target, context, event }) => {
|
|
233
|
+
expect ( context ).to.be.equal ( 'extra' )
|
|
234
|
+
expect ( target.nodeName ).to.be.equal ( 'DIV' )
|
|
235
|
+
result = target.nodeName
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
short.changeContext ( 'extra' )
|
|
240
|
+
const loc = document.querySelector ( '#rspan' ) || false;
|
|
241
|
+
if ( loc ) await userEvent.hover ( loc )
|
|
242
|
+
await waitFor ( () => {
|
|
243
|
+
expect ( result ).to.be.equal ( 'DIV' )
|
|
244
|
+
}, { timeout: 1000, interval: 12 })
|
|
245
|
+
}) // it hover on anchor
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
it ( 'Mute and unmute hover plugin', async () => {
|
|
250
|
+
const
|
|
251
|
+
result = []
|
|
252
|
+
, trg = document.querySelector ( '#rspan' )
|
|
253
|
+
, offTarget = document.querySelector ( '#name' )
|
|
254
|
+
;
|
|
255
|
+
|
|
256
|
+
let i = 0;
|
|
257
|
+
short.setDependencies ({ result })
|
|
258
|
+
result.push ( 'init' )
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
short.load ({
|
|
262
|
+
'local' : {
|
|
263
|
+
'hover : on' : ({dependencies}) => {
|
|
264
|
+
const { result } = dependencies;
|
|
265
|
+
result.push ( i++ )
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
short.enablePlugin ( pluginHover )
|
|
271
|
+
short.changeContext ( 'local' )
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
await userEvent.hover ( trg )
|
|
275
|
+
await wait( 320 )
|
|
276
|
+
await waitFor ( () => {
|
|
277
|
+
// We checking if the shortcut works
|
|
278
|
+
expect ( result ).to.have.lengthOf ( 2 )
|
|
279
|
+
expect ( i ).to.equal ( 1 )
|
|
280
|
+
}, { timeout: 1000, interval: 12 })
|
|
281
|
+
|
|
282
|
+
short.mutePlugin ( 'hover' )
|
|
283
|
+
await userEvent.hover ( offTarget )
|
|
284
|
+
await userEvent.hover ( trg )
|
|
285
|
+
|
|
286
|
+
await wait ( 320 )
|
|
287
|
+
await waitFor ( () => {
|
|
288
|
+
// Plugin is muted, so we don't expect any changes
|
|
289
|
+
expect ( result ).to.have.lengthOf ( 2 )
|
|
290
|
+
expect ( i ).to.equal ( 1 )
|
|
291
|
+
}, { timeout: 1000, interval: 12 })
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
await userEvent.hover ( offTarget )
|
|
295
|
+
short.unmutePlugin ( 'hover' )
|
|
296
|
+
await userEvent.hover ( trg )
|
|
297
|
+
|
|
298
|
+
await wait ( 320 )
|
|
299
|
+
await waitFor ( () => {
|
|
300
|
+
// Plugin is unmuted, should work again
|
|
301
|
+
expect ( result ).to.have.lengthOf ( 3 )
|
|
302
|
+
expect ( i ).to.equal ( 2 )
|
|
303
|
+
}, { timeout: 1000, interval: 12 })
|
|
304
|
+
}) // it mute and unmute hover plugin
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
it ( 'Pause and resume', async () => {
|
|
309
|
+
const
|
|
310
|
+
target = document.querySelector ( '#rspan' )
|
|
311
|
+
, targetOff = document.querySelector ( '#name' )
|
|
312
|
+
;
|
|
313
|
+
|
|
314
|
+
short.enablePlugin ( pluginHover )
|
|
315
|
+
expect ( b ).to.be.equal ( false )
|
|
316
|
+
|
|
317
|
+
short.changeContext ( 'touch' )
|
|
318
|
+
short.pause ( 'hover : on' )
|
|
319
|
+
|
|
320
|
+
await userEvent.hover ( target )
|
|
321
|
+
await wait ( 100 )
|
|
322
|
+
await waitFor ( () => {
|
|
323
|
+
expect ( b ).to.be.equal ( false )
|
|
324
|
+
}, { timeout: 1000, interval: 30 })
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
await userEvent.hover ( targetOff )
|
|
328
|
+
short.resume ( 'hover : on' )
|
|
329
|
+
|
|
330
|
+
await userEvent.hover ( target )
|
|
331
|
+
await wait ( 100 )
|
|
332
|
+
await waitFor ( () => {
|
|
333
|
+
expect ( b ).to.be.equal ( true )
|
|
334
|
+
expect ( c ).to.be.equal ( 'red' )
|
|
335
|
+
}, { timeout: 1000, interval: 30 })
|
|
336
|
+
}) // it pause and resume
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
it ( 'Fast move over hover target', async () => {
|
|
341
|
+
const
|
|
342
|
+
target = document.querySelector ( '#rspan' )
|
|
343
|
+
, targetOff = document.querySelector ( '#name' )
|
|
344
|
+
;
|
|
345
|
+
|
|
346
|
+
short.enablePlugin ( pluginHover )
|
|
347
|
+
expect ( b ).to.be.equal ( false )
|
|
348
|
+
|
|
349
|
+
short.changeContext ( 'touch' )
|
|
350
|
+
await userEvent.hover ( target )
|
|
351
|
+
await wait ( 200 )
|
|
352
|
+
await waitFor ( () => {
|
|
353
|
+
expect ( b ).to.be.equal ( false )
|
|
354
|
+
}, { timeout: 1000, interval: 30 })
|
|
355
|
+
|
|
356
|
+
await userEvent.hover ( targetOff )
|
|
357
|
+
await wait ( 320 )
|
|
358
|
+
await waitFor ( () => {
|
|
359
|
+
expect ( b ).to.be.equal ( false )
|
|
360
|
+
}, { timeout: 1000, interval: 30 })
|
|
361
|
+
}) // it fast move over hover target
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
it ( 'Immediate hover switch between elements', async () => {
|
|
366
|
+
// Test lines 91-93: immediate hover switch without delay
|
|
367
|
+
const events = [];
|
|
368
|
+
short.setDependencies ({ events })
|
|
369
|
+
short.load ({
|
|
370
|
+
'immediate' : {
|
|
371
|
+
'hover : on' : ({ target, dependencies }) => {
|
|
372
|
+
const { events } = dependencies;
|
|
373
|
+
events.push ( { type: 'on', target: target.dataset.hover || target.id } )
|
|
374
|
+
}
|
|
375
|
+
, 'hover: off' : ({ target, dependencies }) => {
|
|
376
|
+
const { events } = dependencies;
|
|
377
|
+
events.push ( { type: 'off', target: target.dataset.hover || target.id } )
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
short.enablePlugin ( pluginHover )
|
|
383
|
+
short.changeContext ( 'immediate' )
|
|
384
|
+
|
|
385
|
+
const
|
|
386
|
+
firstTarget = document.querySelector ( '#rspan' ) // Has data-hover="red"
|
|
387
|
+
, secondTarget = document.querySelector ( '[data-click="mega"]' ) // Has data-hover="blue"
|
|
388
|
+
;
|
|
389
|
+
|
|
390
|
+
// Hover on first element
|
|
391
|
+
await userEvent.hover ( firstTarget )
|
|
392
|
+
await wait ( 320 )
|
|
393
|
+
await waitFor ( () => {
|
|
394
|
+
expect ( events ).to.have.length ( 1 )
|
|
395
|
+
expect ( events[0] ).to.deep.equal ( { type: 'on', target: 'red' } )
|
|
396
|
+
}, { timeout: 1000, interval: 12 })
|
|
397
|
+
|
|
398
|
+
// Immediately hover on second element (tests lines 91-93)
|
|
399
|
+
// This should trigger immediate HOVER:OFF for first element
|
|
400
|
+
events.length = 0 // Reset events array
|
|
401
|
+
await userEvent.hover ( secondTarget )
|
|
402
|
+
await wait ( 50 ) // Very short wait to capture immediate events
|
|
403
|
+
|
|
404
|
+
// Should have immediate OFF event for first element
|
|
405
|
+
await waitFor ( () => {
|
|
406
|
+
expect ( events ).to.have.length ( 1 )
|
|
407
|
+
expect ( events[0] ).to.deep.equal ( { type: 'off', target: 'red' } )
|
|
408
|
+
}, { timeout: 500, interval: 12 })
|
|
409
|
+
|
|
410
|
+
// Wait for ON event for second element
|
|
411
|
+
await wait ( 270 ) // Total 320ms wait
|
|
412
|
+
await waitFor ( () => {
|
|
413
|
+
expect ( events ).to.have.length ( 2 )
|
|
414
|
+
expect ( events[1] ).to.deep.equal ( { type: 'on', target: 'blue' } )
|
|
415
|
+
}, { timeout: 500, interval: 12 })
|
|
416
|
+
}) // it immediate hover switch between elements
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
it ( 'Extra parameters to plugin options', async () => {
|
|
420
|
+
short.enablePlugin ( pluginHover )
|
|
421
|
+
const emit = [];
|
|
422
|
+
const setupContext = {
|
|
423
|
+
'hover:setup' : () => {
|
|
424
|
+
emit.push ( 'setup' )
|
|
425
|
+
return { wait: 100, customParam: 'test-value', emit }
|
|
426
|
+
},
|
|
427
|
+
'hover:on' : ({options}) => {
|
|
428
|
+
expect ( options.wait ).to.equal ( 100 )
|
|
429
|
+
expect ( options.customParam ).to.equal ( 'test-value' )
|
|
430
|
+
options.emit.push ( 'on' )
|
|
431
|
+
},
|
|
432
|
+
'hover:off' : ({options}) => {
|
|
433
|
+
expect ( options.wait ).to.equal ( 100 )
|
|
434
|
+
expect ( options.customParam ).to.equal ( 'test-value' )
|
|
435
|
+
options.emit.push ( 'off' )
|
|
436
|
+
}
|
|
437
|
+
} // setupContext
|
|
438
|
+
|
|
439
|
+
short.load ({ setupContext })
|
|
440
|
+
short.changeContext ( 'setupContext' )
|
|
441
|
+
|
|
442
|
+
// Setup event execution is on change context:
|
|
443
|
+
expect ( emit[0] ).to.equal ( 'setup' )
|
|
444
|
+
|
|
445
|
+
// Test hover on and off with modified options
|
|
446
|
+
const target = document.querySelector ( '#rspan' )
|
|
447
|
+
await userEvent.hover ( target )
|
|
448
|
+
await wait ( 150 ) // Wait for modified hover time (100ms + buffer)
|
|
449
|
+
await waitFor ( () => {
|
|
450
|
+
expect ( emit ).to.deep.equal ( [ 'setup', 'on' ] )
|
|
451
|
+
}, { timeout: 1000, interval: 12 })
|
|
452
|
+
|
|
453
|
+
// Test hover off
|
|
454
|
+
await userEvent.hover ( document.querySelector ( '#name' ) )
|
|
455
|
+
await wait ( 150 )
|
|
456
|
+
await waitFor ( () => {
|
|
457
|
+
expect ( emit ).to.deep.equal ( [ 'setup', 'on', 'off' ] )
|
|
458
|
+
}, { timeout: 1000, interval: 12 })
|
|
459
|
+
}) // it extra parameters to plugin options
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
}) // describe
|