-
Notifications
You must be signed in to change notification settings - Fork 25.1k
Add detox tests for Switch #22470
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
Add detox tests for Switch #22470
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| /** | ||
| * Copyright (c) Facebook, Inc. and its affiliates. | ||
| * | ||
| * This source code is licensed under the MIT license found in the | ||
| * LICENSE file in the root directory of this source tree. | ||
| * | ||
| * @format | ||
| */ | ||
|
|
||
| /* global device, element, by, expect, waitFor */ | ||
|
|
||
| const jestExpect = require('expect'); | ||
|
|
||
| describe.only('Switch', () => { | ||
| beforeAll(async () => { | ||
| await element(by.id('explorer_search')).replaceText('<Switch>'); | ||
| await element(by.label('<Switch> Native boolean input')).tap(); | ||
| }); | ||
|
|
||
| afterAll(async () => { | ||
| await element(by.label('Back')).tap(); | ||
| }); | ||
|
|
||
| it('Switch that starts on should switch', async () => { | ||
| const testID = 'on-off-initial-off'; | ||
| const indicatorID = 'on-off-initial-off-indicator'; | ||
|
|
||
| await expect(element(by.id(testID))).toHaveValue('0'); | ||
| await expect(element(by.id(indicatorID))).toHaveText('Off'); | ||
| await element(by.id(testID)).tap(); | ||
| await expect(element(by.id(testID))).toHaveValue('1'); | ||
| await expect(element(by.id(indicatorID))).toHaveText('On'); | ||
| }); | ||
|
|
||
| it('Switch that starts off should switch', async () => { | ||
| const testID = 'on-off-initial-on'; | ||
| const indicatorID = 'on-off-initial-on-indicator'; | ||
|
|
||
| await expect(element(by.id(testID))).toHaveValue('1'); | ||
| await expect(element(by.id(indicatorID))).toHaveText('On'); | ||
| await element(by.id(testID)).tap(); | ||
| await expect(element(by.id(testID))).toHaveValue('0'); | ||
| await expect(element(by.id(indicatorID))).toHaveText('Off'); | ||
| }); | ||
|
|
||
| it('disabled switch should not toggle', async () => { | ||
| const onTestID = 'disabled-initial-on'; | ||
| const offTestID = 'disabled-initial-off'; | ||
| const onIndicatorID = 'disabled-initial-on-indicator'; | ||
| const offIndicatorID = 'disabled-initial-off-indicator'; | ||
|
|
||
| await expect(element(by.id(onTestID))).toHaveValue('1'); | ||
| await expect(element(by.id(onIndicatorID))).toHaveText('On'); | ||
|
|
||
| try { | ||
| await element(by.id(onTestID)).tap(); | ||
| throw new Error('Does not match'); | ||
| } catch (err) { | ||
| jestExpect(err.message.message).toEqual( | ||
| jestExpect.stringContaining( | ||
| 'Cannot perform action due to constraint(s) failure', | ||
| ), | ||
| ); | ||
| } | ||
| await expect(element(by.id(onTestID))).toHaveValue('1'); | ||
| await expect(element(by.id(onIndicatorID))).toHaveText('On'); | ||
|
|
||
| await expect(element(by.id(offTestID))).toHaveValue('0'); | ||
| await expect(element(by.id(offIndicatorID))).toHaveText('Off'); | ||
| try { | ||
| await element(by.id(offTestID)).tap(); | ||
| throw new Error('Does not match'); | ||
| } catch (err) { | ||
| jestExpect(err.message.message).toEqual( | ||
| jestExpect.stringContaining( | ||
| 'Cannot perform action due to constraint(s) failure', | ||
| ), | ||
| ); | ||
| } | ||
| await expect(element(by.id(offTestID))).toHaveValue('0'); | ||
| await expect(element(by.id(offIndicatorID))).toHaveText('Off'); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,10 +11,37 @@ | |
| 'use strict'; | ||
|
|
||
| const React = require('react'); | ||
| const ReactNative = require('react-native'); | ||
| const {Switch, Text, View} = ReactNative; | ||
| const {Switch, Text, View} = require('react-native'); | ||
|
|
||
| class BasicSwitchExample extends React.Component<{}, $FlowFixMeState> { | ||
| type OnOffIndicatorProps = $ReadOnly<{|on: boolean, testID: string|}>; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm thinking I'll end up pulling these out to use on more tests but I don't want to overabstract until we know they are needed |
||
| function OnOffIndicator({on, testID}: OnOffIndicatorProps) { | ||
| return <Text testID={testID}>{on ? 'On' : 'Off'}</Text>; | ||
| } | ||
|
|
||
| type ExampleRowProps = $ReadOnly<{|children: React.Node|}>; | ||
| function ExampleRow({children}: ExampleRowProps) { | ||
| return ( | ||
| <View | ||
| style={{ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. react-native/no-inline-styles: Inline style: { flexDirection: 'row', |
||
| flexDirection: 'row', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'center', | ||
| marginBottom: 10, | ||
| }}> | ||
| {children} | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| type SimpleSwitchExampleState = $ReadOnly<{| | ||
| trueSwitchIsOn: boolean, | ||
| falseSwitchIsOn: boolean, | ||
| |}>; | ||
|
|
||
| class BasicSwitchExample extends React.Component< | ||
| {||}, | ||
| SimpleSwitchExampleState, | ||
| > { | ||
| state = { | ||
| trueSwitchIsOn: true, | ||
| falseSwitchIsOn: false, | ||
|
|
@@ -23,26 +50,72 @@ class BasicSwitchExample extends React.Component<{}, $FlowFixMeState> { | |
| render() { | ||
| return ( | ||
| <View> | ||
| <Switch | ||
| onValueChange={value => this.setState({falseSwitchIsOn: value})} | ||
| style={{marginBottom: 10}} | ||
| value={this.state.falseSwitchIsOn} | ||
| /> | ||
| <Switch | ||
| onValueChange={value => this.setState({trueSwitchIsOn: value})} | ||
| value={this.state.trueSwitchIsOn} | ||
| /> | ||
| <ExampleRow> | ||
| <Switch | ||
| testID="on-off-initial-off" | ||
| onValueChange={value => this.setState({falseSwitchIsOn: value})} | ||
| value={this.state.falseSwitchIsOn} | ||
| /> | ||
| <OnOffIndicator | ||
| on={this.state.falseSwitchIsOn} | ||
| testID="on-off-initial-off-indicator" | ||
| /> | ||
| </ExampleRow> | ||
| <ExampleRow> | ||
| <Switch | ||
| testID="on-off-initial-on" | ||
| onValueChange={value => this.setState({trueSwitchIsOn: value})} | ||
| value={this.state.trueSwitchIsOn} | ||
| /> | ||
| <OnOffIndicator | ||
| on={this.state.trueSwitchIsOn} | ||
| testID="on-off-initial-on-indicator" | ||
| /> | ||
| </ExampleRow> | ||
| </View> | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| class DisabledSwitchExample extends React.Component<{}> { | ||
| class DisabledSwitchExample extends React.Component< | ||
| {||}, | ||
| SimpleSwitchExampleState, | ||
| > { | ||
| state = { | ||
| trueSwitchIsOn: true, | ||
| falseSwitchIsOn: false, | ||
| }; | ||
|
|
||
| render() { | ||
| return ( | ||
| <View> | ||
| <Switch disabled={true} style={{marginBottom: 10}} value={true} /> | ||
| <Switch disabled={true} value={false} /> | ||
| <ExampleRow> | ||
| <Switch | ||
| testID="disabled-initial-off" | ||
| disabled={true} | ||
| onValueChange={value => this.setState({falseSwitchIsOn: value})} | ||
| value={this.state.falseSwitchIsOn} | ||
| /> | ||
|
|
||
| <OnOffIndicator | ||
| on={this.state.falseSwitchIsOn} | ||
| testID="disabled-initial-off-indicator" | ||
| /> | ||
| </ExampleRow> | ||
|
|
||
| <ExampleRow> | ||
| <Switch | ||
| testID="disabled-initial-on" | ||
| disabled={true} | ||
| onValueChange={value => this.setState({trueSwitchIsOn: value})} | ||
| value={this.state.trueSwitchIsOn} | ||
| /> | ||
|
|
||
| <OnOffIndicator | ||
| on={this.state.trueSwitchIsOn} | ||
| testID="disabled-initial-on-indicator" | ||
| /> | ||
| </ExampleRow> | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels gross. When tapping on an element that is disabled, EarlGrey throws the following error:
any ideas of a cleaner way to handle this case @rotemmiz?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should definitely have better error logs, but what do you mean by cleaner way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One example of something cleaner would be using jest's expect
.toThrow. In this example it would look like this:However, the error we get back is actually an Error object, with the message field set to an Error, with that's message field set to the long string, making it impossible to assert as if it was a normal error.