Skip to content

Commit 44393a9

Browse files
kensodemannadamdbradley
authored andcommitted
feat(mock-doc): add KeyboardEvent (#1581)
1 parent 048118b commit 44393a9

File tree

6 files changed

+169
-5
lines changed

6 files changed

+169
-5
lines changed

src/mock-doc/event.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,26 @@ export class MockCustomEvent extends MockEvent {
5555

5656
}
5757

58+
export class MockKeyboardEvent extends MockEvent {
59+
code = '';
60+
key = '';
61+
altKey = false;
62+
ctrlKey = false;
63+
metaKey = false;
64+
shiftKey = false;
65+
location = 0;
66+
repeat = false;
67+
68+
constructor(type: string, keyboardEventInitDic?: KeyboardEventInit) {
69+
super(type);
70+
71+
if (keyboardEventInitDic != null) {
72+
Object.assign(this, keyboardEventInitDic);
73+
}
74+
}
75+
76+
}
77+
5878

5979
export class MockEventListener {
6080
type: string;

src/mock-doc/global.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ const WINDOW_PROPS = [
5959
'CSS',
6060
'CustomEvent',
6161
'Event',
62-
'HTMLElement'
62+
'HTMLElement',
63+
'KeyboardEvent'
6364
];

src/mock-doc/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
export { MockAttr, MockAttributeMap, cloneAttributes } from './attribute';
33
export { MockComment } from './comment-node';
44
export { MockElement, MockNode, MockTextNode } from './node';
5-
export { MockCustomEvent } from './event';
5+
export { MockCustomEvent, MockKeyboardEvent } from './event';
66
export { MockDocument, createDocument, createFragment, resetDocument } from './document';
77
export { MockWindow, cloneDocument, cloneWindow, constrainTimeouts, resetWindow } from './window';
88
export { NODE_TYPES } from './constants';

src/mock-doc/test/event.spec.ts

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { MockWindow } from '../window';
22

3-
43
describe('event', () => {
54
let win: MockWindow;
65
beforeEach(() => {
@@ -72,7 +71,7 @@ describe('event', () => {
7271
composed: true,
7372
detail: 88
7473
};
75-
const ev = new win.Event('click', eventInitDict) as CustomEvent;
74+
const ev = new win.CustomEvent('click', eventInitDict) as CustomEvent;
7675
expect(ev.bubbles).toBe(true);
7776
expect(ev.cancelBubble).toBe(false);
7877
expect(ev.cancelable).toBe(false);
@@ -86,4 +85,65 @@ describe('event', () => {
8685
expect(ev.detail).toBe(88);
8786
});
8887

88+
it('KeyboardEvent() requires type', () => {
89+
expect(() => {
90+
new win.KeyboardEvent();
91+
}).toThrow();
92+
});
93+
94+
it('KeyboardEvent(type)', () => {
95+
const ev = new win.KeyboardEvent('keyup') as KeyboardEvent;
96+
expect(ev.bubbles).toBe(false);
97+
expect(ev.cancelBubble).toBe(false);
98+
expect(ev.cancelable).toBe(false);
99+
expect(ev.composed).toBe(false);
100+
expect(ev.currentTarget).toBe(null);
101+
expect(ev.defaultPrevented).toBe(false);
102+
expect(ev.srcElement).toBe(null);
103+
expect(ev.target).toBe(null);
104+
expect(typeof ev.timeStamp).toBe('number');
105+
expect(ev.type).toBe('keyup');
106+
expect(ev.code).toBe('');
107+
expect(ev.key).toBe('');
108+
expect(ev.altKey).toBe(false);
109+
expect(ev.ctrlKey).toBe(false);
110+
expect(ev.metaKey).toBe(false);
111+
expect(ev.shiftKey).toBe(false);
112+
expect(ev.location).toBe(0);
113+
expect(ev.repeat).toBe(false);
114+
});
115+
116+
it('KeyboardEvent(type, eventInitDict)', () => {
117+
const eventInitDict = {
118+
bubbles: true,
119+
composed: true,
120+
code: 'KeyA',
121+
key: 'A',
122+
altKey: false,
123+
ctrlKey: false,
124+
metaKey: false,
125+
shiftKey: true,
126+
location: 0,
127+
repeat: true
128+
};
129+
const ev = new win.KeyboardEvent('keyup', eventInitDict) as KeyboardEvent;
130+
expect(ev.bubbles).toBe(true);
131+
expect(ev.cancelBubble).toBe(false);
132+
expect(ev.cancelable).toBe(false);
133+
expect(ev.composed).toBe(true);
134+
expect(ev.currentTarget).toBe(null);
135+
expect(ev.defaultPrevented).toBe(false);
136+
expect(ev.srcElement).toBe(null);
137+
expect(ev.target).toBe(null);
138+
expect(typeof ev.timeStamp).toBe('number');
139+
expect(ev.type).toBe('keyup');
140+
expect(ev.code).toBe('KeyA');
141+
expect(ev.key).toBe('A');
142+
expect(ev.altKey).toBe(false);
143+
expect(ev.ctrlKey).toBe(false);
144+
expect(ev.metaKey).toBe(false);
145+
expect(ev.shiftKey).toBe(true);
146+
expect(ev.location).toBe(0);
147+
expect(ev.repeat).toBe(true);
148+
});
89149
});

src/mock-doc/window.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createConsole } from './console';
22
import { MockCustomElementRegistry, resetCustomElementRegistry } from './custom-element-registry';
3-
import { MockCustomEvent, MockEvent, addEventListener, dispatchEvent, removeEventListener, resetEventListeners } from './event';
3+
import { MockCustomEvent, MockEvent, MockKeyboardEvent, addEventListener, dispatchEvent, removeEventListener, resetEventListeners } from './event';
44
import { MockDocument, resetDocument } from './document';
55
import { MockElement } from './node';
66
import { MockHistory } from './history';
@@ -19,6 +19,7 @@ const navMap = new WeakMap<MockWindow, MockNavigator>();
1919
const sessionStorageMap = new WeakMap<MockWindow, MockStorage>();
2020
const eventClassMap = new WeakMap<MockWindow, any>();
2121
const customEventClassMap = new WeakMap<MockWindow, any>();
22+
const keyboardEventClassMap = new WeakMap<MockWindow, any>();
2223

2324

2425
export class MockWindow {
@@ -101,6 +102,17 @@ export class MockWindow {
101102
customEventClassMap.set(this, custEvClass);
102103
}
103104

105+
get KeyboardEvent() {
106+
const kbEvClass = keyboardEventClassMap.get(this);
107+
if (kbEvClass != null) {
108+
return kbEvClass;
109+
}
110+
return MockKeyboardEvent;
111+
}
112+
set KeyboardEvent(kbEvClass: any) {
113+
keyboardEventClassMap.set(this, kbEvClass);
114+
}
115+
104116
dispatchEvent(ev: MockEvent) {
105117
return dispatchEvent(this, ev);
106118
}
@@ -408,6 +420,7 @@ export function resetWindow(win: Window) {
408420
sessionStorageMap.delete(win as any);
409421
eventClassMap.delete(win as any);
410422
customEventClassMap.delete(win as any);
423+
keyboardEventClassMap.delete(win as any);
411424

412425
if (win.document != null) {
413426
try {

src/runtime/test/event.spec.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,74 @@ describe('event', () => {
160160
<cmp-a>1</cmp-a>
161161
`);
162162
});
163+
164+
describe('KeyboardEvent', () => {
165+
it('can be dispatched', async () => {
166+
@Component({ tag: 'cmp-a'})
167+
class CmpA {
168+
@State() counter = 0;
169+
170+
@Listen('keydown')
171+
onKeyDown() {
172+
this.counter++;
173+
}
174+
175+
render() {
176+
return `${this.counter}`;
177+
}
178+
}
179+
180+
const { root, waitForChanges } = await newSpecPage({
181+
components: [CmpA],
182+
html: `<cmp-a></cmp-a>`,
183+
});
184+
185+
expect(root).toEqualHtml(`
186+
<cmp-a>0</cmp-a>
187+
`);
188+
189+
const ev = new KeyboardEvent('keydown');
190+
root.dispatchEvent(ev);
191+
await waitForChanges();
192+
193+
expect(root).toEqualHtml(`
194+
<cmp-a>1</cmp-a>
195+
`);
196+
});
197+
198+
it('can be dispatched with custom data', async () => {
199+
@Component({ tag: 'cmp-a'})
200+
class CmpA {
201+
@State() key: string;
202+
@State() shift: string;
203+
204+
@Listen('keydown')
205+
onKeyDown(ev: KeyboardEvent) {
206+
this.key = ev.key;
207+
this.shift = ev.shiftKey ? 'Yes' : 'No';
208+
}
209+
210+
render() {
211+
return `${this.key || ''} - ${this.shift || ''}`;
212+
}
213+
}
214+
215+
const { root, waitForChanges } = await newSpecPage({
216+
components: [CmpA],
217+
html: `<cmp-a></cmp-a>`,
218+
});
219+
220+
expect(root).toEqualHtml(`
221+
<cmp-a> - </cmp-a>
222+
`);
223+
224+
const ev = new KeyboardEvent('keydown', {key: 'A', shiftKey: true});
225+
root.dispatchEvent(ev);
226+
await waitForChanges();
227+
228+
expect(root).toEqualHtml(`
229+
<cmp-a>A - Yes</cmp-a>
230+
`);
231+
});
232+
});
163233
});

0 commit comments

Comments
 (0)