1- import { describe , expect , it } from "vite-plus/test" ;
1+ // @vitest -environment jsdom
2+
3+ import { act , createElement } from "react" ;
4+ import { createRoot , type Root } from "react-dom/client" ;
5+ import { afterEach , beforeEach , describe , expect , it , vi } from "vite-plus/test" ;
26
37import {
48 areShortcutModifierStatesEqual ,
59 shortcutModifierStateAfterKeyboardEvent ,
10+ useShortcutModifierState ,
611 type ShortcutModifierState ,
712} from "./shortcutModifierState" ;
813
@@ -13,6 +18,67 @@ const emptyState = (): ShortcutModifierState => ({
1318 shiftKey : false ,
1419} ) ;
1520
21+ describe ( "useShortcutModifierState" , ( ) => {
22+ let root : Root ;
23+ let container : HTMLDivElement ;
24+
25+ beforeEach ( ( ) => {
26+ vi . stubGlobal ( "IS_REACT_ACT_ENVIRONMENT" , true ) ;
27+ container = document . createElement ( "div" ) ;
28+ document . body . append ( container ) ;
29+ root = createRoot ( container ) ;
30+ } ) ;
31+
32+ afterEach ( async ( ) => {
33+ await act ( async ( ) => root . unmount ( ) ) ;
34+ container . remove ( ) ;
35+ vi . unstubAllGlobals ( ) ;
36+ } ) ;
37+
38+ it . each ( [ "keyup" , "paste" , "blur" ] as const ) (
39+ "does not render for unchanged modifiers after %s resets the state" ,
40+ async ( reset ) => {
41+ const render = vi . fn ( ) ;
42+ function Consumer ( ) {
43+ render ( useShortcutModifierState ( ) ) ;
44+ return null ;
45+ }
46+ await act ( async ( ) => {
47+ root . render ( createElement ( Consumer ) ) ;
48+ } ) ;
49+ const press = async ( type : "keydown" | "keyup" , key : string , shiftKey = false ) => {
50+ await act ( async ( ) => {
51+ window . dispatchEvent ( new KeyboardEvent ( type , { key, shiftKey } ) ) ;
52+ } ) ;
53+ } ;
54+
55+ await press ( "keydown" , "Shift" , true ) ;
56+ expect ( render ) . toHaveBeenLastCalledWith ( { ...emptyState ( ) , shiftKey : true } ) ;
57+ if ( reset === "keyup" ) {
58+ await press ( "keyup" , "Shift" ) ;
59+ } else {
60+ await act ( async ( ) => {
61+ window . dispatchEvent ( new Event ( reset ) ) ;
62+ } ) ;
63+ }
64+ expect ( render ) . toHaveBeenLastCalledWith ( emptyState ( ) ) ;
65+ render . mockClear ( ) ;
66+
67+ for ( const key of "typing" ) {
68+ await press ( "keydown" , key ) ;
69+ await press ( "keyup" , key ) ;
70+ }
71+ await act ( async ( ) => {
72+ window . dispatchEvent ( new Event ( "paste" ) ) ;
73+ window . dispatchEvent ( new Event ( "blur" ) ) ;
74+ } ) ;
75+ expect ( render ) . not . toHaveBeenCalled ( ) ;
76+ await press ( "keydown" , "Shift" , true ) ;
77+ expect ( render ) . toHaveBeenCalledExactlyOnceWith ( { ...emptyState ( ) , shiftKey : true } ) ;
78+ } ,
79+ ) ;
80+ } ) ;
81+
1682function keyboardEventLike ( type : "keydown" | "keyup" , init : Partial < KeyboardEvent > ) : KeyboardEvent {
1783 return {
1884 type,
0 commit comments