@peter.naydenov/shortcuts 3.3.1 → 3.4.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.
@@ -1,37 +1,51 @@
1
- import { beforeEach, describe, it, test } from 'vitest'
1
+ import { beforeEach, afterEach, describe, it, expect } from 'vitest'
2
2
  import { userEvent } from '@vitest/browser/context'
3
+ import {
4
+ getByLabelText,
5
+ getByText,
6
+ getByTestId,
7
+ queryByTestId,
8
+ // Tip: all queries are also exposed on an object
9
+ // called "queries" which you could import here as well
10
+ waitFor
11
+ } from '@testing-library/dom'
12
+
3
13
 
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
14
 
15
+ import '../test-helpers/style.css'
16
+ import Block from '../test-helpers/Block.jsx'
17
+ import VisaulController from '@peter.naydenov/visual-controller-for-react'
18
+ import wait from '../test-helpers/wait.js'
8
19
  import {
9
20
  pluginClick,
10
21
  pluginKey
11
22
  , pluginForm
12
23
  , shortcuts
13
24
  } from '../src/main.js'
14
- import { expect } from 'chai'
25
+
15
26
 
16
27
  import askForPromise from 'ask-for-promise'
17
28
 
18
29
  const html = new VisaulController ();
19
-
20
30
  let
21
31
  a = false
22
32
  , b = false
33
+ , c = null
23
34
  ;
24
-
25
-
26
- function wait (ms) {
27
- return new Promise((resolve) => setTimeout(resolve, ms));
28
- }
29
-
30
- const short = shortcuts ({onShortcut : ( shortcut, {context,note,type}) => console.log (shortcut, context, note, type) });
31
-
32
- short.load ({
35
+ const contextDefinition = {
33
36
  general : {
34
- ' key : shift+a': [ () => a = true ]
37
+ ' key : shift+a': [
38
+ () => a = true,
39
+ () => c = 'triggered'
40
+ ]
41
+ }
42
+ , touch : {
43
+ // Single click with left button
44
+ 'click: left-1': () => b = true,
45
+ // Double click with left button
46
+ 'click: left-2': () => b = true,
47
+ // Single click with right button
48
+ 'click: right-1': () => b = true
35
49
  }
36
50
  , extra : {
37
51
  'key : p,r,o,b,a': () => b = true
@@ -47,253 +61,87 @@ short.load ({
47
61
  }
48
62
  ]
49
63
  }
50
- })
51
-
52
- beforeEach ( () => {
53
- let container = document.createElement ( 'div' )
54
- container.id = 'app'
55
- document.body.appendChild ( container )
56
- html.publish ( Block, {}, 'app' )
57
- a = false, b = false
58
- }) // beforeEach
64
+ }
59
65
 
60
66
 
67
+
68
+ let short = shortcuts ();
61
69
 
62
70
 
63
71
 
64
72
  describe ( "Shortcuts", () => {
65
73
 
74
+ beforeEach ( async () => {
75
+ short.load ( contextDefinition )
76
+ let container = document.createElement ( 'div' )
77
+ container.id = 'app'
78
+ document.body.appendChild ( container )
79
+ await html.publish ( Block, {}, 'app' )
80
+ a = false, b = false
81
+ }) // beforeEach
66
82
 
67
83
 
68
- test ( 'Shortcut if no plugin installed', () => {
69
- let res = new Promise ( (resolve,reject) => {
70
- short.changeContext ( 'general' )
71
- let r = short.listShortcuts ('general')
72
- expect ( r[0]).to.equal ( ' key : shift+a' ) // Shortcut name is the same as it was set
73
- resolve ('success')
74
- })
75
- return res
76
- }) // test no plugin installed
77
-
78
-
79
-
80
- test ( 'Key plugin, no context selected', () => {
81
- const res = new Promise ( ( resolve ) => {
82
- short.enablePlugin ( pluginKey )
83
- const r = short.listShortcuts ( 'general' )
84
- expect ( r[0] ).to.equal ( 'KEY:A+SHIFT' ) // Shortcut name is recognized by plugin and is normalized
85
- resolve ('success')
86
- })
87
- return res
88
- }) // test key plugin installed, no context selected
89
-
90
-
91
-
92
- test ( 'Key plugin with context selected', () => {
93
- const res = new Promise ( (resolve) => {
94
- short.enablePlugin ( pluginKey )
95
- short.changeContext ( 'general' )
96
- const r = short.listShortcuts ('general')
97
- expect ( r[0] ).to.equal ( 'KEY:A+SHIFT' ) // Shortcut name is recognized by plugin and is normalized
98
- resolve ( 'success' )
99
- })
100
- return res
101
- }) // test key plugin installed with context selected
102
-
103
-
104
-
105
- test ( 'Simple shortcut', () => {
106
- const res = new Promise ( (resolve) => {
107
- short.enablePlugin ( pluginKey )
108
- short.changeContext ()
109
- short.changeContext ( 'general' )
110
- userEvent.keyboard ( '{Shift>}a</Shift>' )
111
- expect ( a ).to.be.false
112
- wait ( 1000 )
113
- .then ( () => { // Default wait sequence timeout is 480 ms, but maxSequence is 1, so we don't need to wait for timeout
114
- expect ( a ).to.be.true
115
- resolve ( 'success' )
116
- })
117
- })
118
- return res
119
- }) // test simple shortcut
120
84
 
85
+ afterEach ( async () => {
86
+ short.reset ()
87
+ a = false, b = false, c = null;
88
+ }) // afterEach
121
89
 
122
90
 
123
- test ( 'Call sequence shortcut', async () => {
124
- let res = new Promise ( async (resolve) => {
125
- b = false
126
- short.enablePlugin ( pluginKey )
127
- short.changeContext ()
128
- short.changeContext ( 'extra' )
129
- await userEvent.keyboard ( 'proba' )
130
- expect ( b ).to.be.true
131
- resolve ( 'success' )
132
- })
133
- return res
134
- }) // test call sequence shortcut
135
-
136
-
137
-
138
- test ( 'Single mouse click', done => {
139
- const res = new Promise ( async (resolve) => {
140
- expect ( a ).to.be.false
141
- expect ( b ).to.be.false
142
- short.enablePlugin ( pluginClick )
143
-
144
- short.load ({ 'extra' : {
145
- ' cLIck : left - 1 ' : () => a = true // Check if spaces, letter case can break the shortcut recognition
146
- }
147
- })
148
- short.changeContext ()
149
- short.changeContext ( 'extra' )
150
- wait ( 100 )
151
- .then ( async () => {
152
- // Default wait mouse timeout is 320 ms, but maxClicks is 1, so we don't need to wait for timeout
153
- let loc = document.querySelector('#rspan') || false
154
- if ( loc ) await userEvent.click ( loc )
155
- expect ( a ).to.be.true
156
- resolve ( 'success' )
157
- })
158
-
159
-
160
- })
161
- return res
162
- }) // test single mouse click
163
-
164
-
165
-
166
- test ( 'Double mouse click', () => {
167
- let res = new Promise ( async (resolve) => {
168
- expect ( a ).to.be.false
169
- expect ( b ).to.be.false
170
-
171
- short.enablePlugin ( pluginClick )
172
- short.changeContext ( 'extra' )
173
- short.load ({ // load will restart the selected context
174
- 'extra' : { // load will overwrite existing 'extra' context definition
175
- 'click: left-2' : () => a = true
176
- }
177
- })
178
- wait ( 350 )
179
- .then ( async () => { // Default wait mouse timeout is 320 ms
180
- let loc = document.querySelector ( '#rspan' ) || false
181
- // Third click is ignored. Max clicks according definition is 2.
182
- if ( loc ) await userEvent.tripleClick ( loc )
183
- expect ( a ).to.be.true
184
- resolve ( 'success' )
185
- })
186
- })
187
- return res
188
- }) // test double mouse click
189
-
190
-
191
-
192
- test ( 'Dependencies on shortcuts', () => {
193
- const res = new Promise ( async (resolve) => {
194
- const task = askForPromise ();
195
- expect ( a ).to.be.false
196
- expect ( b ).to.be.false
197
-
198
- short.enablePlugin ( pluginClick )
199
- short.setDependencies ({ task })
200
-
201
- short.load ({
202
- 'extra' : { // load will overwrite existing 'extra' context definition
203
- 'click: left-1' : ({dependencies}) => {
204
- const { task } = dependencies;
205
- expect ( task ).to.have.property ( 'done' )
206
- expect ( task ).to.have.property ( 'promise' )
207
- a = true
208
- }
209
- }
210
- }) // load will restart the selected context
211
- short.changeContext ( 'extra' )
212
- wait ( 350 ) // Default wait mouse timeout is 320 ms
213
- .then ( async () => {
214
- let loc = document.querySelector ( '#rspan' ) || false
215
- if ( loc ) await userEvent.click ( loc )
216
- resolve ( 'success' )
217
- })
218
- }) // res promise
219
- return res
220
- }) // test dependencies on shortcuts
221
-
222
-
223
-
224
- test ( 'Emit custom event', () => {
225
- const res = new Promise ( async (resolve) => {
226
- let result = null;
227
- short.changeContext ()
228
- short.enablePlugin ( pluginClick )
229
- const myAllContext = {
230
- myAll: {
231
- 'click : leff-1' : () => console.log ( 'nothing' )
232
- , 'yo' : ({msg}) => result = msg
233
- }}
234
- short.load ( myAllContext )
235
- short.changeContext ( 'myAll' )
236
- short.emit ( 'yo', { context: short.getContext(), note: 'tt', type:'custom', msg:'hello' })
237
- expect ( result ).to.be.equal ( 'hello' )
238
- short.changeContext ( 'general' )
239
- short.unload ( 'myAll' )
240
- resolve ( 'success' )
241
- })
242
- return res
243
- }) // test emit custom event
244
-
245
-
246
-
247
- test ( 'List shortcuts', () => {
248
- short.enablePlugin ( pluginKey )
249
- let general = short.listShortcuts ('general');
250
- expect ( general ).to.be.an ( 'array' )
251
- expect ( general ).to.have.lengthOf ( 1 )
252
- expect ( general[0] ).to.be.equal ( 'KEY:A+SHIFT' )
253
91
 
254
- let fail = short.listShortcuts ( 'somethingNotExisting' );
255
- expect ( fail ).to.be.null
256
-
257
- let all = short.listShortcuts ();
258
- expect ( all ).to.be.an ( 'array' )
92
+ it ( 'Emit custom event', () => {
93
+ // TODO: Check arguments for the custom event handlers
94
+ let result = null;
95
+ short.enablePlugin ( pluginClick )
96
+ const myAllContext = {
97
+ myAll: {
98
+ 'click : leff-1' : () => console.log ( 'nothing' )
99
+ , 'yo' : ({msg}) => result = msg
100
+ }}
101
+ short.load ( myAllContext )
102
+ short.changeContext ( 'myAll' )
103
+ short.emit ( 'yo', { context: short.getContext(), note: 'tt', type:'custom', msg:'hello' })
104
+ expect ( result ).to.be.equal ( 'hello' )
105
+ short.changeContext ( 'general' )
106
+ short.unload ( 'myAll' )
107
+ }) // it emit custom event
108
+
109
+
110
+
111
+ it ( 'List shortcuts', () => {
112
+ short.enablePlugin ( pluginKey )
113
+
114
+ let general = short.listShortcuts ('general');
115
+ expect ( general ).to.be.an ( 'array' )
116
+ expect ( general ).to.have.lengthOf ( 1 )
117
+ expect ( general[0] ).to.be.equal ( 'KEY:A+SHIFT' )
118
+
119
+ let fail = short.listShortcuts ( 'somethingNotExisting' );
120
+ expect ( fail ).to.be.null
121
+
122
+ let all = short.listShortcuts ();
123
+ expect ( all ).to.be.an ( 'array' )
124
+
125
+ expect ( all ).to.have.lengthOf ( 4 )
126
+ // Property 'context' is a context name - string
127
+ expect ( all[0] ).to.have.property ( 'context' )
128
+ expect ( all[0] ).to.have.property ( 'shortcuts' )
129
+ expect ( all[0].shortcuts ).to.be.an ( 'array' )
130
+ expect ( all[0].shortcuts ).to.have.lengthOf ( 1 )
131
+ expect ( all[0].shortcuts[0] ).to.be.equal ( 'KEY:A+SHIFT' )
132
+ expect ( all[0].context ).to.be.equal ( 'general' )
133
+ }) // it list shortcuts
134
+
135
+
136
+
137
+ it ( 'Reset', () => {
138
+ short.enablePlugin ( pluginKey )
139
+ short.reset ()
140
+ expect ( short.listShortcuts () ).to.have.lengthOf ( 0 )
141
+ expect ( short.listShortcuts () ).to.have.lengthOf ( 0 )
142
+ expect ( short.getContext () ).to.be.null
143
+ }) // it Reset
259
144
 
260
- expect ( all ).to.have.lengthOf ( 3 )
261
- expect ( all[0] ).to.have.property ( 'context' )
262
- expect ( all[0] ).to.have.property ( 'shortcuts' )
263
- expect ( all[0].shortcuts ).to.be.an('array')
264
- expect ( all[0].shortcuts ).to.have.lengthOf ( 1 )
265
- expect ( all[0].shortcuts[0] ).to.be.equal ( 'KEY:A+SHIFT' )
266
- expect ( all[0].context ).to.be.equal ( 'general' )
267
- }) // test list shortcuts
268
-
269
-
270
-
271
- test ( 'Click on anchor', () => {
272
- const res = new Promise ( async (resolve) => {
273
- // Click on anchor that don't have click-data attribute.
274
- let result = 'none';
275
- short.enablePlugin ( pluginClick )
276
- short.load ({ 'extra' : {
277
- 'click: 1 - left' : ({target, context, event }) => { // Order of button name and number of click is not important
278
- event.preventDefault ()
279
- expect ( context ).to.be.equal ( 'extra' )
280
- expect ( target.nodeName ).to.be.equal ( 'A' )
281
- result = target.nodeName
282
- }
283
- }
284
- })
285
- short.changeContext ( 'extra' )
286
- wait ( 10 )
287
- .then ( async () => {
288
- let loc = document.querySelector ( '#anchor' ) || false;
289
- if ( loc ) await userEvent.click ( loc )
290
- expect ( result ).to.be.equal ( 'A' )
291
- short.changeContext ( 'general' )
292
- resolve ( 'success' )
293
- })
294
- })
295
- return res
296
- }) // test click on anchor
297
145
 
298
146
  }) // describe
299
147
 
@@ -0,0 +1,174 @@
1
+ import { beforeEach, afterEach, describe, it, expect } from 'vitest'
2
+ import { userEvent } from '@vitest/browser/context'
3
+ import {
4
+ getByLabelText,
5
+ getByText,
6
+ getByTestId,
7
+ queryByTestId,
8
+ // Tip: all queries are also exposed on an object
9
+ // called "queries" which you could import here as well
10
+ waitFor
11
+ } from '@testing-library/dom'
12
+
13
+
14
+
15
+ import '../test-helpers/style.css'
16
+ import Block from '../test-helpers/Block.jsx'
17
+ import VisaulController from '@peter.naydenov/visual-controller-for-react'
18
+ import wait from '../test-helpers/wait.js'
19
+ import {
20
+ shortcuts
21
+ , pluginKey
22
+ , pluginClick
23
+ , pluginForm
24
+ } from '../src/main.js'
25
+
26
+
27
+
28
+ const html = new VisaulController ();
29
+ let
30
+ a = false
31
+ , b = false
32
+ , c = null
33
+ ;
34
+
35
+ const contextDefinition = {
36
+ general : {
37
+ ' key : shift+a': [
38
+ () => a = true,
39
+ () => c = 'triggered'
40
+ ]
41
+ }
42
+ , touch : {
43
+ // Single click with left button
44
+ 'click: left-1': () => b = true,
45
+ // Double click with left button
46
+ 'click: left-2': () => b = true,
47
+ // Single click with right button
48
+ 'click: right-1': () => b = true
49
+ }
50
+ , extra : {
51
+ 'key : p,r,o,b,a': () => b = true
52
+ }
53
+ , extend : {
54
+ 'form : watch' : () => 'input'
55
+ , 'form : define' : () => 'input'
56
+ , 'form : action' : () => [
57
+ {
58
+ fn : (e) => console.log ( e.target )
59
+ , type : 'input'
60
+ , mode : 'in'
61
+ }
62
+ ]
63
+ }
64
+ }
65
+
66
+ let short = shortcuts ();
67
+
68
+
69
+
70
+
71
+
72
+ describe ( 'Key plugin', () => {
73
+
74
+ beforeEach ( async () => {
75
+ short.load ( contextDefinition )
76
+ let container = document.createElement ( 'div' )
77
+ container.id = 'app'
78
+ document.body.appendChild ( container )
79
+ await html.publish ( Block, {}, 'app' )
80
+ a = false, b = false
81
+ }) // beforeEach
82
+
83
+
84
+
85
+ afterEach ( async () => {
86
+ short.reset ()
87
+ a = false, b = false, c = null;
88
+ }) // afterEach
89
+
90
+
91
+
92
+ it ( 'No "key" plugin installed', () => {
93
+ let r = short.listShortcuts ('general');
94
+ // Shortcut name is the same as it was set
95
+ expect ( r[0]).to.equal ( ' key : shift+a' )
96
+ }) // it no 'key' plugin installed
97
+
98
+
99
+
100
+ it ( 'Key plugin installed', () => {
101
+ short.enablePlugin ( pluginKey )
102
+ const r = short.listShortcuts ( 'general' )
103
+ // Shortcut name is recognized by plugin and is normalized
104
+ expect ( r[0] ).to.equal ( 'KEY:A+SHIFT' )
105
+ }) // it key plugin installed
106
+
107
+
108
+
109
+ it ( 'Execute a key shortcut: shift+a', async () => {
110
+ expect ( a ).to.equal ( false )
111
+ // Enable key plugin, normalize shortcuts related to the plugin
112
+ short.enablePlugin ( pluginKey )
113
+ short.changeContext ( 'general' )
114
+ await userEvent.keyboard ( '{Shift>}A{/Shift}' ) // Write 'a' with shift
115
+ await wait ( 12 )
116
+ await waitFor ( () => {
117
+ expect ( a ).to.equal ( true )
118
+ expect ( c ).to.equal ( 'triggered' )
119
+ }, { timeout: 1000, interval: 12 })
120
+ }) // it execute a key shortcut
121
+
122
+
123
+
124
+ it ( 'Key sequence', async () => {
125
+ // enable key plugin and normalize shortcuts related to the plugin 'key'
126
+ short.enablePlugin ( pluginKey )
127
+ short.changeContext ( 'extra' )
128
+ // Execute key sequence: 'p,r,o,b,a'
129
+ await userEvent.keyboard ( 'proba' )
130
+ await wait ( 12 )
131
+ await waitFor ( () => {
132
+ expect ( b ).to.equal ( true )
133
+ }, { timeout: 1000, interval: 12 })
134
+ }) // it key sequence
135
+
136
+
137
+
138
+ it ( 'Mute key plugin', async () => {
139
+ short.enablePlugin ( pluginKey )
140
+ const result = [];
141
+ let i = 0;
142
+ result.push ( 'init' )
143
+
144
+ short.setDependencies ({ result })
145
+ short.load ({
146
+ 'local': {
147
+ 'key: g,t,i ' : ({dependencies}) => {
148
+ let { result } = dependencies;
149
+ result.push ( i++ )
150
+ }
151
+ }
152
+ })
153
+
154
+ short.changeContext ( 'local' )
155
+ await userEvent.keyboard ( 'gti' )
156
+ await waitFor ( () => {
157
+ // We checking if the shortcut works
158
+ expect ( result ).to.have.lengthOf ( 2 )
159
+ expect ( i ).to.equal ( 1 )
160
+ }, { timeout: 1000, interval: 12 })
161
+
162
+ short.mutePlugin ( 'key' )
163
+ await userEvent.keyboard ( 'gti' )
164
+ await waitFor ( () => {
165
+ // Plugin is muted, so we don't expect any changes
166
+ expect ( result ).to.have.lengthOf ( 2 )
167
+ expect ( i ).to.equal ( 1 )
168
+ }, { timeout: 1000, interval: 12 })
169
+ }) // it mute key plugin
170
+
171
+
172
+
173
+
174
+ })