jest-native icon indicating copy to clipboard operation
jest-native copied to clipboard

.toBeDisabled() buggy with RN 0.62

Open mtt87 opened this issue 5 years ago • 12 comments
trafficstars

  • react-native or expo: 0.62.1
  • @testing-library/react-native version: 3.1.0
  • react-native version: 0.62.1
  • node version: 12.16.1

Latest version of RN deprecated accessibilityStates in favor of accessibilityState https://reactnative.dev/blog/2020/03/26/version-0.62#breaking-changes

Seems like now it's an object https://github.com/facebook/react-native/commit/7b35f427fd66cb0f36921b992095fe5b3c14d8b9

I suspect we need to change it here https://github.com/testing-library/jest-native/blob/77ca4408081e3371aeffe739ad12928c9119ff95/src/to-be-disabled.js#L28

It's quite weird that in my codebase everything works fine except 1 use case where I have something like this

<TouchableOpacity disabled testID="button">
  <Button disabled>

And when I check it fails, no matter if the received output from jest seems to be correct and it has the disabled prop and it's true

{
  "disabled": true,
  "testID": "button",
  "children": <Button>
}

Can you help us fix this issue by submitting a pull request?

I checked the codebase and there is an intense use of ramda which hurts my eyes and find it quite difficult to work with, but I'll try to make a PR 😄

mtt87 avatar Apr 06 '20 16:04 mtt87

I think I've found the issue

<TouchableOpacity testID="buttonSendLink" disabled={true}

Then checking

function isElementDisabled(element) {
  const propDisabled = path(['props', 'disabled'], element);
  // propDisabled = true

  const stateDisabled = compose(
    includes('disabled'),
    defaultTo([]),
    path(['props', 'accessibilityStates']),
  )(element);
  // stateDisabled = false (this has to change btw)

  return Boolean(DISABLE_TYPES.includes(getType(element)) && (propDisabled || stateDisabled));
}

The issue is with DISABLE_TYPES.includes(getType(element)

Because getType(element) returns

{ '$$typeof': Symbol(react.forward_ref), render: [Function] }

Something might have changed in the TouchableOpacity export in React Native and now that's what happens

mtt87 avatar Apr 08 '20 14:04 mtt87

Yes seems to be related https://github.com/facebook/react-native/issues/27721

mtt87 avatar Apr 08 '20 14:04 mtt87

Is there any update on this? Or a good workaround? I seem to be experiencing the same problem with the Pressable component on 0.63.2.

dannyhw avatar Jul 27 '20 20:07 dannyhw

About the new prop accessibilityState in favor of AccessibilityStates I have an open PR #30. I didn't have the chance to look at this, though.

brunohkbx avatar Jul 28 '20 14:07 brunohkbx

Seems like the only workaround for this one is mocking TouchableOpacity, TouchableHighlight, and Pressable.

Something like this: jest.mock('react-native/Libraries/Components/Touchable/TouchableOpacity', () => 'TouchableOpacity');

Do you guys think it would be a good solution to doing this mock on our side :thinking: ? @thymikee thoughts?

brunohkbx avatar Jul 29 '20 23:07 brunohkbx

I'd like to avoid custom mocks other than the one provided by the core. Does it work with @testing-library/[email protected]? It's a prerelease sourced from react-native-testing-library. Here's the migration guide: https://github.com/callstack/react-native-testing-library/blob/7.x/website/docs/MigrationV7.md#guide-for-testing-libraryreact-native-users

thymikee avatar Jul 30 '20 07:07 thymikee

It probably shouldn't work. The issue here is that RN exported TouchableHighlight and TouchableOpacity with React.forwardRef without a displayName.

https://github.com/facebook/react-native/blob/master/Libraries/Components/Touchable/TouchableHighlight.js#L382 https://github.com/facebook/react-native/blob/master/Libraries/Components/Touchable/TouchableOpacity.js#L301

The matcher to-be-disabled is checking for one of those components:

const DISABLE_TYPES = [
  'Button',
  'Slider',
  'Switch',
  'Text',
  'TouchableHighlight',
  'TouchableOpacity',
  'TouchableWithoutFeedback',
  'View',
  'TextInput',
];

and since forwardRef does not has a displayName, it does not match.

brunohkbx avatar Jul 30 '20 11:07 brunohkbx

Looks like it's fixed on master: https://github.com/facebook/react-native/commit/4b935ae95f09e4a1eb1e5ac8089eb258222a0f8b

thymikee avatar Jul 30 '20 11:07 thymikee

It turns out this commit didn't fix :disappointed: . Touchables aren't being mocked on RN setup.js So I opened a PR to fix that: https://github.com/facebook/react-native/pull/29531

brunohkbx avatar Jul 30 '20 12:07 brunohkbx

@thymikee @mdjastrzebski as we discussed on #36, what do you guys think about also removing this DISABLE_TYPES from this matcher? It has the same purpose as the VALID_ELEMENTS.

brunohkbx avatar Sep 23 '20 13:09 brunohkbx

@brunohkbx We definitely should update the current code, however just removing DISABLE_TYPES will probably not be enough.

Disabled element checks in RNTL have their own logic, which is different than just checking disabled prop. It follows RN code and uses View.onStartShouldSetResponder prop. So most probably we should use the same logic here.

See: https://github.com/callstack/react-native-testing-library/pull/460

As a separate case we should think whether TextInput editable=false is a disabled element or not.

mdjastrzebski avatar Sep 24 '20 08:09 mdjastrzebski

@mdjastrzebski would you mind reviewing it? #50

brunohkbx avatar Apr 06 '21 19:04 brunohkbx

Closing as stale.

mdjastrzebski avatar Nov 04 '22 08:11 mdjastrzebski