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

iOS: perform actions on UIPickerView #605

Merged
merged 21 commits into from
Mar 26, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion detox/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"eslint.enable": false
"eslint.enable": false,
"git.ignoreLimitWarning": true
}
10 changes: 10 additions & 0 deletions detox/src/ios/expect.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ class SwipeAction extends Action {
}
}

class ScrollColumnToValue extends Action {
constructor(column,value) {
super();
this._call = invoke.callDirectly(GreyActions.actionForSetPickerColumnToValue(column,value))
}
}

class Interaction {
async execute() {
//if (!this._call) throw new Error(`Interaction.execute cannot find a valid _call, got ${typeof this._call}`);
Expand Down Expand Up @@ -284,6 +291,9 @@ class Element {
this._selectElementWithMatcher(this._originalMatcher._avoidProblematicReactNativeElements());
return await new ActionInteraction(this, new SwipeAction(direction, speed, percentage)).execute();
}
async setColumnToValue(column,value) {
return await new ActionInteraction(this, new ScrollColumnToValue(column, value)).execute();
}
}

class Expect {}
Expand Down
17 changes: 17 additions & 0 deletions detox/test/e2e/p-datePicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
describe('DatePicker', () => {
beforeEach(async () => {
await device.reloadReactNative();
});

beforeEach(async () => {
await element(by.text('DatePicker')).tap();
});

it('check and scroll datePicker', async () => {
await expect(element(by.type('UIPickerView'))).toBeVisible();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why by type and not by id? Does it not work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UIPickerView have not accessibility ID, testID = {'CustomDatePicker'} need to be deleted

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a problem. If user has more than one pickers, the API will break

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UIPickerView is a UIView, so it can have an accessibility ID. Are you seeing that UIDatePicker does not forward that ID?

Copy link
Contributor Author

@DmitryPonomarenko DmitryPonomarenko Mar 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked that UI element via AccessebilityInspector (from Xcode Instruments), and now I found only one way to get element by type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't work on android

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know. We want to hone down iOS support first, then we will implement Android as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test should be wrapped with if(iOS).

await expect(element(by.type('UIPickerView')).setColumnToValue(1,"6"));
await expect(element(by.type('UIPickerView')).setColumnToValue(2,"34"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expect should not be on actions.
You should have a label and see that the correct value is shown there.

Should be something like

await element(by.type('UIPickerView')).setColumnToValue(2,"34");
await expect(element(by.id('time'))).toHaveText('6:34');

});

});

64 changes: 62 additions & 2 deletions detox/test/ios/example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,34 @@
remoteGlobalIDString = 58B5119B1A9E6C1200147676;
remoteInfo = RCTText;
};
D58447AF204E9C6000248543 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = EBF21BDC1FC498900052F4D5;
remoteInfo = jsinspector;
};
D58447B1204E9C6000248543 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = EBF21BFA1FC4989A0052F4D5;
remoteInfo = "jsinspector-tvOS";
};
D58447B3204E9C6000248543 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F3131F5F2E4B0010BF04;
remoteInfo = privatedata;
};
D58447B5204E9C6000248543 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04;
remoteInfo = "privatedata-tvOS";
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
Expand Down Expand Up @@ -491,10 +519,14 @@
39A34C5D1E30ED3600BEBB59 /* libcxxreact.a */,
39A34C5F1E30ED3600BEBB59 /* libjschelpers.a */,
39A34C611E30ED3600BEBB59 /* libjschelpers.a */,
D58447B0204E9C6000248543 /* libjsinspector.a */,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this? What will happen if old RN is used? In CI, we have an RN matrix that changes RN versions on the fly. Currently we are testing RN 51 and 53.3

D58447B2204E9C6000248543 /* libjsinspector-tvOS.a */,
4644B8651F897583003223D4 /* libthird-party.a */,
4644B8671F897583003223D4 /* libthird-party.a */,
4644B8691F897583003223D4 /* libdouble-conversion.a */,
4644B86B1F897583003223D4 /* libdouble-conversion.a */,
D58447B4204E9C6000248543 /* libprivatedata.a */,
D58447B6204E9C6000248543 /* libprivatedata-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -972,6 +1004,34 @@
remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
D58447B0204E9C6000248543 /* libjsinspector.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjsinspector.a;
remoteRef = D58447AF204E9C6000248543 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
D58447B2204E9C6000248543 /* libjsinspector-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libjsinspector-tvOS.a";
remoteRef = D58447B1204E9C6000248543 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
D58447B4204E9C6000248543 /* libprivatedata.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libprivatedata.a;
remoteRef = D58447B3204E9C6000248543 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
D58447B6204E9C6000248543 /* libprivatedata-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libprivatedata-tvOS.a";
remoteRef = D58447B5204E9C6000248543 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */

/* Begin PBXResourcesBuildPhase section */
Expand Down Expand Up @@ -1085,7 +1145,7 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.example;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change necessary?

PRODUCT_NAME = example;
};
name = Debug;
Expand All @@ -1102,7 +1162,7 @@
"-ObjC",
"-lc++",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.example;
PRODUCT_NAME = example;
};
name = Release;
Expand Down
12 changes: 6 additions & 6 deletions detox/test/ios/example/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,12 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCalendarsUsageDescription</key>
<string></string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>WKBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
Expand All @@ -58,9 +56,11 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSCalendarsUsageDescription</key>
<string></string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>WKBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
</dict>
</plist>
33 changes: 33 additions & 0 deletions detox/test/src/Screens/DatePickerScreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
DatePickerIOS
} from 'react-native';

export default class DatePickerScreen extends Component {

constructor(props) {
super(props);
}

render() {
return (
<View style={{flex: 1, paddingTop: 20, justifyContent: 'center', alignItems: 'center'}}>
<DatePickerIOS
style = {styles.datePicker}
date = {new Date()}
/>
</View>
);
}
}

const styles = StyleSheet.create({
datePicker: {
width:'100%',
height:200,
backgroundColor:'green',
}
});
4 changes: 3 additions & 1 deletion detox/test/src/Screens/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Permissions from './Permissions';
import NetworkScreen from './NetworkScreen';
import AnimationsScreen from './AnimationsScreen';
import LocationScreen from './LocationScreen';
import DatePickerScreen from './DatePickerScreen'

export {
SanityScreen,
Expand All @@ -25,5 +26,6 @@ export {
Permissions,
NetworkScreen,
AnimationsScreen,
LocationScreen
LocationScreen,
DatePickerScreen
};
1 change: 1 addition & 0 deletions detox/test/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class example extends Component {
{this.renderScreenButton('Network', Screens.NetworkScreen)}
{this.renderScreenButton('Animations', Screens.AnimationsScreen)}
{this.renderScreenButton('Location', Screens.LocationScreen)}
{this.renderScreenButton('DatePicker', Screens.DatePickerScreen)}
{this.renderButton('Crash', () => {throw new Error('Simulated Crash')})}
</View>
);
Expand Down