@peter.naydenov/shortcuts 3.1.3 → 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 CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
 
4
4
 
5
+ ### 3.1.4 ( 2025-05-3)
6
+ - [x] Dependency update. @peter.naydenov/notice - v.2.4.1
7
+
8
+
5
9
  ### 3.1.3 ( 2025-01-12)
6
10
  - [x] Dependency update. @peter.naydenov/notice - v.2.4.0
7
11
 
package/index.html CHANGED
@@ -22,10 +22,10 @@
22
22
  </head>
23
23
  <body>
24
24
  <script type="module">
25
- import sc from '/src/main.js'
25
+ import { shortcuts, pluginKey, pluginClick } from '/src/main.js'
26
26
 
27
27
  const options = {
28
- onShortcut ({ shortcut, context, note }) {
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 = sc ( options );
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
- , 'mouse-click-left-2' : () => console.log ( 'Mouse left click 2' )
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
- console.log('END')
53
- end ()
57
+ end ()
58
+ console.log('END')
54
59
  }
55
60
  else {
56
- console.log('WAIT')
57
- wait ()
61
+ console.log('WAIT')
62
+ wait ()
58
63
  }
59
64
  },
60
- () => console.log ( 'W' )
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.3",
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": "cypress open --component --browser chrome 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.4.0"
29
+ "@peter.naydenov/notice": "^2.4.1"
30
30
  },
31
31
  "devDependencies": {
32
- "@rollup/plugin-commonjs": "^28.0.2",
33
- "@rollup/plugin-node-resolve": "^16.0.0",
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.3.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.1.2",
38
- "cypress": "^13.17.0",
39
- "mocha": "^11.0.1",
40
- "react": "^19.0.0",
41
- "react-dom": "^19.0.0",
42
- "vite": "^6.0.7"
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 }
@@ -61,7 +61,7 @@ function _listenDOM ( dependencies, state ) {
61
61
 
62
62
  if ( sequence ) {
63
63
  const signal = `KEY:${res.join(',')}`
64
- ev.emit ( signal, data )
64
+ ev.emit ( signal, data )
65
65
  // Reset:
66
66
  r = []
67
67
  keyTimer = null
@@ -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,9 @@
1
+ export default function HelloWorld({ name }) {
2
+ const parent = document.createElement('div')
3
+
4
+ const h1 = document.createElement('h1')
5
+ h1.textContent = 'Hello ' + name + '!'
6
+ parent.appendChild(h1)
7
+
8
+ return parent
9
+ }
@@ -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,5 +0,0 @@
1
- {
2
- "name": "Using fixtures to represent data",
3
- "email": "hello@cypress.io",
4
- "body": "Fixtures are a great way to mock data for responses to routes"
5
- }
@@ -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 />)
@@ -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
@@ -1,10 +0,0 @@
1
- import { defineConfig } from "cypress";
2
-
3
- export default defineConfig({
4
- component: {
5
- devServer: {
6
- framework: "react",
7
- bundler: "vite",
8
- },
9
- },
10
- });
@@ -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
-