# All files / src/helpers accessiblity.ts

100% Statements 35/35
100% Branches 26/26
100% Functions 4/4
100% Lines 33/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110

    48x

    48x

    842x
    1x

    841x
    841x
    4784x

    4784x
    4554x
    4554x

    4784x
    42x

    4742x

    799x

    48x

    4554x
    28x

    4526x
    3x

    4523x
    2x

    4521x
    4521x

    4486x
    4486x
    2x

    4484x

    431x
    1x

    430x
    174x

    256x

    256x

     import {
      AccessibilityState,
      AccessibilityValue,
      StyleSheet,
    } from 'react-native';
    import { ReactTestInstance } from 'react-test-renderer';
    import { getConfig } from '../config';
    import { getHostSiblings } from './component-tree';

    type IsInaccessibleOptions = {
      cache?: WeakMap<ReactTestInstance, boolean>;
    };

    export const accessibilityStateKeys: (keyof AccessibilityState)[] = [
      'disabled',
      'selected',
      'checked',
      'busy',
      'expanded',
    ];

    export const accessiblityValueKeys: (keyof AccessibilityValue)[] = [
      'min',
      'max',
      'now',
      'text',
    ];

    export function isHiddenFromAccessibility(
      element: ReactTestInstance | null,
      { cache }: IsInaccessibleOptions = {}
    ): boolean {
      if (element == null) {
        return true;
      }

      let current: ReactTestInstance | null = element;
      while (current) {
        let isCurrentSubtreeInaccessible = cache?.get(current);

        if (isCurrentSubtreeInaccessible === undefined) {
          isCurrentSubtreeInaccessible = isSubtreeInaccessible(current);
          cache?.set(current, isCurrentSubtreeInaccessible);
        }

        if (isCurrentSubtreeInaccessible) {
          return true;
        }

        current = current.parent;
      }

      return false;
    }

    /** RTL-compatitibility alias for `isHiddenFromAccessibility` */
    export const isInaccessible = isHiddenFromAccessibility;

    function isSubtreeInaccessible(element: ReactTestInstance): boolean {
      // Null props can happen for React.Fragments
      if (element.props == null) {
        return false;
      }

      // iOS: accessibilityElementsHidden
      // See: https://reactnative.dev/docs/accessibility#accessibilityelementshidden-ios
      if (element.props.accessibilityElementsHidden) {
        return true;
      }

      // Android: importantForAccessibility
      // See: https://reactnative.dev/docs/accessibility#importantforaccessibility-android
      if (element.props.importantForAccessibility === 'no-hide-descendants') {
        return true;
      }

      // Note that `opacity: 0` is not treated as inaccessible on iOS
      const flatStyle = StyleSheet.flatten(element.props.style) ?? {};
      if (flatStyle.display === 'none') return true;

      // iOS: accessibilityViewIsModal
      // See: https://reactnative.dev/docs/accessibility#accessibilityviewismodal-ios
      const hostSiblings = getHostSiblings(element);
      if (hostSiblings.some((sibling) => sibling.props.accessibilityViewIsModal)) {
        return true;
      }

      return false;
    }

    export function isAccessibilityElement(
      element: ReactTestInstance | null
    ): boolean {
      if (element == null) {
        return false;
      }

      if (element.props.accessible !== undefined) {
        return element.props.accessible;
      }

      const hostComponentNames = getConfig().hostComponentNames;

      return (
        element?.type === hostComponentNames?.text ||
        element?.type === hostComponentNames?.textInput ||
        element?.type === hostComponentNames?.switch
      );
    }