@peter.naydenov/shortcuts 3.1.2 → 3.1.4
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/Changelog.md +10 -0
- package/index.html +21 -13
- package/package.json +14 -12
- package/src/main.js +3 -3
- package/src/plugins/key/_listenDOM.js +1 -1
- package/test/01-general.test.js +287 -0
- package/vitest-example/HelloWorld.js +9 -0
- package/vitest-example/HelloWorld.test.js +11 -0
- package/vitest.workspace.js +19 -0
- package/cypress/fixtures/example.json +0 -5
- package/cypress/support/commands.js +0 -25
- package/cypress/support/component-index.html +0 -14
- package/cypress/support/component.js +0 -27
- package/cypress/support/e2e.js +0 -20
- package/cypress.config.js +0 -10
- package/test/01-general.cy.js +0 -246
package/Changelog.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
## Release History
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
|
|
5
|
+
### 3.1.4 ( 2025-05-3)
|
|
6
|
+
- [x] Dependency update. @peter.naydenov/notice - v.2.4.1
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### 3.1.3 ( 2025-01-12)
|
|
10
|
+
- [x] Dependency update. @peter.naydenov/notice - v.2.4.0
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
4
14
|
### 3.1.2 ( 2024-12-23 )
|
|
5
15
|
- [x] Dependency update. @peter.naydenov/notice - v.2.3.2
|
|
6
16
|
|
package/index.html
CHANGED
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
</head>
|
|
23
23
|
<body>
|
|
24
24
|
<script type="module">
|
|
25
|
-
import
|
|
25
|
+
import { shortcuts, pluginKey, pluginClick } from '/src/main.js'
|
|
26
26
|
|
|
27
27
|
const options = {
|
|
28
|
-
onShortcut (
|
|
28
|
+
onShortcut ( shortcut, { context, note }) {
|
|
29
29
|
console.log ( '-- RESULTS --->' )
|
|
30
30
|
console.log ( 'Shortcut', shortcut )
|
|
31
31
|
console.log ( 'Context:', context )
|
|
@@ -33,31 +33,39 @@
|
|
|
33
33
|
} // onShortcut func.
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const short =
|
|
36
|
+
const short = shortcuts ( options );
|
|
37
|
+
short.enablePlugin( pluginKey )
|
|
38
|
+
short.enablePlugin( pluginClick )
|
|
39
|
+
|
|
40
|
+
|
|
37
41
|
short.load ( { general : {
|
|
38
|
-
'q' : [ () => console.log('Q was clicked') ]
|
|
39
|
-
, 'r,o,s' : () => console.log ( 'ROS was clicked' )
|
|
40
|
-
, '
|
|
41
|
-
, 'r' : [
|
|
42
|
+
'key:q' : [ () => console.log('Q was clicked') ]
|
|
43
|
+
, 'key:r,o,s' : () => console.log ( 'ROS was clicked' )
|
|
44
|
+
, 'click:left-2' : () => console.log ( 'Mouse left click 2' )
|
|
45
|
+
, 'key:r' : [
|
|
42
46
|
({isWaiting}) => {
|
|
43
47
|
if ( !isWaiting() ) {
|
|
44
48
|
console.log ( 'R was clicked' )
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
]
|
|
48
|
-
, 'shift+w' : [
|
|
52
|
+
, 'key:shift+w' : [
|
|
49
53
|
({wait, end, ignore, isWaiting, note }) => {
|
|
54
|
+
console.log ( 'HIT a shift + w')
|
|
50
55
|
ignore ()
|
|
51
56
|
if ( isWaiting () ) {
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
end ()
|
|
58
|
+
console.log('END')
|
|
54
59
|
}
|
|
55
60
|
else {
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
console.log('WAIT')
|
|
62
|
+
wait ()
|
|
58
63
|
}
|
|
59
64
|
},
|
|
60
|
-
() =>
|
|
65
|
+
({end}) => {
|
|
66
|
+
console.log ( 'W' )
|
|
67
|
+
setTimeout ( end, 3000 )
|
|
68
|
+
}
|
|
61
69
|
]
|
|
62
70
|
}
|
|
63
71
|
})
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peter.naydenov/shortcuts",
|
|
3
3
|
"description": "Context control of shortcuts based on keyboard and mouse events",
|
|
4
|
-
"version": "3.1.
|
|
4
|
+
"version": "3.1.4",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Peter Naydenov",
|
|
7
7
|
"main": "./dist/shortcuts.umd.js",
|
|
@@ -19,27 +19,29 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"dev": "vite",
|
|
21
21
|
"build": "rollup -c",
|
|
22
|
-
"test": "
|
|
22
|
+
"test": "vitest --workspace=vitest.workspace.js"
|
|
23
23
|
},
|
|
24
24
|
"repository": {
|
|
25
25
|
"type": "git",
|
|
26
26
|
"url": "git+https://github.com/PeterNaydenov/shortcuts"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@peter.naydenov/notice": "^2.
|
|
29
|
+
"@peter.naydenov/notice": "^2.4.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"@rollup/plugin-
|
|
32
|
+
"@peter.naydenov/visual-controller-for-react": "^3.0.0",
|
|
33
|
+
"@rollup/plugin-commonjs": "^28.0.3",
|
|
34
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
34
35
|
"@rollup/plugin-terser": "^0.4.4",
|
|
35
|
-
"@vitejs/plugin-react": "^4.
|
|
36
|
+
"@vitejs/plugin-react": "^4.4.1",
|
|
37
|
+
"@vitest/browser": "^3.1.2",
|
|
36
38
|
"ask-for-promise": "^3.0.1",
|
|
37
|
-
"chai": "^5.
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"react": "^19.0.
|
|
41
|
-
"react-dom": "^19.0.
|
|
42
|
-
"vite": "^6.
|
|
39
|
+
"chai": "^5.2.0",
|
|
40
|
+
"mocha": "^11.2.2",
|
|
41
|
+
"playwright": "^1.52.0",
|
|
42
|
+
"react": "^19.0.1",
|
|
43
|
+
"react-dom": "^19.0.1",
|
|
44
|
+
"vite": "^6.3.4"
|
|
43
45
|
},
|
|
44
46
|
"keywords": [
|
|
45
47
|
"shortcut",
|
package/src/main.js
CHANGED
|
@@ -103,21 +103,21 @@ function main ( options = {} ) {
|
|
|
103
103
|
/**
|
|
104
104
|
* @function getContext
|
|
105
105
|
* @description Get current context name
|
|
106
|
-
* @returns {string} - Current context name
|
|
106
|
+
* @returns {string|null} - Current context name
|
|
107
107
|
*/
|
|
108
108
|
API.getContext = () => state.currentContext.name
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
111
|
* @function getNote
|
|
112
112
|
* @description Get current context note
|
|
113
|
-
* @returns {string} - Current context note
|
|
113
|
+
* @returns {string|null} - Current context note
|
|
114
114
|
*/
|
|
115
115
|
API.getNote = () => state.currentContext.note
|
|
116
116
|
|
|
117
117
|
/**
|
|
118
118
|
* @function setNote
|
|
119
119
|
* @description Set current context note
|
|
120
|
-
* @param {string} note - Context note
|
|
120
|
+
* @param {string|null} note - Context note
|
|
121
121
|
* @returns {void}
|
|
122
122
|
*/
|
|
123
123
|
API.setNote = (note=null) => { if (typeof note === 'string' || note == null ) state.currentContext.note = note }
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { beforeEach, describe, it, test } from 'vitest'
|
|
2
|
+
import { userEvent } from '@vitest/browser/context'
|
|
3
|
+
|
|
4
|
+
import Block from '../test-components/Block.jsx'
|
|
5
|
+
import VisaulController from '@peter.naydenov/visual-controller-for-react'
|
|
6
|
+
import '../test-components/style.css'
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
pluginClick,
|
|
10
|
+
pluginKey
|
|
11
|
+
, shortcuts
|
|
12
|
+
} from '../src/main.js'
|
|
13
|
+
import { expect } from 'chai'
|
|
14
|
+
|
|
15
|
+
import askForPromise from 'ask-for-promise'
|
|
16
|
+
|
|
17
|
+
const html = new VisaulController ();
|
|
18
|
+
|
|
19
|
+
let
|
|
20
|
+
a = false
|
|
21
|
+
, b = false
|
|
22
|
+
;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
function wait (ms) {
|
|
26
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const short = shortcuts ({onShortcut : ( shortcut, {context,note,type}) => console.log (shortcut, context, note, type) });
|
|
30
|
+
|
|
31
|
+
short.load ({
|
|
32
|
+
general : {
|
|
33
|
+
' key : shift+a': [ () => a = true ]
|
|
34
|
+
}
|
|
35
|
+
, extra : {
|
|
36
|
+
'key : p,r,o,b,a': () => b = true
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
beforeEach ( () => {
|
|
41
|
+
let container = document.createElement ( 'div' )
|
|
42
|
+
container.id = 'app'
|
|
43
|
+
document.body.appendChild ( container )
|
|
44
|
+
html.publish ( Block, {}, 'app' )
|
|
45
|
+
a = false, b = false
|
|
46
|
+
}) // beforeEach
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
describe ( "Shortcuts", () => {
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
test ( 'Shortcut if no plugin installed', () => {
|
|
57
|
+
let res = new Promise ( (resolve,reject) => {
|
|
58
|
+
short.changeContext ( 'general' )
|
|
59
|
+
let r = short.listShortcuts ('general')
|
|
60
|
+
expect ( r[0]).to.equal ( ' key : shift+a' ) // Shortcut name is the same as it was set
|
|
61
|
+
resolve ('success')
|
|
62
|
+
})
|
|
63
|
+
return res
|
|
64
|
+
}) // test no plugin installed
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
test ( 'Key plugin, no context selected', () => {
|
|
69
|
+
const res = new Promise ( ( resolve ) => {
|
|
70
|
+
short.enablePlugin ( pluginKey )
|
|
71
|
+
const r = short.listShortcuts ( 'general' )
|
|
72
|
+
expect ( r[0] ).to.equal ( 'KEY:A+SHIFT' ) // Shortcut name is recognized by plugin and is normalized
|
|
73
|
+
resolve ('success')
|
|
74
|
+
})
|
|
75
|
+
return res
|
|
76
|
+
}) // test key plugin installed, no context selected
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
test ( 'Key plugin with context selected', () => {
|
|
81
|
+
const res = new Promise ( (resolve) => {
|
|
82
|
+
short.enablePlugin ( pluginKey )
|
|
83
|
+
short.changeContext ( 'general' )
|
|
84
|
+
const r = short.listShortcuts ('general')
|
|
85
|
+
expect ( r[0] ).to.equal ( 'KEY:A+SHIFT' ) // Shortcut name is recognized by plugin and is normalized
|
|
86
|
+
resolve ( 'success' )
|
|
87
|
+
})
|
|
88
|
+
return res
|
|
89
|
+
}) // test key plugin installed with context selected
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
test ( 'Simple shortcut', () => {
|
|
94
|
+
const res = new Promise ( (resolve) => {
|
|
95
|
+
short.enablePlugin ( pluginKey )
|
|
96
|
+
short.changeContext ()
|
|
97
|
+
short.changeContext ( 'general' )
|
|
98
|
+
userEvent.keyboard ( '{Shift>}a</Shift>' )
|
|
99
|
+
expect ( a ).to.be.false
|
|
100
|
+
wait ( 1000 )
|
|
101
|
+
.then ( () => { // Default wait sequence timeout is 480 ms, but maxSequence is 1, so we don't need to wait for timeout
|
|
102
|
+
expect ( a ).to.be.true
|
|
103
|
+
resolve ( 'success' )
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
return res
|
|
107
|
+
}) // test simple shortcut
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
test ( 'Call sequence shortcut', async () => {
|
|
112
|
+
let res = new Promise ( async (resolve) => {
|
|
113
|
+
b = false
|
|
114
|
+
short.enablePlugin ( pluginKey )
|
|
115
|
+
short.changeContext ()
|
|
116
|
+
short.changeContext ( 'extra' )
|
|
117
|
+
await userEvent.keyboard ( 'proba' )
|
|
118
|
+
expect ( b ).to.be.true
|
|
119
|
+
resolve ( 'success' )
|
|
120
|
+
})
|
|
121
|
+
return res
|
|
122
|
+
}) // test call sequence shortcut
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
test ( 'Single mouse click', done => {
|
|
127
|
+
const res = new Promise ( async (resolve) => {
|
|
128
|
+
expect ( a ).to.be.false
|
|
129
|
+
expect ( b ).to.be.false
|
|
130
|
+
short.enablePlugin ( pluginClick )
|
|
131
|
+
|
|
132
|
+
short.load ({ 'extra' : {
|
|
133
|
+
' cLIck : left - 1 ' : () => a = true // Check if spaces, letter case can break the shortcut recognition
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
short.changeContext ()
|
|
137
|
+
short.changeContext ( 'extra' )
|
|
138
|
+
wait ( 100 )
|
|
139
|
+
.then ( async () => {
|
|
140
|
+
// Default wait mouse timeout is 320 ms, but maxClicks is 1, so we don't need to wait for timeout
|
|
141
|
+
let loc = document.querySelector('#rspan') || false
|
|
142
|
+
if ( loc ) await userEvent.click ( loc )
|
|
143
|
+
expect ( a ).to.be.true
|
|
144
|
+
resolve ( 'success' )
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
})
|
|
149
|
+
return res
|
|
150
|
+
}) // test single mouse click
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
test ( 'Double mouse click', () => {
|
|
155
|
+
let res = new Promise ( async (resolve) => {
|
|
156
|
+
expect ( a ).to.be.false
|
|
157
|
+
expect ( b ).to.be.false
|
|
158
|
+
|
|
159
|
+
short.enablePlugin ( pluginClick )
|
|
160
|
+
short.changeContext ( 'extra' )
|
|
161
|
+
short.load ({ // load will restart the selected context
|
|
162
|
+
'extra' : { // load will overwrite existing 'extra' context definition
|
|
163
|
+
'click: left-2' : () => a = true
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
wait ( 350 )
|
|
167
|
+
.then ( async () => { // Default wait mouse timeout is 320 ms
|
|
168
|
+
let loc = document.querySelector ( '#rspan' ) || false
|
|
169
|
+
// Third click is ignored. Max clicks according definition is 2.
|
|
170
|
+
if ( loc ) await userEvent.tripleClick ( loc )
|
|
171
|
+
expect ( a ).to.be.true
|
|
172
|
+
resolve ( 'success' )
|
|
173
|
+
})
|
|
174
|
+
})
|
|
175
|
+
return res
|
|
176
|
+
}) // test double mouse click
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
test ( 'Dependencies on shortcuts', () => {
|
|
181
|
+
const res = new Promise ( async (resolve) => {
|
|
182
|
+
const task = askForPromise ();
|
|
183
|
+
expect ( a ).to.be.false
|
|
184
|
+
expect ( b ).to.be.false
|
|
185
|
+
|
|
186
|
+
short.enablePlugin ( pluginClick )
|
|
187
|
+
short.setDependencies ({ task })
|
|
188
|
+
|
|
189
|
+
short.load ({
|
|
190
|
+
'extra' : { // load will overwrite existing 'extra' context definition
|
|
191
|
+
'click: left-1' : ({dependencies}) => {
|
|
192
|
+
const { task } = dependencies;
|
|
193
|
+
expect ( task ).to.have.property ( 'done' )
|
|
194
|
+
expect ( task ).to.have.property ( 'promise' )
|
|
195
|
+
a = true
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}) // load will restart the selected context
|
|
199
|
+
short.changeContext ( 'extra' )
|
|
200
|
+
wait ( 350 ) // Default wait mouse timeout is 320 ms
|
|
201
|
+
.then ( async () => {
|
|
202
|
+
let loc = document.querySelector ( '#rspan' ) || false
|
|
203
|
+
if ( loc ) await userEvent.click ( loc )
|
|
204
|
+
resolve ( 'success' )
|
|
205
|
+
})
|
|
206
|
+
}) // res promise
|
|
207
|
+
return res
|
|
208
|
+
}) // test dependencies on shortcuts
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
test ( 'Emit custom event', () => {
|
|
213
|
+
const res = new Promise ( async (resolve) => {
|
|
214
|
+
let result = null;
|
|
215
|
+
short.changeContext ()
|
|
216
|
+
short.enablePlugin ( pluginClick )
|
|
217
|
+
const myAllContext = {
|
|
218
|
+
myAll: {
|
|
219
|
+
'click : leff-1' : () => console.log ( 'nothing' )
|
|
220
|
+
, 'yo' : ({msg}) => result = msg
|
|
221
|
+
}}
|
|
222
|
+
short.load ( myAllContext )
|
|
223
|
+
short.changeContext ( 'myAll' )
|
|
224
|
+
short.emit ( 'yo', { context: short.getContext(), note: 'tt', type:'custom', msg:'hello' })
|
|
225
|
+
expect ( result ).to.be.equal ( 'hello' )
|
|
226
|
+
short.changeContext ( 'general' )
|
|
227
|
+
short.unload ( 'myAll' )
|
|
228
|
+
resolve ( 'success' )
|
|
229
|
+
})
|
|
230
|
+
return res
|
|
231
|
+
}) // test emit custom event
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
test ( 'List shortcuts', () => {
|
|
236
|
+
short.enablePlugin ( pluginKey )
|
|
237
|
+
let general = short.listShortcuts ('general');
|
|
238
|
+
expect ( general ).to.be.an ( 'array' )
|
|
239
|
+
expect ( general ).to.have.lengthOf ( 1 )
|
|
240
|
+
expect ( general[0] ).to.be.equal ( 'KEY:A+SHIFT' )
|
|
241
|
+
|
|
242
|
+
let fail = short.listShortcuts ( 'somethingNotExisting' );
|
|
243
|
+
expect ( fail ).to.be.null
|
|
244
|
+
|
|
245
|
+
let all = short.listShortcuts ();
|
|
246
|
+
expect ( all ).to.be.an ( 'array' )
|
|
247
|
+
|
|
248
|
+
expect ( all ).to.have.lengthOf ( 2 )
|
|
249
|
+
expect ( all[0] ).to.have.property ( 'context' )
|
|
250
|
+
expect ( all[0] ).to.have.property ( 'shortcuts' )
|
|
251
|
+
expect ( all[0].shortcuts ).to.be.an('array')
|
|
252
|
+
expect ( all[0].shortcuts ).to.have.lengthOf ( 1 )
|
|
253
|
+
expect ( all[0].shortcuts[0] ).to.be.equal ( 'KEY:A+SHIFT' )
|
|
254
|
+
expect ( all[0].context ).to.be.equal ( 'general' )
|
|
255
|
+
}) // test list shortcuts
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
test ( 'Click on anchor', () => {
|
|
260
|
+
const res = new Promise ( async (resolve) => {
|
|
261
|
+
// Click on anchor that don't have click-data attribute.
|
|
262
|
+
let result = 'none';
|
|
263
|
+
short.enablePlugin ( pluginClick )
|
|
264
|
+
short.load ({ 'extra' : {
|
|
265
|
+
'click: 1 - left' : ({target, context, event }) => { // Order of button name and number of click is not important
|
|
266
|
+
event.preventDefault ()
|
|
267
|
+
expect ( context ).to.be.equal ( 'extra' )
|
|
268
|
+
expect ( target.nodeName ).to.be.equal ( 'A' )
|
|
269
|
+
result = target.nodeName
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
short.changeContext ( 'extra' )
|
|
274
|
+
wait ( 10 )
|
|
275
|
+
.then ( async () => {
|
|
276
|
+
let loc = document.querySelector ( '#anchor' ) || false;
|
|
277
|
+
if ( loc ) await userEvent.click ( loc )
|
|
278
|
+
expect ( result ).to.be.equal ( 'A' )
|
|
279
|
+
short.changeContext ( 'general' )
|
|
280
|
+
resolve ( 'success' )
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
return res
|
|
284
|
+
}) // test click on anchor
|
|
285
|
+
|
|
286
|
+
}) // describe
|
|
287
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { expect, test } from 'vitest'
|
|
2
|
+
import { getByText } from '@testing-library/dom'
|
|
3
|
+
import HelloWorld from './HelloWorld.js'
|
|
4
|
+
|
|
5
|
+
test('renders name', () => {
|
|
6
|
+
const parent = HelloWorld({ name: 'Vitest' })
|
|
7
|
+
document.body.appendChild(parent)
|
|
8
|
+
|
|
9
|
+
const element = getByText(parent, 'Hello Vitest!')
|
|
10
|
+
expect(element).toBeInTheDocument()
|
|
11
|
+
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineWorkspace } from 'vitest/config'
|
|
2
|
+
|
|
3
|
+
export default defineWorkspace([
|
|
4
|
+
// If you want to keep running your existing tests in Node.js, uncomment the next line.
|
|
5
|
+
// 'vite.config.js',
|
|
6
|
+
{
|
|
7
|
+
extends: 'vite.config.js',
|
|
8
|
+
test: {
|
|
9
|
+
environment: 'browser',
|
|
10
|
+
browser: {
|
|
11
|
+
enabled: true,
|
|
12
|
+
name: 'chromium',
|
|
13
|
+
provider: 'playwright',
|
|
14
|
+
// https://vitest.dev/guide/browser/playwright
|
|
15
|
+
configs: [],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
])
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
// ***********************************************
|
|
2
|
-
// This example commands.js shows you how to
|
|
3
|
-
// create various custom commands and overwrite
|
|
4
|
-
// existing commands.
|
|
5
|
-
//
|
|
6
|
-
// For more comprehensive examples of custom
|
|
7
|
-
// commands please read more here:
|
|
8
|
-
// https://on.cypress.io/custom-commands
|
|
9
|
-
// ***********************************************
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// -- This is a parent command --
|
|
13
|
-
// Cypress.Commands.add('login', (email, password) => { ... })
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
// -- This is a child command --
|
|
17
|
-
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
// -- This is a dual command --
|
|
21
|
-
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
// -- This will overwrite an existing command --
|
|
25
|
-
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
7
|
-
<title>Components App</title>
|
|
8
|
-
<!-- Used by Next.js to inject CSS. -->
|
|
9
|
-
<div id="__next_css__DO_NOT_USE__"></div>
|
|
10
|
-
</head>
|
|
11
|
-
<body>
|
|
12
|
-
<div data-cy-root></div>
|
|
13
|
-
</body>
|
|
14
|
-
</html>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// ***********************************************************
|
|
2
|
-
// This example support/component.js is processed and
|
|
3
|
-
// loaded automatically before your test files.
|
|
4
|
-
//
|
|
5
|
-
// This is a great place to put global configuration and
|
|
6
|
-
// behavior that modifies Cypress.
|
|
7
|
-
//
|
|
8
|
-
// You can change the location of this file or turn off
|
|
9
|
-
// automatically serving support files with the
|
|
10
|
-
// 'supportFile' configuration option.
|
|
11
|
-
//
|
|
12
|
-
// You can read more here:
|
|
13
|
-
// https://on.cypress.io/configuration
|
|
14
|
-
// ***********************************************************
|
|
15
|
-
|
|
16
|
-
// Import commands.js using ES2015 syntax:
|
|
17
|
-
import './commands'
|
|
18
|
-
|
|
19
|
-
// Alternatively you can use CommonJS syntax:
|
|
20
|
-
// require('./commands')
|
|
21
|
-
|
|
22
|
-
import { mount } from 'cypress/react18'
|
|
23
|
-
|
|
24
|
-
Cypress.Commands.add('mount', mount)
|
|
25
|
-
|
|
26
|
-
// Example use:
|
|
27
|
-
// cy.mount(<MyComponent />)
|
package/cypress/support/e2e.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// ***********************************************************
|
|
2
|
-
// This example support/e2e.js is processed and
|
|
3
|
-
// loaded automatically before your test files.
|
|
4
|
-
//
|
|
5
|
-
// This is a great place to put global configuration and
|
|
6
|
-
// behavior that modifies Cypress.
|
|
7
|
-
//
|
|
8
|
-
// You can change the location of this file or turn off
|
|
9
|
-
// automatically serving support files with the
|
|
10
|
-
// 'supportFile' configuration option.
|
|
11
|
-
//
|
|
12
|
-
// You can read more here:
|
|
13
|
-
// https://on.cypress.io/configuration
|
|
14
|
-
// ***********************************************************
|
|
15
|
-
|
|
16
|
-
// Import commands.js using ES2015 syntax:
|
|
17
|
-
import './commands'
|
|
18
|
-
|
|
19
|
-
// Alternatively you can use CommonJS syntax:
|
|
20
|
-
// require('./commands')
|
package/cypress.config.js
DELETED
package/test/01-general.cy.js
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import Block from '../test-components/Block.jsx'
|
|
3
|
-
import '../test-components/style.css'
|
|
4
|
-
import {
|
|
5
|
-
pluginClick,
|
|
6
|
-
pluginKey
|
|
7
|
-
, shortcuts
|
|
8
|
-
} from '../src/main.js'
|
|
9
|
-
import { expect } from 'chai'
|
|
10
|
-
|
|
11
|
-
import askForPromise from 'ask-for-promise'
|
|
12
|
-
|
|
13
|
-
let
|
|
14
|
-
a = false
|
|
15
|
-
, b = false
|
|
16
|
-
;
|
|
17
|
-
|
|
18
|
-
const short = shortcuts ({onShortcut : ( shortcut, {context,note,type}) => console.log (shortcut, context, note, type) });
|
|
19
|
-
|
|
20
|
-
short.load ({
|
|
21
|
-
general : {
|
|
22
|
-
' key : shift+a': [ () => a = true ]
|
|
23
|
-
}
|
|
24
|
-
, extra : {
|
|
25
|
-
'key:shift+a,p,r,o,b,a,ctrl+m' : () => b = true
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
describe ( 'Shortcuts', () => {
|
|
32
|
-
|
|
33
|
-
beforeEach ( () => {
|
|
34
|
-
cy.mount ( Block () )
|
|
35
|
-
a = false, b = false
|
|
36
|
-
}) // beforeEach
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
it ( 'Shortcut if no plugin installed', done => {
|
|
41
|
-
short.changeContext ( 'general' )
|
|
42
|
-
let r = short.listShortcuts ('general')
|
|
43
|
-
expect ( r[0]).to.equal ( ' key : shift+a' ) // Shortcut name is the same as it was set
|
|
44
|
-
done ()
|
|
45
|
-
}) // it no plugin installed
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
it ( 'Key plugin, no context selected', done => {
|
|
50
|
-
short.enablePlugin ( pluginKey )
|
|
51
|
-
const r = short.listShortcuts ( 'general' )
|
|
52
|
-
expect ( r[0] ).to.equal ( 'KEY:A+SHIFT' ) // Shortcut name is recognized by plugin and is normalized
|
|
53
|
-
done ()
|
|
54
|
-
}) // it key plugin installed, no context selected
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
it ( 'Key plugin with context selected', done => {
|
|
59
|
-
short.enablePlugin ( pluginKey )
|
|
60
|
-
short.changeContext ( 'general' )
|
|
61
|
-
const r = short.listShortcuts ('general')
|
|
62
|
-
expect ( r[0] ).to.equal ( 'KEY:A+SHIFT' ) // Shortcut name is recognized by plugin and is normalized
|
|
63
|
-
cy.wait ( 1 )
|
|
64
|
-
.then ( () => done () )
|
|
65
|
-
}) // it key plugin installed with context selected
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
it ( 'Simple shortcut', done => {
|
|
70
|
-
short.enablePlugin ( pluginKey )
|
|
71
|
-
short.changeContext ( )
|
|
72
|
-
short.changeContext ( 'general' )
|
|
73
|
-
cy.get('body').type ( '{shift}a' )
|
|
74
|
-
cy.wait ( 1 ) // Default wait sequence timeout is 480 ms, but maxSequence is 1, so we don't need to wait for timeout
|
|
75
|
-
.then ( () => {
|
|
76
|
-
expect ( a ).to.be.true
|
|
77
|
-
done ()
|
|
78
|
-
})
|
|
79
|
-
}) // it simple shortcut
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
it ( 'Call sequence shortcut', done => {
|
|
84
|
-
b = false
|
|
85
|
-
short.enablePlugin ( pluginKey )
|
|
86
|
-
short.changeContext ( 'general' )
|
|
87
|
-
short.changeContext ( 'extra' )
|
|
88
|
-
|
|
89
|
-
cy.get('body')
|
|
90
|
-
.type ( '{shift}a' )
|
|
91
|
-
.type ( 'proba' )
|
|
92
|
-
.type ( '{ctrl}M' )
|
|
93
|
-
|
|
94
|
-
cy.wait ( 1 ) // Default wait sequence timeout is 480 ms, but maxSequence is 1, so we don't need to wait for timeout
|
|
95
|
-
.then ( () => {
|
|
96
|
-
expect ( b ).to.be.true
|
|
97
|
-
done ()
|
|
98
|
-
})
|
|
99
|
-
}) // it call sequence shortcut
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
it ( 'Single mouse click', done => {
|
|
104
|
-
expect ( a ).to.be.false
|
|
105
|
-
expect ( b ).to.be.false
|
|
106
|
-
short.enablePlugin ( pluginClick )
|
|
107
|
-
|
|
108
|
-
short.load ({ 'extra' : {
|
|
109
|
-
' cLIck : left - 1 ' : () => a = true // Check if spaces, letter case can break the shortcut recognition
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
short.changeContext ( 'extra' )
|
|
113
|
-
cy.get('#rspan').click ()
|
|
114
|
-
cy.wait ( 10 ) // Default wait mouse timeout is 320 ms, but maxClicks is 1, so we don't need to wait for timeout
|
|
115
|
-
.then ( () => {
|
|
116
|
-
expect ( a ).to.be.true
|
|
117
|
-
})
|
|
118
|
-
cy.wait ( 1 ) // ...but mouseIgnore still active, so we better wait to not interfere with next test
|
|
119
|
-
.then ( () => done() )
|
|
120
|
-
}) // it mouse click
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
it ( 'Double mouse click', done => {
|
|
125
|
-
expect ( a ).to.be.false
|
|
126
|
-
expect ( b ).to.be.false
|
|
127
|
-
|
|
128
|
-
short.enablePlugin ( pluginClick )
|
|
129
|
-
short.changeContext ( 'extra' )
|
|
130
|
-
|
|
131
|
-
short.load ({
|
|
132
|
-
'extra' : { // load will overwrite existing 'extra' context definition
|
|
133
|
-
'click: left-2' : () => a = true
|
|
134
|
-
}
|
|
135
|
-
}) // load will restart the selected context
|
|
136
|
-
|
|
137
|
-
cy.get('#rspan').click().click ().click () // Third click is ignored. Max clicks according definition is 2.
|
|
138
|
-
cy.wait ( 1 ) // Default wait mouse timeout is 320 ms
|
|
139
|
-
.then ( () => {
|
|
140
|
-
expect ( a ).to.be.true
|
|
141
|
-
done ()
|
|
142
|
-
})
|
|
143
|
-
}) // it double mouse click
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
it ( 'Dependencies on shortcuts', done => {
|
|
148
|
-
const task = askForPromise ();
|
|
149
|
-
expect ( a ).to.be.false
|
|
150
|
-
expect ( b ).to.be.false
|
|
151
|
-
|
|
152
|
-
short.enablePlugin ( pluginClick )
|
|
153
|
-
short.setDependencies ({ task })
|
|
154
|
-
|
|
155
|
-
short.load ({
|
|
156
|
-
'extra' : { // load will overwrite existing 'extra' context definition
|
|
157
|
-
'click: left-1' : ({dependencies}) => {
|
|
158
|
-
const { task } = dependencies;
|
|
159
|
-
expect ( task ).to.have.property ( 'done' )
|
|
160
|
-
expect ( task ).to.have.property ( 'promise' )
|
|
161
|
-
a = true
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}) // load will restart the selected context
|
|
165
|
-
|
|
166
|
-
short.changeContext ( 'extra' )
|
|
167
|
-
cy.get('#rspan').click ()
|
|
168
|
-
cy.wait ( 350 ) // Default wait mouse timeout is 320 ms
|
|
169
|
-
.then ( () => {
|
|
170
|
-
expect ( a ).to.be.true
|
|
171
|
-
done ()
|
|
172
|
-
})
|
|
173
|
-
}) // it dependencies on shortcuts
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
it ( 'Emit custom event', done => {
|
|
178
|
-
let result = null;
|
|
179
|
-
short.changeContext ()
|
|
180
|
-
short.enablePlugin ( pluginClick )
|
|
181
|
-
const myAllContext = {
|
|
182
|
-
myAll: {
|
|
183
|
-
'click : leff-1' : () => console.log ( 'nothing' )
|
|
184
|
-
, 'yo' : ({msg}) => result = msg
|
|
185
|
-
}}
|
|
186
|
-
short.load ( myAllContext )
|
|
187
|
-
short.changeContext ( 'myAll' )
|
|
188
|
-
short.emit ( 'yo', { context: short.getContext(), note: 'tt', type:'custom', msg:'hello' })
|
|
189
|
-
expect ( result ).to.be.equal ( 'hello' )
|
|
190
|
-
short.changeContext ( 'general' )
|
|
191
|
-
short.unload ( 'myAll' )
|
|
192
|
-
done ()
|
|
193
|
-
}) // it emit custom event
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
it ( 'List shortcuts', () => {
|
|
198
|
-
let general = short.listShortcuts ('general');
|
|
199
|
-
expect ( general ).to.be.an('array')
|
|
200
|
-
expect ( general ).to.have.lengthOf ( 1 )
|
|
201
|
-
expect ( general[0] ).to.be.equal ( 'KEY:A+SHIFT' )
|
|
202
|
-
|
|
203
|
-
let fail = short.listShortcuts ('somethingNotExisting');
|
|
204
|
-
expect ( fail ).to.be.null
|
|
205
|
-
|
|
206
|
-
let all = short.listShortcuts ();
|
|
207
|
-
expect ( all ).to.be.an('array')
|
|
208
|
-
|
|
209
|
-
expect ( all ).to.have.lengthOf ( 2 )
|
|
210
|
-
expect ( all[0] ).to.have.property ( 'context' )
|
|
211
|
-
expect ( all[0] ).to.have.property ( 'shortcuts' )
|
|
212
|
-
expect ( all[0].shortcuts ).to.be.an('array')
|
|
213
|
-
expect ( all[0].shortcuts ).to.have.lengthOf ( 1 )
|
|
214
|
-
expect ( all[0].shortcuts[0] ).to.be.equal ( 'KEY:A+SHIFT' )
|
|
215
|
-
expect ( all[0].context ).to.be.equal ( 'general' )
|
|
216
|
-
}) // it list shortcuts
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
it ( 'Click on anchor', done => {
|
|
221
|
-
// Click on anchor that don't have click-data attribute.
|
|
222
|
-
let result = 'none';
|
|
223
|
-
short.load ({ 'extra' : {
|
|
224
|
-
'click: 1 - left' : ({target, context, event }) => { // Order of button name and number of click is not important
|
|
225
|
-
event.preventDefault ()
|
|
226
|
-
expect ( context ).to.be.equal ( 'extra' )
|
|
227
|
-
expect ( target.nodeName ).to.be.equal ( 'A' )
|
|
228
|
-
result = target.nodeName
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
})
|
|
232
|
-
short.changeContext ( 'extra' )
|
|
233
|
-
cy.get ( '#anchor' ).click ()
|
|
234
|
-
cy.wait ( 3 ) // Consider mouse click has some latency
|
|
235
|
-
// According Cypress documentation:
|
|
236
|
-
// It is unsafe to chain further commands that rely on the subject after .click().
|
|
237
|
-
// source docs: https://docs.cypress.io/api/commands/click
|
|
238
|
-
.then ( () => {
|
|
239
|
-
short.changeContext ( 'general' )
|
|
240
|
-
expect ( result ).to.be.equal ( 'A' )
|
|
241
|
-
done ()
|
|
242
|
-
})
|
|
243
|
-
}) // it click on anchor
|
|
244
|
-
}) // describe
|
|
245
|
-
|
|
246
|
-
|