Skip to content

Commit

Permalink
Merge branch 'master' into devtools-v4-merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn committed Aug 27, 2019
2 parents fb31678 + 4ef2696 commit 33d439f
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
20 changes: 20 additions & 0 deletions packages/react-events/src/dom/Press.js
Expand Up @@ -476,6 +476,19 @@ function handleStopPropagation(
}
}

// After some investigation work, screen reader virtual
// clicks (NVDA, Jaws, VoiceOver) do not have co-ords associated with the click
// event and "detail" is always 0 (where normal clicks are > 0)
function isScreenReaderVirtualClick(nativeEvent): boolean {
return (
nativeEvent.detail === 0 &&
nativeEvent.screenX === 0 &&
nativeEvent.screenY === 0 &&
nativeEvent.clientX === 0 &&
nativeEvent.clientY === 0
);
}

function targetIsDocument(target: null | Node): boolean {
// When target is null, it is the root
return target === null || target.nodeType === 9;
Expand Down Expand Up @@ -617,6 +630,13 @@ const pressResponderImpl = {
if (state.shouldPreventClick) {
nativeEvent.preventDefault();
}
const onPress = props.onPress;
if (isFunction(onPress) && isScreenReaderVirtualClick(nativeEvent)) {
state.pointerType = 'keyboard';
state.pressTarget = event.responderTarget;
dispatchEvent(event, onPress, context, state, 'press', DiscreteEvent);
}
break;
}
}
Expand Down
12 changes: 12 additions & 0 deletions packages/react-events/src/dom/__tests__/Press-test.internal.js
Expand Up @@ -420,6 +420,18 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
innerTarget.pointerup({pointerType: 'mouse'});
expect(onPress).toBeCalled();
});

it('is called once after virtual screen reader "click" event', () => {
const target = createEventTarget(ref.current);
target.virtualclick();
expect(onPress).toHaveBeenCalledTimes(1);
expect(onPress).toHaveBeenCalledWith(
expect.objectContaining({
pointerType: 'keyboard',
type: 'press',
}),
);
});
});

describe('onPressMove', () => {
Expand Down
28 changes: 17 additions & 11 deletions packages/react-events/src/dom/testing-library/domEvents.js
Expand Up @@ -170,28 +170,30 @@ function createMouseEvent(
x = 0,
y = 0,
} = {},
virtual = false,
) {
const modifierState = {altKey, ctrlKey, metaKey, shiftKey};

return createEvent(type, {
altKey,
buttons,
clientX: x,
clientY: y,
clientX: virtual ? 0 : x,
clientY: virtual ? 0 : y,
ctrlKey,
detail: virtual ? 0 : 1,
getModifierState(keyArg) {
createGetModifierState(keyArg, modifierState);
},
metaKey,
movementX,
movementY,
offsetX,
offsetY,
pageX: pageX || x,
pageY: pageY || y,
movementX: virtual ? 0 : movementX,
movementY: virtual ? 0 : movementY,
offsetX: virtual ? 0 : offsetX,
offsetY: virtual ? 0 : offsetY,
pageX: virtual ? 0 : pageX || x,
pageY: virtual ? 0 : pageY || y,
preventDefault,
screenX: x,
screenY: y + defaultBrowserChromeSize,
screenX: virtual ? 0 : x,
screenY: virtual ? 0 : y + defaultBrowserChromeSize,
shiftKey,
});
}
Expand Down Expand Up @@ -251,7 +253,11 @@ export function blur({relatedTarget} = {}) {
}

export function click(payload) {
return createMouseEvent('click', payload);
return createMouseEvent('click', payload, false);
}

export function virtualclick(payload) {
return createMouseEvent('click', payload, true);
}

export function contextmenu(payload) {
Expand Down
3 changes: 3 additions & 0 deletions packages/react-events/src/dom/testing-library/index.js
Expand Up @@ -44,6 +44,9 @@ const createEventTarget = node => ({
keyup(payload) {
node.dispatchEvent(domEvents.keyup(payload));
},
virtualclick(payload) {
node.dispatchEvent(domEvents.virtualclick(payload));
},
scroll(payload) {
node.dispatchEvent(domEvents.scroll(payload));
},
Expand Down

0 comments on commit 33d439f

Please sign in to comment.