diff --git a/detox/.vscode/settings.json b/detox/.vscode/settings.json index a92f73ffdf..187a47f79d 100644 --- a/detox/.vscode/settings.json +++ b/detox/.vscode/settings.json @@ -1,3 +1,4 @@ { - "eslint.enable": false + "eslint.enable": false, + "git.ignoreLimitWarning": true } \ No newline at end of file diff --git a/detox/src/ios/expect.js b/detox/src/ios/expect.js index ac7e7bd953..c1d4ecb10d 100644 --- a/detox/src/ios/expect.js +++ b/detox/src/ios/expect.js @@ -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}`); @@ -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 {} diff --git a/detox/src/ios/expect.test.js b/detox/src/ios/expect.test.js index ecb623e16e..d4430b8a30 100644 --- a/detox/src/ios/expect.test.js +++ b/detox/src/ios/expect.test.js @@ -34,6 +34,7 @@ describe('expect', async () => { it(`element by type`, async () => { await e.expect(e.element(e.by.type('test'))).toBeVisible(); + await e.element(e.by.type('UIPickerView')).setColumnToValue(1,"6"); }); it(`element by traits`, async () => { @@ -79,6 +80,8 @@ describe('expect', async () => { await e.waitFor(e.element(e.by.id('id'))).toHaveValue('value'); await e.waitFor(e.element(e.by.id('id'))).toNotHaveValue('value'); + + await e.waitFor(e.element(e.by.id('id'))).toBeVisible().whileElement(e.by.id('id2')).scroll(50, 'down'); await e.waitFor(e.element(e.by.id('id'))).toBeVisible().whileElement(e.by.id('id2')).scroll(50); }); diff --git a/detox/test/e2e/p-crash-handling.js b/detox/test/e2e/r-crash-handling.js similarity index 100% rename from detox/test/e2e/p-crash-handling.js rename to detox/test/e2e/r-crash-handling.js diff --git a/detox/test/e2e/s-datePicker.js b/detox/test/e2e/s-datePicker.js new file mode 100644 index 0000000000..3d0e4513ab --- /dev/null +++ b/detox/test/e2e/s-datePicker.js @@ -0,0 +1,17 @@ +describe('DatePicker', () => { + beforeEach(async () => { + await device.reloadReactNative(); + }); + + beforeEach(async () => { + await element(by.text('DatePicker')).tap(); + }); + + it('datePicker should trigger change handler correctly', async () => { + await element(by.type('UIPickerView')).setColumnToValue(1,"6"); + await element(by.type('UIPickerView')).setColumnToValue(2,"34"); + await expect(element(by.id("timeLabel"))).toHaveText('choosenTime is 6:34'); + }); + + }); + diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj index 44bdc447ef..3f225714ef 100644 --- a/detox/test/ios/example.xcodeproj/project.pbxproj +++ b/detox/test/ios/example.xcodeproj/project.pbxproj @@ -1145,7 +1145,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example; PRODUCT_NAME = example; }; name = Debug; @@ -1162,7 +1162,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example; PRODUCT_NAME = example; }; name = Release; diff --git a/detox/test/src/Screens/DatePickerScreen.js b/detox/test/src/Screens/DatePickerScreen.js new file mode 100644 index 0000000000..2de669c27a --- /dev/null +++ b/detox/test/src/Screens/DatePickerScreen.js @@ -0,0 +1,59 @@ +import React, { Component } from 'react'; +import { + Text, + View, + StyleSheet, + DatePickerIOS +} from 'react-native'; + +export default class DatePickerScreen extends Component { + + constructor(props) { + super(props); + this.state = { + chosenDate: new Date() + } + this._setDate = this._setDate.bind(this); + } + + _setDate(newDate) { + this.setState({ + chosenDate :newDate + }) + } + + getTime() { + minutes = this.state.chosenDate.getMinutes() + hour = this.state.chosenDate.getHours() + if( hour > 12 ) { + hour = hour - 12; + } + return `${hour}:${minutes}` + } + + render() { + return ( + + + {"choosenTime is " + this.getTime()} + + + + ); + } +} + +const styles = StyleSheet.create({ + datePicker: { + width:'100%', + height:200, + backgroundColor:'green', + }, + dateText: { + textAlign: 'center', + } +}); diff --git a/detox/test/src/Screens/index.js b/detox/test/src/Screens/index.js index 3bc9526ad3..8548420b1c 100644 --- a/detox/test/src/Screens/index.js +++ b/detox/test/src/Screens/index.js @@ -12,6 +12,7 @@ import NetworkScreen from './NetworkScreen'; import AnimationsScreen from './AnimationsScreen'; import LocationScreen from './LocationScreen'; import ShakeScreen from './ShakeScreen'; +import DatePickerScreen from './DatePickerScreen' export { SanityScreen, @@ -27,5 +28,6 @@ export { NetworkScreen, AnimationsScreen, LocationScreen, - ShakeScreen + ShakeScreen, + DatePickerScreen }; diff --git a/detox/test/src/app.js b/detox/test/src/app.js index 7ed755533c..cdb9201845 100644 --- a/detox/test/src/app.js +++ b/detox/test/src/app.js @@ -91,6 +91,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') })} diff --git a/docs/APIRef.ActionsOnElement.md b/docs/APIRef.ActionsOnElement.md index b3f465647c..c6a6fb376e 100644 --- a/docs/APIRef.ActionsOnElement.md +++ b/docs/APIRef.ActionsOnElement.md @@ -21,6 +21,7 @@ Actions are functions that emulate user behavior. They are being performed on ma - [`.scroll()`](#scrollpixels-direction) - [`.scrollTo()`](#scrolltoedge) - [`.swipe()`](#swipedirection-speed-percentage) +- [`.setColumnToValue()`](#setcolumntovalue-column-value) **iOS only** ### `tap()` @@ -107,3 +108,13 @@ await element(by.id('scrollView')).swipe('down'); await element(by.id('scrollView')).swipe('down', 'fast'); await element(by.id('scrollView')).swipe('down', 'fast', 0.5); ``` +### `setColumnToValue(column,value)` iOS only + +column - number of datepicker column (starts from 0) +value - string value in setted column (must be correct) + +```js +await expect(element(by.type('UIPickerView'))).toBeVisible(); +await element(by.type('UIPickerView')).setColumnToValue(1,"6"); +await element(by.type('UIPickerView')).setColumnToValue(2,"34"); +``` diff --git a/generation/core/generator.js b/generation/core/generator.js index e3f676c3ec..98aff8c194 100644 --- a/generation/core/generator.js +++ b/generation/core/generator.js @@ -180,7 +180,7 @@ module.exports = function({ t.identifier("value"), addArgumentContentSanitizerCall(arg, json.name) ) - ]) + ]) : addArgumentContentSanitizerCall(arg, json.name) ); diff --git a/generation/package.json b/generation/package.json index 83389021bf..729d99a507 100644 --- a/generation/package.json +++ b/generation/package.json @@ -49,4 +49,4 @@ "babel-template": "^6.26.0", "java-method-parser": "^0.4.5" } -} \ No newline at end of file +}