@blotch/angular-lynx-testing-library 22.2.4 → 22.2.6
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.
- package/README.md +14 -5
- package/dist/fire-event.d.ts +65 -19
- package/dist/fire-event.d.ts.map +1 -1
- package/dist/fire-event.js +135 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ Call this after any signal mutation that happens outside an event handler (e.g.
|
|
|
110
110
|
|
|
111
111
|
### `fireEvent`
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
Fires Lynx events at JSDOM elements. Use the named helpers for standard Lynx events:
|
|
114
114
|
|
|
115
115
|
```ts
|
|
116
116
|
import { fireEvent } from '@blotch/angular-lynx-testing-library';
|
|
@@ -120,7 +120,16 @@ fireEvent.input(element, { value: 'hello' });
|
|
|
120
120
|
fireEvent.scroll(element, { scrollTop: 100 });
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
A named helper runs the handlers a device would, in the same order:
|
|
124
|
+
|
|
125
|
+
- **Touch events bubble.** A tap, long press or touch runs the element's own `(bindtap)` or `(catchtap)`, then its ancestors' on the way up to the page. So a tap on a row inside a pressable card reaches the card's `(click)`. `(capture-bind…)` and `(capture-catch…)` handlers run before them, from the page down.
|
|
126
|
+
- **Mouse, wheel and key events bubble too**, as Lynx sends them on desktop and web.
|
|
127
|
+
- **A `catch` handler stops the event** where it runs: a `(catchtap)` panel keeps a tap from reaching the backdrop behind it.
|
|
128
|
+
- **Other events stay on their element.** `scroll`, `input`, `layoutchange` and the rest run only the element's own handler.
|
|
129
|
+
|
|
130
|
+
`init.bubbles` overrides the event's own: `fireEvent.tap(element, { bubbles: false })` runs only the element's handler.
|
|
131
|
+
|
|
132
|
+
`init.eventType` fires at one kind of handler on the element and nothing else: `fireEvent.tap(element, { eventType: 'catchEvent' })` dispatches the DOM event `"catchEvent:tap"`, which reaches only the element's `(catchtap)`.
|
|
124
133
|
|
|
125
134
|
To dispatch a raw DOM event directly:
|
|
126
135
|
|
|
@@ -134,7 +143,7 @@ fireEvent(element, new Event('bindEvent:tap'));
|
|
|
134
143
|
|
|
135
144
|
### `eventMap`
|
|
136
145
|
|
|
137
|
-
The full Lynx event registry. Each entry has a `defaultInit` object
|
|
146
|
+
The full Lynx event registry. Each entry has a `defaultInit` object: `{ bubbles: true }` for the events Lynx sends up the response chain, `{}` for the rest.
|
|
138
147
|
|
|
139
148
|
```ts
|
|
140
149
|
import { eventMap } from '@blotch/angular-lynx-testing-library';
|
|
@@ -179,7 +188,7 @@ expect(getByRole('button', { name: 'Week', selected: true })).toBeTruthy();
|
|
|
179
188
|
- **Role**: from each trait in the table. An `<image>` is an `img` unless it sets `accessibility-traits`.
|
|
180
189
|
- **Reachable**: a screen reader reaches `<text>`, `<image>`, and other elements with `accessibility-element="true"`, outside `accessibility-elements-hidden`. A `tabbar` is read from the container around the tabs, so it needs no `accessibility-element`. Others match only with `hidden: true`.
|
|
181
190
|
- **`name`**: the `accessibility-label`, or a `<text>`'s own text. A `<view>` gets no name from the text inside it, since iOS doesn't read it.
|
|
182
|
-
- **`selected`**: the `selected` trait, as in `accessibility-traits="button,selected"`, which an active `routerLinkActive` element gets. iOS reads a comma-separated list. Android reads one trait (`button` or `image`) and treats a list as `none`.
|
|
191
|
+
- **`selected`**: the `selected` trait, as in `accessibility-traits="button,selected"`, which an active `routerLinkActive` element gets, and which `[lynxAccessibilityTraits]="{ selected: true }"` adds. iOS reads a comma-separated list. Android reads one trait (`button` or `image`) and treats a list as `none`.
|
|
183
192
|
- **`value: { text }`**: the `accessibility-value`.
|
|
184
193
|
- **Other ARIA states** (`checked`, `pressed`, `expanded`, `level`, …) have no Lynx attribute, so Lynx elements never match them.
|
|
185
194
|
|
|
@@ -400,7 +409,7 @@ render(Component)
|
|
|
400
409
|
|
|
401
410
|
AngularLynx registers event handlers via `__AddEvent(element, eventType, eventName, { type: 'worklet', value: callback })`. The testing environment stores this as a DOM event listener under the key `"${eventType}:${eventName}"` (e.g. `"bindEvent:tap"`).
|
|
402
411
|
|
|
403
|
-
`fireEvent.tap(el)`
|
|
412
|
+
`fireEvent.tap(el)` walks Lynx's event response chain, from the page down to `el` and back up, and calls each element's listener for the kind of handler it has, stopping at a `catch` one. The listener calls `runWorklet(callback, [event])` which invokes the Angular handler directly on the main thread. One bubbling `"bindEvent:tap"` DOM event wouldn't do: it would pass a `(catchtap)` ancestor's `"catchEvent:tap"` listener by and run the handlers above it.
|
|
404
413
|
|
|
405
414
|
Template binding → PAPI registration → DOM listener key:
|
|
406
415
|
|
package/dist/fire-event.d.ts
CHANGED
|
@@ -1,64 +1,110 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* fireEvent — dispatches Lynx events through the dual-thread pipeline.
|
|
3
3
|
*
|
|
4
|
-
* Lynx events are registered via __AddEvent with a key of "
|
|
4
|
+
* Lynx events are registered via __AddEvent with a key of "<type>:<name>"
|
|
5
5
|
* (e.g. "bindEvent:tap"). The event handler stored on the element calls
|
|
6
6
|
* lynxCoreInject.tt.publishEvent(handlerSign, eventData) which routes the
|
|
7
7
|
* event to the background thread (not used by AngularLynx, which runs on
|
|
8
8
|
* the main thread).
|
|
9
9
|
*
|
|
10
10
|
* For AngularLynx, the (event) bindings in templates are wired by
|
|
11
|
-
* LynxRenderer.listen() which calls __AddEvent internally. The
|
|
12
|
-
*
|
|
11
|
+
* LynxRenderer.listen() which calls __AddEvent internally. The named helpers
|
|
12
|
+
* (fireEvent.tap, …) run those handlers on the main thread along the path
|
|
13
|
+
* Lynx sends the event (see deliver()).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The events the named helpers fire. Those with `bubbles: true` travel Lynx's
|
|
17
|
+
* event response chain, from the element up to the page, so a tap on a row
|
|
18
|
+
* inside a pressable card reaches the card's handler. The rest reach only
|
|
19
|
+
* the element they happened on, as Lynx sends an element's own events
|
|
20
|
+
* (scroll, input, layout, …).
|
|
21
|
+
*
|
|
22
|
+
* The touch events bubble on every platform, as React Lynx's testing library
|
|
23
|
+
* has them. Mouse, wheel and key events bubble too, where Lynx sends them:
|
|
24
|
+
* its desktop engine dispatches them with TouchEventHandler::HandleBubbleEvent
|
|
25
|
+
* (all but mouseenter and mouseleave) and Lynx for Web with the DOM event's
|
|
26
|
+
* own bubbling. iOS and Android don't send them.
|
|
13
27
|
*/
|
|
14
28
|
export declare const eventMap: {
|
|
15
29
|
tap: {
|
|
16
|
-
defaultInit: {
|
|
30
|
+
defaultInit: {
|
|
31
|
+
bubbles: boolean;
|
|
32
|
+
};
|
|
17
33
|
};
|
|
18
34
|
longtap: {
|
|
19
|
-
defaultInit: {
|
|
35
|
+
defaultInit: {
|
|
36
|
+
bubbles: boolean;
|
|
37
|
+
};
|
|
20
38
|
};
|
|
21
39
|
touchstart: {
|
|
22
|
-
defaultInit: {
|
|
40
|
+
defaultInit: {
|
|
41
|
+
bubbles: boolean;
|
|
42
|
+
};
|
|
23
43
|
};
|
|
24
44
|
touchmove: {
|
|
25
|
-
defaultInit: {
|
|
45
|
+
defaultInit: {
|
|
46
|
+
bubbles: boolean;
|
|
47
|
+
};
|
|
26
48
|
};
|
|
27
49
|
touchcancel: {
|
|
28
|
-
defaultInit: {
|
|
50
|
+
defaultInit: {
|
|
51
|
+
bubbles: boolean;
|
|
52
|
+
};
|
|
29
53
|
};
|
|
30
54
|
touchend: {
|
|
31
|
-
defaultInit: {
|
|
55
|
+
defaultInit: {
|
|
56
|
+
bubbles: boolean;
|
|
57
|
+
};
|
|
32
58
|
};
|
|
33
59
|
longpress: {
|
|
34
|
-
defaultInit: {
|
|
60
|
+
defaultInit: {
|
|
61
|
+
bubbles: boolean;
|
|
62
|
+
};
|
|
35
63
|
};
|
|
36
64
|
keydown: {
|
|
37
|
-
defaultInit: {
|
|
65
|
+
defaultInit: {
|
|
66
|
+
bubbles: boolean;
|
|
67
|
+
};
|
|
38
68
|
};
|
|
39
69
|
keyup: {
|
|
40
|
-
defaultInit: {
|
|
70
|
+
defaultInit: {
|
|
71
|
+
bubbles: boolean;
|
|
72
|
+
};
|
|
41
73
|
};
|
|
42
74
|
mousedown: {
|
|
43
|
-
defaultInit: {
|
|
75
|
+
defaultInit: {
|
|
76
|
+
bubbles: boolean;
|
|
77
|
+
};
|
|
44
78
|
};
|
|
45
79
|
mouseup: {
|
|
46
|
-
defaultInit: {
|
|
80
|
+
defaultInit: {
|
|
81
|
+
bubbles: boolean;
|
|
82
|
+
};
|
|
47
83
|
};
|
|
48
84
|
mousemove: {
|
|
49
|
-
defaultInit: {
|
|
85
|
+
defaultInit: {
|
|
86
|
+
bubbles: boolean;
|
|
87
|
+
};
|
|
50
88
|
};
|
|
51
89
|
mouseclick: {
|
|
52
|
-
defaultInit: {
|
|
90
|
+
defaultInit: {
|
|
91
|
+
bubbles: boolean;
|
|
92
|
+
};
|
|
53
93
|
};
|
|
54
94
|
mousedblclick: {
|
|
55
|
-
defaultInit: {
|
|
95
|
+
defaultInit: {
|
|
96
|
+
bubbles: boolean;
|
|
97
|
+
};
|
|
56
98
|
};
|
|
57
99
|
mouselongpress: {
|
|
58
|
-
defaultInit: {
|
|
100
|
+
defaultInit: {
|
|
101
|
+
bubbles: boolean;
|
|
102
|
+
};
|
|
59
103
|
};
|
|
60
104
|
wheel: {
|
|
61
|
-
defaultInit: {
|
|
105
|
+
defaultInit: {
|
|
106
|
+
bubbles: boolean;
|
|
107
|
+
};
|
|
62
108
|
};
|
|
63
109
|
scroll: {
|
|
64
110
|
defaultInit: {};
|
package/dist/fire-event.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fire-event.d.ts","sourceRoot":"","sources":["../src/fire-event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"fire-event.d.ts","sourceRoot":"","sources":["../src/fire-event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAUH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CpB,CAAC;AAEF,KAAK,SAAS,GAAG,MAAM,OAAO,QAAQ,CAAC;AACvC,KAAK,YAAY,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;AAC/E,KAAK,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG;KAC3D,CAAC,IAAI,SAAS,GAAG,YAAY;CAC/B,CAAC;AA8GF,eAAO,MAAM,SAAS,EAAE,SAET,CAAC"}
|
package/dist/fire-event.js
CHANGED
|
@@ -1,38 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* fireEvent — dispatches Lynx events through the dual-thread pipeline.
|
|
3
3
|
*
|
|
4
|
-
* Lynx events are registered via __AddEvent with a key of "
|
|
4
|
+
* Lynx events are registered via __AddEvent with a key of "<type>:<name>"
|
|
5
5
|
* (e.g. "bindEvent:tap"). The event handler stored on the element calls
|
|
6
6
|
* lynxCoreInject.tt.publishEvent(handlerSign, eventData) which routes the
|
|
7
7
|
* event to the background thread (not used by AngularLynx, which runs on
|
|
8
8
|
* the main thread).
|
|
9
9
|
*
|
|
10
10
|
* For AngularLynx, the (event) bindings in templates are wired by
|
|
11
|
-
* LynxRenderer.listen() which calls __AddEvent internally. The
|
|
12
|
-
*
|
|
11
|
+
* LynxRenderer.listen() which calls __AddEvent internally. The named helpers
|
|
12
|
+
* (fireEvent.tap, …) run those handlers on the main thread along the path
|
|
13
|
+
* Lynx sends the event (see deliver()).
|
|
13
14
|
*/
|
|
14
|
-
import { createEvent, fireEvent as domFireEvent } from '@testing-library/dom';
|
|
15
|
+
import { createEvent, fireEvent as domFireEvent, getConfig, } from '@testing-library/dom';
|
|
15
16
|
const EVENT_INIT_KEYS = new Set(['bubbles', 'cancelable', 'composed']);
|
|
17
|
+
/**
|
|
18
|
+
* The events the named helpers fire. Those with `bubbles: true` travel Lynx's
|
|
19
|
+
* event response chain, from the element up to the page, so a tap on a row
|
|
20
|
+
* inside a pressable card reaches the card's handler. The rest reach only
|
|
21
|
+
* the element they happened on, as Lynx sends an element's own events
|
|
22
|
+
* (scroll, input, layout, …).
|
|
23
|
+
*
|
|
24
|
+
* The touch events bubble on every platform, as React Lynx's testing library
|
|
25
|
+
* has them. Mouse, wheel and key events bubble too, where Lynx sends them:
|
|
26
|
+
* its desktop engine dispatches them with TouchEventHandler::HandleBubbleEvent
|
|
27
|
+
* (all but mouseenter and mouseleave) and Lynx for Web with the DOM event's
|
|
28
|
+
* own bubbling. iOS and Android don't send them.
|
|
29
|
+
*/
|
|
16
30
|
export const eventMap = {
|
|
17
31
|
// Touch / gesture
|
|
18
|
-
tap: { defaultInit: {} },
|
|
19
|
-
longtap: { defaultInit: {} },
|
|
20
|
-
touchstart: { defaultInit: {} },
|
|
21
|
-
touchmove: { defaultInit: {} },
|
|
22
|
-
touchcancel: { defaultInit: {} },
|
|
23
|
-
touchend: { defaultInit: {} },
|
|
24
|
-
longpress: { defaultInit: {} },
|
|
32
|
+
tap: { defaultInit: { bubbles: true } },
|
|
33
|
+
longtap: { defaultInit: { bubbles: true } },
|
|
34
|
+
touchstart: { defaultInit: { bubbles: true } },
|
|
35
|
+
touchmove: { defaultInit: { bubbles: true } },
|
|
36
|
+
touchcancel: { defaultInit: { bubbles: true } },
|
|
37
|
+
touchend: { defaultInit: { bubbles: true } },
|
|
38
|
+
longpress: { defaultInit: { bubbles: true } },
|
|
25
39
|
// Keyboard
|
|
26
|
-
keydown: { defaultInit: {} },
|
|
27
|
-
keyup: { defaultInit: {} },
|
|
40
|
+
keydown: { defaultInit: { bubbles: true } },
|
|
41
|
+
keyup: { defaultInit: { bubbles: true } },
|
|
28
42
|
// Mouse
|
|
29
|
-
mousedown: { defaultInit: {} },
|
|
30
|
-
mouseup: { defaultInit: {} },
|
|
31
|
-
mousemove: { defaultInit: {} },
|
|
32
|
-
mouseclick: { defaultInit: {} },
|
|
33
|
-
mousedblclick: { defaultInit: {} },
|
|
34
|
-
mouselongpress: { defaultInit: {} },
|
|
35
|
-
wheel: { defaultInit: {} },
|
|
43
|
+
mousedown: { defaultInit: { bubbles: true } },
|
|
44
|
+
mouseup: { defaultInit: { bubbles: true } },
|
|
45
|
+
mousemove: { defaultInit: { bubbles: true } },
|
|
46
|
+
mouseclick: { defaultInit: { bubbles: true } },
|
|
47
|
+
mousedblclick: { defaultInit: { bubbles: true } },
|
|
48
|
+
mouselongpress: { defaultInit: { bubbles: true } },
|
|
49
|
+
wheel: { defaultInit: { bubbles: true } },
|
|
36
50
|
// Scroll / viewport
|
|
37
51
|
scroll: { defaultInit: {} },
|
|
38
52
|
scrollend: { defaultInit: {} },
|
|
@@ -57,23 +71,113 @@ export const eventMap = {
|
|
|
57
71
|
transitioncancel: { defaultInit: {} },
|
|
58
72
|
animationend: { defaultInit: {} },
|
|
59
73
|
};
|
|
74
|
+
/**
|
|
75
|
+
* The kinds of handler Lynx runs on the way down the response chain to the
|
|
76
|
+
* target (capture) and on the way back up (bubble). An element has at most
|
|
77
|
+
* one handler per event name, of any kind (see the runtime's
|
|
78
|
+
* combinedEventType), so the order within a phase only matters to a test
|
|
79
|
+
* that registers more.
|
|
80
|
+
*/
|
|
81
|
+
const CAPTURE_PHASE = ['capture-bindEvent', 'capture-catchEvent'];
|
|
82
|
+
const BUBBLE_PHASE = ['bindEvent', 'catchEvent'];
|
|
83
|
+
/**
|
|
84
|
+
* The handler __AddEvent registered on `element` for the event `type:name`,
|
|
85
|
+
* if any. The testing environment keeps an element's handlers in an
|
|
86
|
+
* `eventMap` keyed that way, each also listening for the DOM event of that
|
|
87
|
+
* name (setup.ts's __GetEvents reads the same map).
|
|
88
|
+
*/
|
|
89
|
+
const handlerOf = (element, type, name) => element.eventMap?.[`${type}:${name}`];
|
|
90
|
+
/**
|
|
91
|
+
* The event a handler of `type` receives: the `<type>:<name>` DOM event that
|
|
92
|
+
* reaches it when fired on its own, with the Lynx properties and the test's
|
|
93
|
+
* init on it. Standard EventInit keys are read-only on constructed events,
|
|
94
|
+
* so they're passed to the constructor and not assigned.
|
|
95
|
+
*/
|
|
96
|
+
const createLynxEvent = (elem, type, name, init) => {
|
|
97
|
+
const eventInit = { eventType: type, eventName: name, ...init };
|
|
98
|
+
const event = createEvent(`${type}:${name}`, elem, eventInit);
|
|
99
|
+
Object.assign(event, Object.fromEntries(Object.entries(eventInit).filter(([k]) => !EVENT_INIT_KEYS.has(k))));
|
|
100
|
+
return event;
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Runs the handlers for the event `name` fired at `target`, as Lynx's
|
|
104
|
+
* TouchEventHandler::HandleEventInternal does on a device. An event that
|
|
105
|
+
* bubbles goes down from the page to the target, running `capture-bind` and
|
|
106
|
+
* `capture-catch` handlers, then back up, running `bind` and `catch` ones. A
|
|
107
|
+
* `catch` handler of either phase runs and stops the event there. Any other
|
|
108
|
+
* event runs the target's own `bind` or `catch` handler and nothing more.
|
|
109
|
+
*
|
|
110
|
+
* It calls the handlers rather than dispatching one DOM event, because the
|
|
111
|
+
* testing environment listens for a separate DOM event per kind
|
|
112
|
+
* (`bindEvent:tap`, `catchEvent:tap`, …): a bubbling `bindEvent:tap` would
|
|
113
|
+
* pass a `(catchtap)` ancestor by, and reach the handlers above it, where a
|
|
114
|
+
* device stops. Returns false if a handler canceled its event, as
|
|
115
|
+
* dispatchEvent does.
|
|
116
|
+
*/
|
|
117
|
+
const deliver = (target, name, init) => {
|
|
118
|
+
// The error Testing Library gives a query that found nothing, rather than
|
|
119
|
+
// a TypeError from reading its parent.
|
|
120
|
+
if (!target) {
|
|
121
|
+
throw new Error(`Unable to fire a "${name}" event - please provide a DOM element.`);
|
|
122
|
+
}
|
|
123
|
+
const chain = [target];
|
|
124
|
+
if (init['bubbles']) {
|
|
125
|
+
for (let el = target.parentElement; el; el = el.parentElement) {
|
|
126
|
+
chain.push(el);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
let notCanceled = true;
|
|
130
|
+
/**
|
|
131
|
+
* Runs each element's handlers of `types` in turn. Returns true once a
|
|
132
|
+
* catch handler stops the event.
|
|
133
|
+
*/
|
|
134
|
+
const runPhase = (elements, types) => {
|
|
135
|
+
for (const element of elements) {
|
|
136
|
+
let caught = false;
|
|
137
|
+
for (const type of types) {
|
|
138
|
+
const handler = handlerOf(element, type, name);
|
|
139
|
+
if (!handler)
|
|
140
|
+
continue;
|
|
141
|
+
const event = createLynxEvent(target, type, name, init);
|
|
142
|
+
handler(event);
|
|
143
|
+
notCanceled &&= !event.defaultPrevented;
|
|
144
|
+
caught ||= type.endsWith('catchEvent');
|
|
145
|
+
}
|
|
146
|
+
if (caught)
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
};
|
|
151
|
+
// Lynx has no capture phase for the events that stay on their target.
|
|
152
|
+
const captured = !!init['bubbles'] && runPhase([...chain].reverse(), CAPTURE_PHASE);
|
|
153
|
+
if (!captured)
|
|
154
|
+
runPhase(chain, BUBBLE_PHASE);
|
|
155
|
+
return notCanceled;
|
|
156
|
+
};
|
|
60
157
|
export const fireEvent = ((elem, event) => {
|
|
61
158
|
return domFireEvent(elem, event);
|
|
62
159
|
});
|
|
63
160
|
for (const key of Object.keys(eventMap)) {
|
|
64
161
|
fireEvent[key] = (elem, init) => {
|
|
65
|
-
const eventType = init
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
162
|
+
const { eventType, ...rest } = init ?? {};
|
|
163
|
+
if (eventType === undefined) {
|
|
164
|
+
const eventInit = { ...eventMap[key].defaultInit, ...rest };
|
|
165
|
+
// Run through Testing Library's eventWrapper, as its fireEvent runs a
|
|
166
|
+
// dispatch, for a test that configures one.
|
|
167
|
+
let notCanceled = true;
|
|
168
|
+
getConfig().eventWrapper(() => {
|
|
169
|
+
notCanceled = deliver(elem, key, eventInit);
|
|
170
|
+
});
|
|
171
|
+
return notCanceled;
|
|
172
|
+
}
|
|
173
|
+
// An explicit eventType fires the one `<eventType>:<name>` DOM event at
|
|
174
|
+
// elem: it reaches elem's handler of that kind, or a listener the test
|
|
175
|
+
// added for it, and goes no further unless init asks it to bubble.
|
|
176
|
+
const event = createLynxEvent(elem, String(eventType), key, {
|
|
69
177
|
...eventMap[key].defaultInit,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// Assign Lynx-specific custom properties (eventType, eventName, etc.).
|
|
74
|
-
// Standard EventInit keys are read-only on constructed events so we skip them.
|
|
75
|
-
const customProps = Object.fromEntries(Object.entries(eventInit).filter(([k]) => !EVENT_INIT_KEYS.has(k)));
|
|
76
|
-
Object.assign(event, customProps);
|
|
178
|
+
bubbles: false,
|
|
179
|
+
...rest,
|
|
180
|
+
});
|
|
77
181
|
return domFireEvent(elem, event);
|
|
78
182
|
};
|
|
79
183
|
}
|
package/package.json
CHANGED