wix / Detox

Gray box end-to-end testing and automation framework for mobile apps
https://wix.github.io/Detox/
MIT License
11.25k stars 1.92k forks source link

toHaveToogleValue() fails with RN73 #4639

Open d4vidi opened 4 days ago

d4vidi commented 4 days ago

What happened?

A common matcher such as:

await expect(element(by.id('item.toggle'))).toHaveToggleValue(false);

seems to have stopped working when upgrading from RN 71 to 73. It introduces the following error:

Test Failed: Failed expectation: TOHAVEVALUE(value == “0”) WITH MATCHER(id == “item.toggle”)

What was the expected behaviour?

No response

Was it tested on latest Detox?

Did your test throw out a timeout?

Help us reproduce this issue!

Should repro on any screen with a toggle coming from react-native-ui-lib.

In what environment did this happen?

Detox version: React Native version: Has Fabric (React Native's new rendering system) enabled: (yes/no) Node version: Device model: iOS version: macOS version: Xcode version: Test-runner (select one): jest / other

Detox logs

Detox logs ``` paste logs here! ```

Device logs

Device logs ``` paste your device.log here! ```

More data, please!

No response

d4vidi commented 4 days ago

Heavy debugging shows that for toggles based on non-switch components (as in react-native-ui-lib), i.e. which rather utilize RN's accessibility props, the issue is reproduced. For example:

      <TouchableOpacity {...this.getAccessibilityProps()} {...props} onPress={this.onPress}>
        {this.renderToggle()}
      </TouchableOpacity>

// where getAccessibilityProps is something like:
getAccessibilityProp() {
    return {
      accessible: true,
      accessibilityRole: 'switch',
      accessibilityState: {
        disabled,
        checked: value ? 'checked' : 'unchecked'
      },
      accessibilityValue: {
        text: value ? '1' : '0'
      }
    };

}

Starting RN73 (or 72), the native accessibility value is now determined based on both accessibilityValue and accessibilityRole. Up to RN71 it used to be set based on accessibilityValue alone. Namely, for 'accessibilityRole=switch' and 'accessibilityValue=1', this is the change that appears to have been introduced:

RN < 73:
iOS accessibility value = '1'

RN ≥ 73:
iOS accessibility value = 'switch, 1'
d4vidi commented 4 days ago

Workaround

Resort to jest-expecting based on getAttributes().value, for example:

const attributes = await element(...).getAttributes();
jestExpect(attributes.value).toEqual('swtich, 0');

Solution

  1. (Best) accessibilityValue doesn't seem to be manipulated by RN when using the official RN Switch component. Need to have react-native-ui-lib either use it (instead of relying on a proprietary implementation) or at least better mimic what they are doing.
  2. Adjust detox to compare either value=<accessibilityValue> or value=<accessibilityRole, accessibilityValue>