Skip to content

Commit 23547f4

Browse files
committed
fix tests
1 parent b1ec9ea commit 23547f4

File tree

9 files changed

+84
-56
lines changed

9 files changed

+84
-56
lines changed

knip.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@
22
"$schema": "https://unpkg.com/knip@5/schema.json",
33
"ignoreDependencies": ["@faker-js/faker"],
44
"ignoreWorkspaces": ["examples/**"],
5-
"ignore": ["**/eslint.config.js"],
6-
"eslint": {
7-
"config": []
8-
},
95
"workspaces": {
10-
"packages/react-pacer": {
6+
"packages/react-keys": {
117
"ignore": []
128
}
139
}

packages/keys/src/constants.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ export function detectPlatform(): 'mac' | 'windows' | 'linux' {
1313
return 'linux' // Default for SSR
1414
}
1515

16-
const platform = navigator.platform?.toLowerCase() ?? ''
17-
const userAgent = navigator.userAgent?.toLowerCase() ?? ''
16+
const platform = navigator.platform.toLowerCase()
17+
const userAgent = navigator.userAgent.toLowerCase()
1818

1919
if (platform.includes('mac') || userAgent.includes('mac')) {
2020
return 'mac'

packages/keys/src/match.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export function createMultiHotkeyHandler(
152152
// Pre-parse all hotkeys for efficiency
153153
const parsedHandlers = Object.entries(handlers)
154154
.filter(
155-
(entry): entry is [string, HotkeyCallback] => entry[1] !== undefined,
155+
(entry): entry is [string, HotkeyCallback] => Boolean(entry[1]),
156156
)
157157
.map(([hotkey, handler]) => {
158158
const parsed = parseHotkey(hotkey as Hotkey, resolvedPlatform)

packages/react-keys-devtools/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@
5050
"src"
5151
],
5252
"devDependencies": {
53+
"@eslint-react/eslint-plugin": "^2.8.1",
5354
"@types/react": "^19.2.10",
5455
"@vitejs/plugin-react": "^5.1.2",
56+
"eslint-plugin-react-compiler": "19.1.0-rc.2",
57+
"eslint-plugin-react-hooks": "^7.0.1",
5558
"react": "^19.2.4"
5659
},
5760
"peerDependencies": {

packages/react-keys/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959
"@vitejs/plugin-react": "^5.1.2",
6060
"eslint-plugin-react-compiler": "19.1.0-rc.2",
6161
"eslint-plugin-react-hooks": "^7.0.1",
62-
"react": "^19.2.4"
62+
"react": "^19.2.4",
63+
"react-dom": "^19.2.4"
6364
},
6465
"peerDependencies": {
6566
"react": ">=16.8",

packages/react-keys/src/useHotkey.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,26 @@ export function useHotkey(
6767
): void {
6868
const { enabled = true, ...hotkeyOptions } = options
6969

70+
// Extract options for stable dependencies
71+
const {
72+
preventDefault,
73+
stopPropagation,
74+
platform,
75+
eventType,
76+
requireReset,
77+
} = hotkeyOptions
78+
7079
// Use refs to keep callback and hotkey stable across renders
7180
const callbackRef = useRef(callback)
7281
callbackRef.current = callback
7382

7483
const hotkeyRef = useRef(hotkey)
7584
hotkeyRef.current = hotkey
7685

86+
// Serialize hotkey for dependency comparison
87+
const hotkeyKey =
88+
typeof hotkey === 'string' ? hotkey : JSON.stringify(hotkey)
89+
7790
useEffect(() => {
7891
if (!enabled) {
7992
return
@@ -86,25 +99,33 @@ export function useHotkey(
8699
: formatParsedHotkey(hotkeyValue)
87100

88101
const manager = getHotkeyManager()
102+
103+
// Build options object, only including defined values to avoid
104+
// overwriting manager defaults with undefined
105+
const registerOptions: HotkeyOptions = { enabled: true }
106+
if (preventDefault !== undefined)
107+
registerOptions.preventDefault = preventDefault
108+
if (stopPropagation !== undefined)
109+
registerOptions.stopPropagation = stopPropagation
110+
if (platform !== undefined) registerOptions.platform = platform
111+
if (eventType !== undefined) registerOptions.eventType = eventType
112+
if (requireReset !== undefined) registerOptions.requireReset = requireReset
113+
89114
const unregister = manager.register(
90115
hotkeyString,
91116
(event, context) => callbackRef.current(event, context),
92-
{
93-
...hotkeyOptions,
94-
enabled: true,
95-
},
117+
registerOptions,
96118
)
97119

98120
return unregister
99121
}, [
100122
enabled,
101-
hotkeyOptions.preventDefault,
102-
hotkeyOptions.stopPropagation,
103-
hotkeyOptions.platform,
104-
hotkeyOptions.eventType,
105-
hotkeyOptions.requireReset,
106-
// Re-register if hotkey changes (serialize for comparison)
107-
typeof hotkey === 'string' ? hotkey : JSON.stringify(hotkey),
123+
preventDefault,
124+
stopPropagation,
125+
platform,
126+
eventType,
127+
requireReset,
128+
hotkeyKey,
108129
])
109130
}
110131

packages/react-keys/src/useHotkeySequence.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ export function useHotkeySequence(
5353
): void {
5454
const { enabled = true, ...sequenceOptions } = options
5555

56+
// Extract options for stable dependencies
57+
const { timeout, platform } = sequenceOptions
58+
5659
// Use refs to keep callback stable
5760
const callbackRef = useRef(callback)
5861
callbackRef.current = callback
@@ -66,16 +69,18 @@ export function useHotkeySequence(
6669
}
6770

6871
const manager = getSequenceManager()
72+
73+
// Build options object conditionally to avoid overwriting manager defaults with undefined
74+
const registerOptions: SequenceOptions = { enabled: true }
75+
if (timeout !== undefined) registerOptions.timeout = timeout
76+
if (platform !== undefined) registerOptions.platform = platform
77+
6978
const unregister = manager.register(
7079
sequence,
7180
(event, context) => callbackRef.current(event, context),
72-
{
73-
...sequenceOptions,
74-
enabled: true,
75-
},
81+
registerOptions,
7682
)
7783

7884
return unregister
79-
// eslint-disable-next-line react-hooks/exhaustive-deps
80-
}, [enabled, sequenceKey, sequenceOptions.timeout, sequenceOptions.platform])
85+
}, [enabled, sequence, sequenceKey, timeout, platform])
8186
}

packages/react-keys/tests/useHotkey.test.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1-
import { describe, expect, it, vi } from 'vitest'
1+
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest'
22
import { renderHook } from '@testing-library/react'
3+
import { HotkeyManager } from '@tanstack/keys'
34
import { useHotkey } from '../src/useHotkey'
45

56
describe('useHotkey', () => {
7+
// Reset the HotkeyManager singleton between tests
8+
beforeEach(() => {
9+
HotkeyManager.resetInstance()
10+
})
11+
12+
afterEach(() => {
13+
HotkeyManager.resetInstance()
14+
})
15+
616
it('should register a hotkey handler', () => {
717
const callback = vi.fn()
818
const addEventListenerSpy = vi.spyOn(document, 'addEventListener')
@@ -57,6 +67,7 @@ describe('useHotkey', () => {
5767
const event = new KeyboardEvent('keydown', {
5868
key: 's',
5969
metaKey: true,
70+
bubbles: true,
6071
})
6172
document.dispatchEvent(event)
6273

@@ -72,6 +83,7 @@ describe('useHotkey', () => {
7283
const event = new KeyboardEvent('keydown', {
7384
key: 'a',
7485
metaKey: true,
86+
bubbles: true,
7587
})
7688
document.dispatchEvent(event)
7789

pnpm-lock.yaml

Lines changed: 19 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)