Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to test isFocused on TextInput #276

Closed
Eldjotnar opened this issue Apr 14, 2020 · 5 comments
Closed

Unable to test isFocused on TextInput #276

Eldjotnar opened this issue Apr 14, 2020 · 5 comments
Labels
question Further information is requested

Comments

@Eldjotnar
Copy link

Ask your Question

I'm attempting to test the native methods of TextInput, but am unable to test isFocused or clear, but focus and blur work fine.

My test file:

// Sample.test.js
import React, { createRef } from 'react';
import { render } from 'react-native-testing-library';
import { TextInput } from 'react-native';

describe('@input: native methods', () => {
  it('* blur', () => {
    const componentRef = createRef();
    render(<TextInput ref={componentRef} />);

    expect(componentRef.current?.blur).toBeTruthy();
  });

  it('* isFocused', () => {
    const componentRef = createRef();
    render(<TextInput ref={componentRef} />);

    expect(componentRef.current?.isFocused).toBeTruthy();
  });
});

* blur passes, but * isFocused fails:

expect(received).toBeTruthy()

    Received: undefined

      15 |     render(<TextInput ref={componentRef} />);
      16 |
    > 17 |     expect(componentRef.current?.isFocused).toBeTruthy();
         |                                             ^
      18 |   });
      19 | });
      20 |

package.json has:

"dependencies": {
    "@react-native-community/masked-view": "^0.1.7",
    "react": "16.11.0",
    "react-dom": "16.11.0",
    "react-is": "^16.8",
    "react-native": "0.62.1",
    "react-native-gesture-handler": "^1.6.1",
    "react-native-reanimated": "^1.7.1",
    "react-native-safe-area-context": "^0.7.3",
    "react-native-safe-area-view": "^1.0.0",
    "react-native-screens": "^2.4.0",
    "styled-components": "^5.0.1",
    "styled-system": "^5.1.5"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2",
    "@commitlint/cli": "^8.3.5",
    "@commitlint/config-conventional": "^8.3.4",
    "@react-native-community/eslint-config": "^1.0.0",
    "@types/jest": "^24.0.24",
    "@types/react-native": "^0.62.0",
    "@types/react-test-renderer": "16.9.2",
    "@types/styled-components": "^5.0.1",
    "@types/styled-system": "^5.1.9",
    "@typescript-eslint/eslint-plugin": "^2.25.0",
    "@typescript-eslint/parser": "^2.25.0",
    "babel-jest": "^24.9.0",
    "babel-plugin-styled-components": "^1.10.7",
    "concurrently": "^5.1.0",
    "eslint": "^6.5.1",
    "eslint-import-resolver-typescript": "^2.0.0",
    "eslint-plugin-import": "^2.20.2",
    "husky": "^4.2.3",
    "jest": "^24.9.0",
    "lint-staged": "^10.1.2",
    "metro-react-native-babel-preset": "^0.58.0",
    "prettier": "^2.0.2",
    "react-native-testing-library": "^1.13.0",
    "react-test-renderer": "^16.13.1",
    "typescript": "^3.8.3"
  }

Any ideas what's going on?

@Eldjotnar Eldjotnar added the question Further information is requested label Apr 14, 2020
@thymikee
Copy link
Member

What happens if you console.log(componentRef.current)?

@Eldjotnar
Copy link
Author

Component {
      props:
       { editable: true,
         fontSize: 'md',
         px: 4,
         height: 10,
         rounded: 'md',
         style: [ [Object] ],
         allowFontScaling: true,
         rejectResponderTermination: true,
         underlineColorAndroid: 'transparent' },
      context: {},
      refs: {},
      updater:
       { isMounted: [Function: isMounted],
         enqueueSetState: [Function: enqueueSetState],
         enqueueReplaceState: [Function: enqueueReplaceState],
         enqueueForceUpdate: [Function: enqueueForceUpdate] },
      _reactInternalFiber:
       FiberNode {
         tag: 1,
         key: null,
         elementType:
          { [Function: Component]
            displayName: 'Component',
            '$$typeof': Symbol(react.forward_ref),
            render: [Function: TextInput],
            defaultProps: [Object],
            propTypes: [Object],
            State: [Object] },
         type:
          { [Function: Component]
            displayName: 'Component',
            '$$typeof': Symbol(react.forward_ref),
            render: [Function: TextInput],
            defaultProps: [Object],
            propTypes: [Object],
            State: [Object] },
         stateNode: [Circular],
         return:
          FiberNode {
            tag: 9,
            key: null,
            elementType: [Object],
            type: [Object],
            stateNode: null,
            return: [FiberNode],
            child: [Circular],
            sibling: null,
            index: 0,
            ref: null,
            pendingProps: [Object],
            memoizedProps: [Object],
            updateQueue: null,
            memoizedState: null,
            dependencies: [Object],
            mode: 0,
            effectTag: 1,
            nextEffect: null,
            firstEffect: [Circular],
            lastEffect: [Circular],
            expirationTime: 0,
            childExpirationTime: 0,
            alternate: null,
            actualDuration: 0,
            actualStartTime: -1,
            selfBaseDuration: 0,
            treeBaseDuration: 0,
            _debugID: 31,
            _debugIsCurrentlyTiming: false,
            _debugSource: null,
            _debugOwner: [FiberNode],
            _debugNeedsRemount: false,
            _debugHookTypes: null },
         child:
          FiberNode {
            tag: 5,
            key: null,
            elementType: 'TextInput',
            type: 'TextInput',
            stateNode: [Object],
            return: [Circular],
            child: null,
            sibling: null,
            index: 0,
            ref: null,
            pendingProps: [Object],
            memoizedProps: [Object],
            updateQueue: null,
            memoizedState: null,
            dependencies: null,
            mode: 0,
            effectTag: 0,
            nextEffect: null,
            firstEffect: null,
            lastEffect: null,
            expirationTime: 0,
            childExpirationTime: 0,
            alternate: null,
            actualDuration: 0,
            actualStartTime: -1,
            selfBaseDuration: 0,
            treeBaseDuration: 0,
            _debugID: 33,
            _debugIsCurrentlyTiming: false,
            _debugSource: null,
            _debugOwner: [Circular],
            _debugNeedsRemount: false,
            _debugHookTypes: null },
         sibling: null,
         index: 0,
         ref: { current: [Circular] },
         pendingProps:
          { editable: true,
            fontSize: 'md',
            px: 4,
            height: 10,
            rounded: 'md',
            style: [Array],
            allowFontScaling: true,
            rejectResponderTermination: true,
            underlineColorAndroid: 'transparent' },
         memoizedProps:
          { editable: true,
            fontSize: 'md',
            px: 4,
            height: 10,
            rounded: 'md',
            style: [Array],
            allowFontScaling: true,
            rejectResponderTermination: true,
            underlineColorAndroid: 'transparent' },
         updateQueue:
          { baseState: null,
            baseQueue: null,
            shared: [Object],
            effects: null },
         memoizedState: null,
         dependencies: null,
         mode: 0,
         effectTag: 129,
         nextEffect: null,
         firstEffect: null,
         lastEffect: null,
         expirationTime: 0,
         childExpirationTime: 0,
         alternate: null,
         actualDuration: 0,
         actualStartTime: -1,
         selfBaseDuration: 0,
         treeBaseDuration: 0,
         _debugID: 32,
         _debugIsCurrentlyTiming: false,
         _debugSource: null,
         _debugOwner:
          FiberNode {
            tag: 9,
            key: null,
            elementType: [Object],
            type: [Object],
            stateNode: null,
            return: [FiberNode],
            child: [Circular],
            sibling: null,
            index: 0,
            ref: null,
            pendingProps: [Object],
            memoizedProps: [Object],
            updateQueue: null,
            memoizedState: null,
            dependencies: [Object],
            mode: 0,
            effectTag: 1,
            nextEffect: null,
            firstEffect: [Circular],
            lastEffect: [Circular],
            expirationTime: 0,
            childExpirationTime: 0,
            alternate: null,
            actualDuration: 0,
            actualStartTime: -1,
            selfBaseDuration: 0,
            treeBaseDuration: 0,
            _debugID: 31,
            _debugIsCurrentlyTiming: false,
            _debugSource: null,
            _debugOwner: [FiberNode],
            _debugNeedsRemount: false,
            _debugHookTypes: null },
         _debugNeedsRemount: false,
         _debugHookTypes: null },
      _reactInternalInstance: {},
      state: null }

@thymikee
Copy link
Member

Does isFocused exist when you console / debug it directly in the component? Maybe there's something funky going on in the TextInput implementation as well? Worth checking :)

@Eldjotnar
Copy link
Author

If I use it in a regular component, it seems to work fine:

// Sample.jsx
import React, { createRef, useEffect } from 'react';
import { View, TextInput } from 'react-native';

const Sample = () => {
  const componentRef = createRef();

  useEffect(() => {
    console.log(componentRef.current?.isFocused());
  }, [componentRef]);

  return (
    <View style={{ flex: 1 }}>
      <TextInput ref={componentRef} />
    </View>
  );
};

export default Sample;

which logs false like I'd expect.

@thymikee
Copy link
Member

thymikee commented Apr 14, 2020

Mhm, so the ref state is cleared after render I suppose. It's interesting that the this function is undefined, while blur is – likely an implementation detail, not sure how it's supposed to react though.

Anyway, "focus" is something given by TextInput itself, so it's not something that you need to test (we assume it's tested by the framework). Unless, it controls some observable state of your component – then you should test what's observable, which you can do using query API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants