diff --git a/detox/src/devices/Simulator.js b/detox/src/devices/Simulator.js index 4d1b2f7aef..e7ac3b6b4f 100644 --- a/detox/src/devices/Simulator.js +++ b/detox/src/devices/Simulator.js @@ -7,6 +7,7 @@ const IosNoneDevice = require('./IosNoneDevice'); const FBsimctl = require('./Fbsimctl'); const configuration = require('../configuration'); const argparse = require('../utils/argparse'); +const invoke = require('../invoke'); class Simulator extends IosNoneDevice { @@ -97,6 +98,23 @@ class Simulator extends IosNoneDevice { async shutdown() { await this._fbsimctl.shutdown(this._simulatorUdid); } + + async setOrientation(orientation) { + // keys are possible orientations + const orientationMapping = { + landscape: 3, // top at left side landscape + portrait: 1 // non-reversed portrait + }; + if (!Object.keys(orientationMapping).includes(orientation)) { + throw new Error(`setOrientation failed: provided orientation ${orientation} is not part of supported orientations: ${Object.keys(orientationMapping)}`) + } + + const call = invoke.call(invoke.EarlGrey.instance, + 'rotateDeviceToOrientation:errorOrNil:', + invoke.IOS.NSInteger(orientationMapping[orientation]) + ); + await new invoke.InvocationManager(this.client).execute(call); + } } module.exports = Simulator; diff --git a/detox/src/devices/Simulator.test.js b/detox/src/devices/Simulator.test.js index aa8d4a9f2a..e47015a558 100644 --- a/detox/src/devices/Simulator.test.js +++ b/detox/src/devices/Simulator.test.js @@ -187,6 +187,39 @@ describe('Simulator', () => { await simulator.openURL(url); expect(simulator._fbsimctl.open).toHaveBeenCalledWith(simulator._simulatorUdid, url); }); + + it(`setOrientation() should throw an error if give wrong input `, async() => { + expect.assertions(1); + simulator = validSimulator(); + + try { + await simulator.setOrientation('UpsideDown'); + } catch(e) { + expect(e.message).toMatch('setOrientation failed: provided orientation UpsideDown is not part of supported orientations: landscape,portrait'); + } + }); + + it(`setOrientation() should set the orientation to portrait`, async() => { + simulator = validSimulator(); + + await simulator.setOrientation('portrait'); + expect(client.execute).toHaveBeenCalled(); + const call = client.execute.mock.calls[client.execute.mock.calls.length - 1][0](); + expect(call.target.type).toBe('EarlGrey'); + expect(call.method).toBe('rotateDeviceToOrientation:errorOrNil:'); + expect(call.args[0].value).toBe(1); + }); + + it(`setOrientation() should set the orientation to landscape`, async() => { + simulator = validSimulator(); + + await simulator.setOrientation('landscape'); + expect(client.execute).toHaveBeenCalled(); + const call = client.execute.mock.calls[client.execute.mock.calls.length - 1][0](); + expect(call.target.type).toBe('EarlGrey'); + expect(call.method).toBe('rotateDeviceToOrientation:errorOrNil:'); + expect(call.args[0].value).toBe(3); + }); }); const notification = { diff --git a/detox/test/e2e/f-simulator.js b/detox/test/e2e/f-simulator.js index 51066bbeb7..b150fbc99b 100644 --- a/detox/test/e2e/f-simulator.js +++ b/detox/test/e2e/f-simulator.js @@ -28,4 +28,28 @@ describe('Simulator', () => { await element(by.label('Say Hello')).tap(); await expect(element(by.label('Hello!!!'))).toBeVisible(); }); + + describe('device orientation', () => { + beforeEach(async() => { + await device.reloadReactNative(); + await element(by.label('Orientation')).tap(); + + // Check if the element whichs input we will test actually exists + await expect(element(by.id('currentOrientation'))).toExist(); + }); + + it('OrientationLandscape', async () => { + await device.setOrientation('landscape'); + + await expect(element(by.id('currentOrientation'))).toHaveText('Landscape'); + }); + + it('OrientationPortrait', async() => { + // As default is portrait we need to set it otherwise + await device.setOrientation('landscape'); + await device.setOrientation('portrait'); + + await expect(element(by.id('currentOrientation'))).toHaveText('Portrait'); + }); + }); }); diff --git a/detox/test/index.ios.js b/detox/test/index.ios.js index f779e37f25..812eeb6b38 100644 --- a/detox/test/index.ios.js +++ b/detox/test/index.ios.js @@ -69,6 +69,7 @@ class example extends Component { {this.renderScreenButton('Stress', Screens.StressScreen)} {this.renderScreenButton('Switch Root', Screens.SwitchRootScreen)} {this.renderScreenButton('Timeouts', Screens.TimeoutsScreen)} + {this.renderScreenButton('Orientation', Screens.Orientation)} ); } diff --git a/detox/test/src/Screens/Orientation.js b/detox/test/src/Screens/Orientation.js new file mode 100644 index 0000000000..9d91402679 --- /dev/null +++ b/detox/test/src/Screens/Orientation.js @@ -0,0 +1,33 @@ +import React, { Component } from 'react'; +import { + Text, + View, + TouchableOpacity +} from 'react-native'; + +export default class Orientation extends Component { + + constructor(props) { + super(props); + this.state = { + horizontal: false + }; + console.log('Orientation react component constructed (console.log test)'); + } + + detectHorizontal({nativeEvent: {layout: {width, height,x,y}}}) { + this.setState({ + horizontal: width > height + }); + } + + render() { + return ( + + + {this.state.horizontal ? 'Landscape' : 'Portrait'} + + + ); + } +} diff --git a/detox/test/src/Screens/index.js b/detox/test/src/Screens/index.js index 1d41a38755..a7989d6cff 100644 --- a/detox/test/src/Screens/index.js +++ b/detox/test/src/Screens/index.js @@ -6,6 +6,7 @@ import WaitForScreen from './WaitForScreen'; import StressScreen from './StressScreen'; import SwitchRootScreen from './SwitchRootScreen'; import TimeoutsScreen from './TimeoutsScreen'; +import Orientation from './Orientation'; export { SanityScreen, @@ -15,5 +16,6 @@ export { WaitForScreen, StressScreen, SwitchRootScreen, - TimeoutsScreen + TimeoutsScreen, + Orientation }; diff --git a/docs/APIRef.DeviceObjectAPI.md b/docs/APIRef.DeviceObjectAPI.md index 91ef485b6b..9d312e45e1 100644 --- a/docs/APIRef.DeviceObjectAPI.md +++ b/docs/APIRef.DeviceObjectAPI.md @@ -29,3 +29,7 @@ Uninstall the app defined in the current [`configuration`](APIRef.Configuration. ### `device.sendUserNotification(params)` + +### `device.setOrientation(orientation)` +Takes `"portrait"` or `"landscape"` and rotates the device to the given orientation. +Currently only available in the iOS Simulator.