kokopu-react 1.5.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/lib/Movetext.js +17 -5
  2. package/doc_src/demo/PageMovetextInteraction.js +10 -6
  3. package/graphic_test_app/16_movetext_interaction.js +2 -2
  4. package/package.json +5 -5
  5. package/scripts/test_graphic/docker-compose.yml +1 -1
  6. package/src/Chessboard.js +2 -2
  7. package/src/Movetext.js +19 -8
  8. package/test/8_movetext_interaction.js +12 -8
  9. package/test/references/01_marker_icons/0.png +0 -0
  10. package/test/references/01_marker_icons/1.png +0 -0
  11. package/test/references/01_marker_icons/10.png +0 -0
  12. package/test/references/01_marker_icons/2.png +0 -0
  13. package/test/references/01_marker_icons/3.png +0 -0
  14. package/test/references/01_marker_icons/4.png +0 -0
  15. package/test/references/01_marker_icons/5.png +0 -0
  16. package/test/references/01_marker_icons/6.png +0 -0
  17. package/test/references/01_marker_icons/7.png +0 -0
  18. package/test/references/01_marker_icons/8.png +0 -0
  19. package/test/references/01_marker_icons/9.png +0 -0
  20. package/test/references/02_chessboard_simple/0.png +0 -0
  21. package/test/references/02_chessboard_simple/1.png +0 -0
  22. package/test/references/02_chessboard_simple/2.png +0 -0
  23. package/test/references/02_chessboard_simple/3.png +0 -0
  24. package/test/references/02_chessboard_simple/4.png +0 -0
  25. package/test/references/02_chessboard_simple/5.png +0 -0
  26. package/test/references/03_chessboard_flipped/0.png +0 -0
  27. package/test/references/03_chessboard_flipped/1.png +0 -0
  28. package/test/references/03_chessboard_flipped/2.png +0 -0
  29. package/test/references/03_chessboard_flipped/3.png +0 -0
  30. package/test/references/03_chessboard_flipped/4.png +0 -0
  31. package/test/references/04_chessboard_annotations/0.png +0 -0
  32. package/test/references/04_chessboard_annotations/1.png +0 -0
  33. package/test/references/04_chessboard_annotations/2.png +0 -0
  34. package/test/references/04_chessboard_annotations/3.png +0 -0
  35. package/test/references/04_chessboard_annotations/4.png +0 -0
  36. package/test/references/04_chessboard_annotations/5.png +0 -0
  37. package/test/references/05_chessboard_move/0.png +0 -0
  38. package/test/references/05_chessboard_move/1.png +0 -0
  39. package/test/references/05_chessboard_move/2.png +0 -0
  40. package/test/references/05_chessboard_move/3.png +0 -0
  41. package/test/references/05_chessboard_move/4.png +0 -0
  42. package/test/references/05_chessboard_move/5.png +0 -0
  43. package/test/references/05_chessboard_move/6.png +0 -0
  44. package/test/references/05_chessboard_move/7.png +0 -0
  45. package/test/references/05_chessboard_move/8.png +0 -0
  46. package/test/references/06_chessboard_theme/0.png +0 -0
  47. package/test/references/06_chessboard_theme/1.png +0 -0
  48. package/test/references/06_chessboard_theme/2.png +0 -0
  49. package/test/references/06_chessboard_theme/3.png +0 -0
  50. package/test/references/06_chessboard_theme/4.png +0 -0
  51. package/test/references/06_chessboard_theme/5.png +0 -0
  52. package/test/references/06_chessboard_theme/6.png +0 -0
  53. package/test/references/06_chessboard_theme/7.png +0 -0
  54. package/test/references/06_chessboard_theme/8.png +0 -0
  55. package/test/references/08_chessboard_move_pieces/after_move.png +0 -0
  56. package/test/references/08_chessboard_move_pieces/empty_square.png +0 -0
  57. package/test/references/08_chessboard_move_pieces/null_vector.png +0 -0
  58. package/test/references/08_chessboard_move_pieces/out_of_board.png +0 -0
  59. package/test/references/08_chessboard_move_pieces/over_arrow_marker.png +0 -0
  60. package/test/references/08_chessboard_move_pieces/over_empty.png +0 -0
  61. package/test/references/08_chessboard_move_pieces/over_non_empty_1.png +0 -0
  62. package/test/references/08_chessboard_move_pieces/over_non_empty_2.png +0 -0
  63. package/test/references/08_chessboard_move_pieces/over_square_marker.png +0 -0
  64. package/test/references/08_chessboard_move_pieces/over_text_marker.png +0 -0
  65. package/test/references/09_chessboard_edit_arrows/base_1.png +0 -0
  66. package/test/references/09_chessboard_edit_arrows/base_2.png +0 -0
  67. package/test/references/09_chessboard_edit_arrows/edit_color_not_set.png +0 -0
  68. package/test/references/09_chessboard_edit_arrows/null_vector.png +0 -0
  69. package/test/references/09_chessboard_edit_arrows/out_of_board.png +0 -0
  70. package/test/references/09_chessboard_edit_arrows/over_arrow_marker.png +0 -0
  71. package/test/references/09_chessboard_edit_arrows/over_square_marker.png +0 -0
  72. package/test/references/10_chessboard_play_moves/castling_move.png +0 -0
  73. package/test/references/10_chessboard_play_moves/chess960_ambiguous_king_move.png +0 -0
  74. package/test/references/10_chessboard_play_moves/chess960_castling_move_1.png +0 -0
  75. package/test/references/10_chessboard_play_moves/chess960_castling_move_2.png +0 -0
  76. package/test/references/10_chessboard_play_moves/chess960_non_kxr_castling.png +0 -0
  77. package/test/references/10_chessboard_play_moves/illegal_move.png +0 -0
  78. package/test/references/10_chessboard_play_moves/illegal_position.png +0 -0
  79. package/test/references/10_chessboard_play_moves/null_vector.png +0 -0
  80. package/test/references/10_chessboard_play_moves/out_of_board.png +0 -0
  81. package/test/references/10_chessboard_play_moves/regular_move_1.png +0 -0
  82. package/test/references/10_chessboard_play_moves/regular_move_2.png +0 -0
  83. package/test/references/10_chessboard_play_moves/wrong_color.png +0 -0
  84. package/test/references/11_chessboard_play_promotions/antichess_promotion.png +0 -0
  85. package/test/references/11_chessboard_play_promotions/cancel_promotion.png +0 -0
  86. package/test/references/11_chessboard_play_promotions/regular_promotion_1.png +0 -0
  87. package/test/references/11_chessboard_play_promotions/regular_promotion_2.png +0 -0
  88. package/test/references/12_movetext_simple/2.png +0 -0
  89. package/test/references/12_movetext_simple/3.png +0 -0
  90. package/test/references/15_movetext_options/2.png +0 -0
@@ -94,10 +94,9 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
94
94
  });
95
95
  }
96
96
 
97
- var game = info.game;
98
97
  return /*#__PURE__*/_react["default"].createElement("div", {
99
98
  className: "kokopu-movetext"
100
- }, this.renderHeaders(game), this.renderBody(game), this.renderFocusField());
99
+ }, this.renderHeaders(info.game), this.renderBody(info.game), this.renderFocusField());
101
100
  }
102
101
  }, {
103
102
  key: "renderHeaders",
@@ -530,12 +529,15 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
530
529
 
531
530
  var game = parseGame(this.props.game, this.props.gameIndex).game;
532
531
  var nodeId = false;
532
+ var evtOrigin = '';
533
533
 
534
534
  if (this.props.selection === 'start') {
535
535
  if (evt.key === 'ArrowRight') {
536
536
  nodeId = getNextNodeId(game.mainVariation(), true);
537
+ evtOrigin = 'key-next';
537
538
  } else if (evt.key === 'End') {
538
539
  nodeId = getLastNodeId(game.mainVariation(), true);
540
+ evtOrigin = 'key-last';
539
541
  }
540
542
  } else {
541
543
  var currentNode = game.findById(this.props.selection);
@@ -546,17 +548,21 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
546
548
 
547
549
  if (evt.key === 'Home') {
548
550
  nodeId = 'start';
551
+ evtOrigin = 'key-first';
549
552
  } else if (evt.key === 'ArrowLeft') {
550
553
  nodeId = getPreviousNodeId(currentNode);
554
+ evtOrigin = 'key-previous';
551
555
  } else if (evt.key === 'ArrowRight') {
552
556
  nodeId = getNextNodeId(currentNode, false);
557
+ evtOrigin = 'key-next';
553
558
  } else if (evt.key === 'End') {
554
559
  nodeId = getLastNodeId(currentNode, false);
560
+ evtOrigin = 'key-last';
555
561
  }
556
562
  }
557
563
 
558
564
  if (nodeId && this.props.onMoveSelected) {
559
- this.props.onMoveSelected(nodeId);
565
+ this.props.onMoveSelected(nodeId, evtOrigin);
560
566
  }
561
567
  }
562
568
  }, {
@@ -565,7 +571,7 @@ var Movetext = /*#__PURE__*/function (_React$Component) {
565
571
  this.focusFieldRef.current.focus();
566
572
 
567
573
  if (this.props.onMoveSelected) {
568
- this.props.onMoveSelected(nodeId === this.props.selection ? undefined : nodeId);
574
+ this.props.onMoveSelected(nodeId === this.props.selection ? undefined : nodeId, 'click');
569
575
  }
570
576
  }
571
577
  /**
@@ -675,10 +681,16 @@ Movetext.propTypes = {
675
681
  interactionMode: _propTypes["default"].oneOf(['selectMove']),
676
682
 
677
683
  /**
678
- * Callback invoked when the user clicks on a move (only if `interactionMode` is set to `'selectMove'`).
684
+ * Callback invoked when the user selects a move (only if `interactionMode` is set to `'selectMove'`).
679
685
  *
680
686
  * @param {string?} nodeId ID of the selected move (as returned by [kokopu.Node#id](https://kokopu.yo35.org/docs/Node.html#id)),
681
687
  * `'start'` for the beginning of the main variation, or `undefined` if the user unselects the previously selected move.
688
+ * @param {string} evtOrigin Origin of the event. Can be:
689
+ * - `'key-first'`: the event has been triggered by the "go-to-first-move" key (aka. the home key),
690
+ * - `'key-previous'`: the event has been triggered by the "go-to-previous-move" key (aka. the arrow left key),
691
+ * - `'key-next'`: the event has been triggered by the "go-to-next-move" key (aka. the arrow right key),
692
+ * - `'key-last'`: the event has been triggered by the "go-to-last-move" key (aka. the end key),
693
+ * - `'click'`: the event has been triggered by a mouse click on a move.
682
694
  */
683
695
  onMoveSelected: _propTypes["default"].func
684
696
  };
@@ -50,6 +50,7 @@ export default class Page extends React.Component {
50
50
  selection: '28b',
51
51
  interactionMode: 'selectMove',
52
52
  withPopup: true,
53
+ withMove: false,
53
54
  };
54
55
  }
55
56
 
@@ -91,7 +92,7 @@ export default class Page extends React.Component {
91
92
  pieceSymbols="figurines"
92
93
  diagramVisible={false}
93
94
  interactionMode={this.state.interactionMode}
94
- onMoveSelected={nodeId => this.handleMoveSelected(nodeId)}
95
+ onMoveSelected={(nodeId, evtOrigin) => this.handleMoveSelected(nodeId, evtOrigin)}
95
96
  />
96
97
  </Box>
97
98
  );
@@ -117,14 +118,14 @@ export default class Page extends React.Component {
117
118
 
118
119
  renderNavigationBoard() {
119
120
  let button = <Button size="small" onClick={() => this.handlePopupToggled()}>{this.state.withPopup ? 'Reduce' : 'Open'}</Button>;
120
- let { position, csl, cal } = this.getCurrentPositionAndAnnotations();
121
- let content = this.state.withPopup ? <Stack><Chessboard position={position} squareMarkers={csl} arrowMarkers={cal} />{button}</Stack> : button;
121
+ let { position, move, csl, cal } = this.getCurrentPositionAndAnnotations();
122
+ let content = this.state.withPopup ? <Stack><Chessboard position={position} move={move} squareMarkers={csl} arrowMarkers={cal} animated={true} />{button}</Stack> : button;
122
123
  return <Paper className="kokopu-fixedPopup" elevation={3}>{content}</Paper>;
123
124
  }
124
125
 
125
- handleMoveSelected(nodeId) {
126
+ handleMoveSelected(nodeId, evtOrigin) {
126
127
  if (nodeId) {
127
- this.set('selection', nodeId);
128
+ this.set('selection', nodeId, 'withMove', evtOrigin === 'key-next');
128
129
  }
129
130
  }
130
131
 
@@ -149,7 +150,10 @@ export default class Page extends React.Component {
149
150
  }
150
151
  else {
151
152
  let node = game.findById(this.state.selection);
152
- return { position: node.position(), csl: node.tag('csl'), cal: node.tag('cal') };
153
+ let result = this.state.withMove ? { position: node.positionBefore(), move: node.notation() } : { position: node.position() };
154
+ result.csl = node.tag('csl');
155
+ result.cal = node.tag('cal');
156
+ return result;
153
157
  }
154
158
  }
155
159
  }
@@ -26,8 +26,8 @@ import { Movetext } from '../src/index';
26
26
 
27
27
  import pgn from './common/games.pgn';
28
28
 
29
- function onMoveSelected(nodeId) {
30
- setSandbox(`move selected: ${nodeId}`);
29
+ function onMoveSelected(nodeId, evtOrigin) {
30
+ setSandbox(`move selected: ${nodeId}\norigin: ${evtOrigin}`);
31
31
  }
32
32
 
33
33
  testApp([ /* eslint-disable react/jsx-key */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kokopu-react",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "A React-based library to create and display chessboard components.",
5
5
  "keywords": [
6
6
  "chess",
@@ -33,7 +33,7 @@
33
33
  "kokopu": "^2.7.0",
34
34
  "prop-types": "^15.8.1",
35
35
  "react": "^17.0.2",
36
- "react-draggable": "^4.4.4",
36
+ "react-draggable": "^4.4.5",
37
37
  "react-motion": "^0.5.2"
38
38
  },
39
39
  "devDependencies": {
@@ -43,13 +43,13 @@
43
43
  "@babel/preset-react": "^7.16.7",
44
44
  "@emotion/react": "^11.9.0",
45
45
  "@emotion/styled": "^11.8.1",
46
- "@mui/material": "^5.6.2",
46
+ "@mui/material": "^5.6.3",
47
47
  "babel-loader": "^8.2.5",
48
48
  "babel-plugin-istanbul": "^6.1.1",
49
49
  "copy-webpack-plugin": "^10.2.4",
50
50
  "coveralls": "^3.1.1",
51
51
  "css-loader": "^6.7.1",
52
- "eslint": "^8.13.0",
52
+ "eslint": "^8.14.0",
53
53
  "eslint-plugin-react": "^7.29.4",
54
54
  "html-webpack-plugin": "^5.5.0",
55
55
  "img-diff-js": "^0.5.2",
@@ -59,7 +59,7 @@
59
59
  "prompt": "^1.3.0",
60
60
  "react-dom": "^17.0.2",
61
61
  "react-styleguidist": "^11.2.0",
62
- "selenium-webdriver": "^4.1.1",
62
+ "selenium-webdriver": "^4.1.2",
63
63
  "ssh2-sftp-client": "^8.0.0",
64
64
  "style-loader": "^3.3.1",
65
65
  "unit.js": "^2.1.1",
@@ -2,7 +2,7 @@ version: "3.7"
2
2
 
3
3
  services:
4
4
  web-client:
5
- image: selenium/standalone-firefox:4.1.1-20220121
5
+ image: selenium/standalone-firefox:4.1.4-20220427
6
6
  shm_size: '2gb'
7
7
  ports:
8
8
  - 4444:4444 # Driver (http://localhost:4444)
package/src/Chessboard.js CHANGED
@@ -83,10 +83,10 @@ export default class Chessboard extends React.Component {
83
83
  // Compute the current position.
84
84
  let info = this.getPositionAndMoveInfo();
85
85
  if (info.positionError) {
86
- return <ErrorBox title={i18n.INVALID_FEN_ERROR_TITLE} message={info.message}></ErrorBox>;
86
+ return <ErrorBox title={i18n.INVALID_FEN_ERROR_TITLE} message={info.message} />;
87
87
  }
88
88
  else if (info.moveError) {
89
- return <ErrorBox title={i18n.INVALID_NOTATION_ERROR_TITLE} message={info.message}></ErrorBox>;
89
+ return <ErrorBox title={i18n.INVALID_NOTATION_ERROR_TITLE} message={info.message} />;
90
90
  }
91
91
  let { position, move, positionBefore } = info;
92
92
 
package/src/Movetext.js CHANGED
@@ -46,14 +46,12 @@ export default class Movetext extends React.Component {
46
46
  render() {
47
47
  let info = parseGame(this.props.game, this.props.gameIndex);
48
48
  if (info.error) {
49
- return <ErrorBox title={i18n.INVALID_PGN_ERROR_TITLE} message={info.message} text={info.text} errorIndex={info.errorIndex} lineNumber={info.lineNumber}></ErrorBox>;
49
+ return <ErrorBox title={i18n.INVALID_PGN_ERROR_TITLE} message={info.message} text={info.text} errorIndex={info.errorIndex} lineNumber={info.lineNumber} />;
50
50
  }
51
- let game = info.game;
52
-
53
51
  return (
54
52
  <div className="kokopu-movetext">
55
- {this.renderHeaders(game)}
56
- {this.renderBody(game)}
53
+ {this.renderHeaders(info.game)}
54
+ {this.renderBody(info.game)}
57
55
  {this.renderFocusField()}
58
56
  </div>
59
57
  );
@@ -338,12 +336,15 @@ export default class Movetext extends React.Component {
338
336
  }
339
337
  let game = parseGame(this.props.game, this.props.gameIndex).game;
340
338
  let nodeId = false;
339
+ let evtOrigin = '';
341
340
  if (this.props.selection === 'start') {
342
341
  if (evt.key === 'ArrowRight') {
343
342
  nodeId = getNextNodeId(game.mainVariation(), true);
343
+ evtOrigin = 'key-next';
344
344
  }
345
345
  else if (evt.key === 'End') {
346
346
  nodeId = getLastNodeId(game.mainVariation(), true);
347
+ evtOrigin = 'key-last';
347
348
  }
348
349
  }
349
350
  else {
@@ -353,26 +354,30 @@ export default class Movetext extends React.Component {
353
354
  }
354
355
  if (evt.key === 'Home') {
355
356
  nodeId = 'start';
357
+ evtOrigin = 'key-first';
356
358
  }
357
359
  else if (evt.key === 'ArrowLeft') {
358
360
  nodeId = getPreviousNodeId(currentNode);
361
+ evtOrigin = 'key-previous';
359
362
  }
360
363
  else if (evt.key === 'ArrowRight') {
361
364
  nodeId = getNextNodeId(currentNode, false);
365
+ evtOrigin = 'key-next';
362
366
  }
363
367
  else if (evt.key === 'End') {
364
368
  nodeId = getLastNodeId(currentNode, false);
369
+ evtOrigin = 'key-last';
365
370
  }
366
371
  }
367
372
  if (nodeId && this.props.onMoveSelected) {
368
- this.props.onMoveSelected(nodeId);
373
+ this.props.onMoveSelected(nodeId, evtOrigin);
369
374
  }
370
375
  }
371
376
 
372
377
  handleNodeClicked(nodeId) {
373
378
  this.focusFieldRef.current.focus();
374
379
  if (this.props.onMoveSelected) {
375
- this.props.onMoveSelected(nodeId === this.props.selection ? undefined : nodeId);
380
+ this.props.onMoveSelected(nodeId === this.props.selection ? undefined : nodeId, 'click');
376
381
  }
377
382
  }
378
383
 
@@ -473,10 +478,16 @@ Movetext.propTypes = {
473
478
  interactionMode: PropTypes.oneOf([ 'selectMove' ]),
474
479
 
475
480
  /**
476
- * Callback invoked when the user clicks on a move (only if `interactionMode` is set to `'selectMove'`).
481
+ * Callback invoked when the user selects a move (only if `interactionMode` is set to `'selectMove'`).
477
482
  *
478
483
  * @param {string?} nodeId ID of the selected move (as returned by [kokopu.Node#id](https://kokopu.yo35.org/docs/Node.html#id)),
479
484
  * `'start'` for the beginning of the main variation, or `undefined` if the user unselects the previously selected move.
485
+ * @param {string} evtOrigin Origin of the event. Can be:
486
+ * - `'key-first'`: the event has been triggered by the "go-to-first-move" key (aka. the home key),
487
+ * - `'key-previous'`: the event has been triggered by the "go-to-previous-move" key (aka. the arrow left key),
488
+ * - `'key-next'`: the event has been triggered by the "go-to-next-move" key (aka. the arrow right key),
489
+ * - `'key-last'`: the event has been triggered by the "go-to-last-move" key (aka. the end key),
490
+ * - `'click'`: the event has been triggered by a mouse click on a move.
480
491
  */
481
492
  onMoveSelected: PropTypes.func,
482
493
  };
@@ -53,18 +53,22 @@ describe('Movetext interaction', function() {
53
53
  });
54
54
  }
55
55
 
56
+ function tpl(nodeId, evtOrigin) {
57
+ return `move selected: ${nodeId}\norigin: ${evtOrigin}`;
58
+ }
59
+
56
60
  itCheckClickMove(0, 'click on disabled', [
57
61
  { searchedText: 'Nf6', expectedText: '' },
58
62
  { searchedText: 'Qc2', expectedText: '' },
59
63
  ]);
60
64
 
61
65
  itCheckClickMove(1, 'click on unselected', [
62
- { searchedText: 'cxd5', expectedText: 'move selected: 5w' },
66
+ { searchedText: 'cxd5', expectedText: tpl('5w', 'click') },
63
67
  ]);
64
68
 
65
69
  itCheckClickMove(2, 'click on with variations 1', [
66
- { searchedText: 'Bb5', expectedText: 'move selected: undefined' },
67
- { searchedText: 'Nc6', expectedText: 'move selected: 1b-v0-2b' },
70
+ { searchedText: 'Bb5', expectedText: tpl(undefined, 'click') },
71
+ { searchedText: 'Nc6', expectedText: tpl('1b-v0-2b', 'click') },
68
72
  ]);
69
73
 
70
74
  function itCheckKeyboardActions(itemIndex, label, expectedOnGoFirst, expectedOnGoPrevious, expectedOnGoNext, expectedOnGoLast) {
@@ -90,10 +94,10 @@ describe('Movetext interaction', function() {
90
94
  }
91
95
 
92
96
  itCheckKeyboardActions(1, 'key on unselected', '', '', '', '');
93
- itCheckKeyboardActions(2, 'key on with variations 1', 'move selected: start', 'move selected: 1b-v0-2b', 'move selected: 1b-v0-3w-v0-3b', 'move selected: 1b-v0-3w-v0-4w');
94
- itCheckKeyboardActions(3, 'key on with variations 2', 'move selected: start', 'move selected: 1b-v0-2w', 'move selected: 1b-v0-3w', 'move selected: 1b-v0-3w');
95
- itCheckKeyboardActions(4, 'key on start selected', '', '', 'move selected: 1w', 'move selected: 6b');
96
- itCheckKeyboardActions(5, 'key on first selected', 'move selected: start', 'move selected: start', 'move selected: 1b', 'move selected: 6b');
97
- itCheckKeyboardActions(6, 'key on last selected', 'move selected: start', 'move selected: 6w', '', '');
97
+ itCheckKeyboardActions(2, 'key on with variations 1', tpl('start', 'key-first'), tpl('1b-v0-2b', 'key-previous'), tpl('1b-v0-3w-v0-3b', 'key-next'), tpl('1b-v0-3w-v0-4w', 'key-last'));
98
+ itCheckKeyboardActions(3, 'key on with variations 2', tpl('start', 'key-first'), tpl('1b-v0-2w', 'key-previous'), tpl('1b-v0-3w', 'key-next'), tpl('1b-v0-3w', 'key-last'));
99
+ itCheckKeyboardActions(4, 'key on start selected', '', '', tpl('1w', 'key-next'), tpl('6b', 'key-last'));
100
+ itCheckKeyboardActions(5, 'key on first selected', tpl('start', 'key-first'), tpl('start', 'key-previous'), tpl('1b', 'key-next'), tpl('6b', 'key-last'));
101
+ itCheckKeyboardActions(6, 'key on last selected', tpl('start', 'key-first'), tpl('6w', 'key-previous'), '', '');
98
102
  itCheckKeyboardActions(7, 'key on invalid selection', '', '', '', '');
99
103
  });