| ... | @@ -178,14 +178,35 @@ describe("makeQuitShortcutHandler", () => { | ... | @@ -178,14 +178,35 @@ describe("makeQuitShortcutHandler", () => { |
| 178 | await harness.holdFor(QUIT_HOLD_DURATION_MS + 200); | 178 | await harness.holdFor(QUIT_HOLD_DURATION_MS + 200); |
| 179 | await harness.send(makeInput({ type: "keyUp", key: "Meta", meta: false })); | 179 | await harness.send(makeInput({ type: "keyUp", key: "Meta", meta: false })); |
| 180 | harness.preventDefault.mockClear(); | 180 | harness.preventDefault.mockClear(); |
| 181 | await harness.send(makeInput({ meta: false, isAutoRepeat: true })); | 181 | // Repeats without the modifier prove Q is still down, so they hold the |
| 182 | expect(harness.preventDefault).toHaveBeenCalledTimes(1); | 182 | // quit back for as long as they keep arriving. |
| 183 | vi.advanceTimersByTime(QUIT_HOLD_RELEASE_GRACE_MS * 2); | 183 | await harness.holdFor(QUIT_HOLD_RELEASE_GRACE_MS * 2, { meta: false }); |
| | 184 | expect(harness.preventDefault).toHaveBeenCalled(); |
| 184 | expect(harness.quit).not.toHaveBeenCalled(); | 185 | expect(harness.quit).not.toHaveBeenCalled(); |
| 185 | await harness.send(makeInput({ type: "keyUp", meta: false })); | 186 | await harness.send(makeInput({ type: "keyUp", meta: false })); |
| 186 | expect(harness.quit).toHaveBeenCalledTimes(1); | 187 | expect(harness.quit).toHaveBeenCalledTimes(1); |
| 187 | }); | 188 | }); |
| 188 | | 189 | |
| | 190 | it("commits a concealed hold when the last Q repeat is never released", async () => { |
| | 191 | // macOS can drop the final Q keyUp. The quit must land on its own once |
| | 192 | // repeats stop, rather than sitting armed until an unrelated key arrives. |
| | 193 | const harness = makeHarness(); |
| | 194 | await harness.send(makeInput({})); |
| | 195 | await harness.holdFor(QUIT_HOLD_DURATION_MS + 200); |
| | 196 | await harness.send(makeInput({ type: "keyUp", key: "Meta", meta: false })); |
| | 197 | await harness.send(makeInput({ meta: false, isAutoRepeat: true })); |
| | 198 | |
| | 199 | vi.advanceTimersByTime(QUIT_HOLD_RELEASE_GRACE_MS); |
| | 200 | expect(harness.quit).toHaveBeenCalledTimes(1); |
| | 201 | |
| | 202 | // A lone Cmd tap afterwards must not quit a second time. |
| | 203 | harness.quit.mockClear(); |
| | 204 | await harness.send(makeInput({ key: "Meta" })); |
| | 205 | await harness.send(makeInput({ type: "keyUp", key: "Meta", meta: false })); |
| | 206 | vi.advanceTimersByTime(QUIT_HOLD_RELEASE_GRACE_MS * 4); |
| | 207 | expect(harness.quit).not.toHaveBeenCalled(); |
| | 208 | }); |
| | 209 | |
| 189 | it("does not quit when the hold stops before the duration", async () => { | 210 | it("does not quit when the hold stops before the duration", async () => { |
| 190 | const harness = makeHarness(); | 211 | const harness = makeHarness(); |
| 191 | await harness.send(makeInput({})); | 212 | await harness.send(makeInput({})); |