google/EarlGrey

View on GitHub
docs/api.md

Summary

Maintainability
Test Coverage
# API
EarlGrey includes three main groups of APIs:

  * [Interaction APIs](#interaction-apis)
  * [Synchronization APIs](#synchronization-apis)
  * [Other Top Level APIs](#other-top-level-apis)


## Interaction APIs

EarlGrey test cases are made up of interactions with UI elements. Each interaction consists of:

  * Selecting an element to interact with,
  * Performing an action on it, and/or
  * Making an assertion to verify state and behavior.

To reflect this, the Interaction APIs are organized into the following:

  * [Selection API](#selection-api)
  * [Action API](#action-api)
  * [Assertion API](#assertion-api)

Each of these APIs is designed with extensibility in mind, giving the user flexibility for customization,
while preserving the prose-like structure of tests. Consider the following snippet:


```objc
[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"ClickMe")];
```

It shows how to start an interaction by selecting an element with `ClickMe` as the Accessibility
Identifier. After you select an element, you can continue the interaction with an action or an
assertion. EarlGrey works with any element that conforms to the [UIAccessibility protocol](https://developer.apple.com/library/ios/documentation/uikit/reference/UIAccessibility_Protocol/Introduction/Introduction.html),
not just `UIViews`; this allows tests to perform a richer set of interactions.

You can chain a selection and an action in one statement. For example, you can tap on the element
that has `ClickMe` as its Accessibility Identifier as follows:


```objc
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"ClickMe")]
    performAction:grey_tap()];
```

Note: `selectElementWithMatcher:` doesn't return an element; it just marks the beginning of an
interaction.

You can also chain a selection and an assertion. The following snippet shows how to select an
element that has `ClickMe` as its accessibility identifier and asserts that it is displayed:


```objc
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"ClickMe")]
    assertWithMatcher:grey_sufficientlyVisible()];
```

Finally, you can perform actions and assertions in sequence. The following statement finds an element with
the accessibility identifier `ClickMe`, taps on it, and asserts that it is not displayed.


```objc
[[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"ClickMe")]
    performAction:grey_tap()]
    assertWithMatcher:grey_notVisible()];
```


The following is an example of a simple interaction:


```objc
[[[EarlGrey selectElementWithMatcher:<element_matcher>]
    performAction:<action>]
    assertWithMatcher:<assertion_matcher>];
```

Where `<element_matcher>` and `<assertion_matcher>` are matchers contained in `GREYMatchers.h` and
`<action>` is one of the actions in `GREYActions.h`. Because each of these has a shorthand
C-function, instead of using `[GREYMatchers matcherForSufficientlyVisible]` you can use
`grey_sufficientlyVisible()`. Shorthand notation is enabled by default. To disable it, add
`#define GREY_DISABLE_SHORTHAND 1` to the project's prefix header.

### Selection API

Use the Selection API to locate a UI element on the screen. This API accepts a matcher and tests it against all
the elements in the UI hierarchy to locate an element to interact with. In
EarlGrey, matchers support an API that is similar to that of [OCHamcrest](https://github.com/hamcrest/OCHamcrest)
matchers. You can combine matchers using AND-OR-NOT logic, allowing you to create matching rules
that can pinpoint any element in the UI hierarchy.

#### EarlGrey Matchers

All EarlGrey matchers are available in the [GREYMatchers](../EarlGrey/Matcher/GREYMatchers.m)
factory class. The best way to find a UI element is to use its accessibility properties. We
strongly recommend using an [accessibility identifier](https://developer.apple.com/library/ios/documentation/uikit/reference/UIAccessibilityIdentification_Protocol/Introduction/Introduction.html)
as it uniquely identifies an element. Use `grey_accessibilityID()` as your matcher to select a UI
element by its accessibility identifier. You can also use other accessibility properties, such as using
`grey_accessibilityTrait()` as the matcher for UI elements with specific accessibility traits, or by using
`grey_accessibilityLabel()` as the matcher for accessibility labels.

A matcher can be ambiguous and match multiple elements: for example, `grey_sufficientlyVisible()`
will match all sufficiently visible UI elements. In such cases, you must narrow down the
selection until it can uniquely identify a single UI element. You can make the matchers more specific
by combining matchers with `grey_allOf()`, `grey_anyOf()`, `grey_not()`  or by supplying a root
matcher with the `inRoot` method to narrow the selection.

Consider these examples for both cases.

First, with collection matchers, the following snippet finds a UI element that has an accessibility
label `Send` **and** is displayed on the screen.


```objc
id<GREYMatcher> visibleSendButtonMatcher =
    grey_allOf(grey_accessibilityLabel(@"Send"), grey_sufficientlyVisible(), nil);

[[EarlGrey selectElementWithMatcher:visibleSendButtonMatcher]
    performAction:grey_tap()];
```

Note that with `grey_allOf` the order matters. If `grey_sufficientlyVisible` is used first, then every element
in the entire application will be checked for visibility. It's important to order matchers from
most selective (such as accessibility label and accessibility id) to least.

Next, with `inRoot`, the following statement finds an element that has the accessibility label set
to `Send` and is contained in a UI element that is an instance of the `SendMessageView` class.

```objc
[[[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Send")]
    inRoot:grey_kindOfClass([SendMessageView class])]
    performAction:grey_tap()];
```

Note: For compatibility with Swift, we use `grey_allOfMatchers()` and `grey_anyOfMatchers()` instead of `grey_allOf()` and `grey_anyOf()` respectively.

#### Custom Matchers

To create custom matchers, use the block-based [GREYElementMatcherBlock](../EarlGrey/Matcher/GREYElementMatcherBlock.h)
class. For example, the following code matches views that don't have any subviews:


```objc
+ (id<GREYMatcher>)matcherForViewsWithoutSubviews {
  MatchesBlock matches = ^BOOL(UIView *view) {
    return view.subviews.count == 0;
  };
  DescribeToBlock describe = ^void(id<GREYDescription> description) {
    [description appendText:@"Views without subviews"];
  };

  return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
                                              descriptionBlock:describe];
}
```

`MatchesBlock` can also accept type `id` instead of `UIView *`. You should use `id` when the
matcher must also work with accessibility elements. The following matcher example works
universally for all UI element types:


```objc
+ (id<GREYMatcher>)matcherForElementWithoutChildren {
  MatchesBlock matches = ^BOOL(id element) {
    if ([element isKindOfClass:[UIView class]]) {
      return ((UIView *)element).subviews.count == 0;
    }
    // Handle accessibility elements here.
    return ...;
  };
  DescribeToBlock describe = ^void(id<GREYDescription> description) {
    [description appendText:@"UI element without children"];
  };
  return [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
                                              descriptionBlock:describe];
}
```

This matcher can be used in a test to select a UI element that doesn’t have any children (or
subviews) and double-tap on it (assuming that the method was declared in a class `CustomMatchers`):


```objc
[[EarlGrey selectElementWithMatcher:[CustomMatchers matcherForElementWithoutChildren]]
    performAction:grey_doubleTap()];
```

#### Selecting Off-Screen UI Elements

In certain situations the UI element may be hidden off-screen, and may require certain interactions
to bring it onto the screen. Common examples include scrolling to an element that is not visible in
the scrollview, zooming-in on a map to show UI elements that are shown only in street-view,
navigating through a [UICollectionView](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionView_class/)
that has a custom layout, etc. You can use the `[usingSearchAction:onElementWithMatcher:]` method
to provide a search action for such elements. The API allows you to specify a search action and a
matcher for the element on which the search action will be applied. EarlGrey applies the search
action repeatedly until the element you are looking for is found (or a timeout occurs).

For example, the following statement attempts to find an element matching `aButtonMatcher` by
repeatedly scrolling down (by 50 points at a time) on the element matching `aScrollViewMatcher` and
taps the button when it finally finds it.


```objc
[[[EarlGrey selectElementWithMatcher:aButtonMatcher]
    usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 50)
 onElementWithMatcher:aScrollViewMatcher]
    performAction:grey_tap()];
```

And in this example, this statement attempts to find a table view cell matching `aCellMatcher` by
repeatedly scrolling up (by 50 points at a time) on a table matching `aTableViewMatcher`.

```objc
[[[EarlGrey selectElementWithMatcher:aCellMatcher]
    usingSearchAction:grey_scrollInDirection(kGREYDirectionUp, 50)
 onElementWithMatcher:aTableViewMatcher]
    performAction:grey_tap()];
```

### Action API

Use the Action API to specify the test actions to perform on a selected UI element.

#### EarlGrey Actions

All EarlGrey actions are available in the [GREYActions](../EarlGrey/Action/GREYActions.h) factory
class. The most common action is tapping (or clicking) on a given element using the `grey_tap()`
method:

```objc
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"TapMe")]
    performAction:grey_tap()];
```

If an action triggers changes in the UI hierarchy, EarlGrey synchronizes each action (including
chained actions) with the UI, ensuring that it is in a stable state before the next action is
performed.

Not all actions can be performed on all elements; for example, the tap action cannot be performed
on elements that are not visible. To enforce this, EarlGrey uses **constraints** which are
preconditions in the form of [GREYMatcher](../EarlGrey/Matcher/GREYMatcher.h) that
must be met before an action is actually performed. Failure to meet these constraints results in an
exception being thrown and the test marked as failed. To avoid test failure, you can invoke
`performAction:error:` to get an [NSError](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSError_Class/)
object containing failure details.


```objc
NSError *error;
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Non-Existent-Ax-Id")]
    performAction:grey_tap()
            error:&error];
```

In the above case, an exception **will not** be thrown for the EarlGrey interaction being performed
on a non-existent element. Instead, the error object passed will save the failure details and not
fail the test immediately. The error details can then be perused for finding the failure details.

#### Custom Actions

Custom actions can be created by conforming to the [GREYAction](../EarlGrey/Action/GREYAction.h)
protocol. For convenience, you can use [GREYActionBlock](../EarlGrey/Action/GREYActionBlock.h),
which already conforms to the GREYAction protocol and allows you to express an action in the form
of a block. The following code creates an action using a block that invokes a custom selector
(`animateWindow`) to animate the selected element’s window:


```objc
- (id<GREYAction>)animateWindowAction {
  return [GREYActionBlock actionWithName:@"Animate Window"
                             constraints:nil
                            performBlock:^(id element, NSError *__strong *errorOrNil) {
    // First, make sure the element is attached to a window.
    if ([element window] == nil) {
      // Populate error.
      *errorOrNil = ...
      // Indicates that the action failed.
      return NO;
    }
    // Invoke a custom selector that animates the window of the element.
    [element animateWindow];
    // Indicates that the action was executed successfully.
    return YES;
  }];
}
```

### Assertion API

Use the Assertion API to verify the state and behavior of a UI element.

#### Assertions Using Matchers

Use `assertWithMatcher:` to perform an assertion with [GREYMatcher](../EarlGrey/Matcher/GREYMatcher.h)
matchers. The selected element is run through the matcher for verification. For example,
the following snippet asserts that the element with the accessibility ID `ClickMe` is visible,
and the test fails if the element is not visible on the screen.

```objc
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"ClickMe")]
    assertWithMatcher:grey_sufficientlyVisible()];
```

To prevent test failure, you can provide an `NSError` object to the `assertWithMatcher:error:`
method, as in the statement shown below. Instead of failing, the EarlGrey assertion will provide
you with an `NSError` object that contains details about the failure.

```objc
NSError *error;
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"ClickMe")]
    assertWithMatcher:grey_sufficientlyVisible()
                error:&error];
```

You can also perform an assertion by using the `assert` method and passing an instance of
[`GREYAssertion`](../EarlGrey/Assertion/GREYAssertion.h). We recommend that you create
assertions from matchers using `assertWithMatcher:`
whenever possible. Matchers are lightweight and ideal for simple assertions. However, a custom
`GREYAssertion` could be a better choice in the case of an assertion that needs to perform complex
logic, like manipulating the UI, to proceed with the assertion.

#### Custom Assertions

You can create custom assertions using the [`GREYAssertion`](../EarlGrey/Assertion/GREYAssertion.h)
protocol or by using [`GREYAssertionBlock`](../EarlGrey/Assertion/GREYAssertionBlock.h) that
accepts the assertion logic in a block. The following example uses `GREYAssertionBlock` to write an
assertion that checks that the view's alpha is equal to the provided value:


```objc
+ (id<GREYAssertion>)hasAlpha:(CGFloat)alpha {
  return [GREYAssertionBlock assertionWithName:@"Has Alpha"
                                assertionBlock:^(UIView *view, NSError *__strong *errorOrNil) {
    if (view.alpha != alpha) {
      NSString *reason =
        [NSString stringWithFormat:@"Alpha value doesn't match for %@", view];
      // Check if errorOrNil was provided, if so populate it with relevant details.
      if (errorOrNil) {
        *errorOrNil = ...
      }
      // Indicates assertion failed.
      return NO;
    }
    // Indicates assertion passed.
    return YES;
  }];
}
```

Note: Do not assume that assertions are run against valid UI elements. You will need to perform
your own check to make sure the UI element is in a valid state before validating the assertion. For
instance, the following snippet checks that the element exists (that it isn’t `nil`) before
asserting the rest of the state:

```objc
+ (id<GREYAssertion>)hasAlpha:(CGFloat)alpha {
  return [GREYAssertionBlock assertionWithName:@"Has Alpha"
                                assertionBlock:^(UIView *view, NSError *__strong *errorOrNil) {
    // Assertions can be performed on nil elements. Make sure view isn’t nil.
    if (view == nil) {
      // Check if errorOrNil was provided, if so populate it with relevant details.
      if (errorOrNil) {
        *errorOrNil = [NSError errorWithDomain:kGREYInteractionErrorDomain
                                        code:kGREYInteractionElementNotFoundErrorCode
                                    userInfo:nil];
      }
      return NO;
    }
    // Perform rest of the assertion logic.
    ...
    // Indicates assertion passed.
    return YES;
  }];
}
```

Alternatively, you can create a class that conforms to
[GREYAssertion](../EarlGrey/Assertion/GREYAssertion.h).

#### Failure Handlers

By default, EarlGrey uses a failure handler that is invoked when any exception is raised by the
framework. The default handler logs the exception, takes a screenshot, and then prints its path
along with any other useful information. You can choose to provide your own custom failure handler
and install it using the `EarlGrey setFailureHandler:` API which replaces the global default
framework handler. To create a custom failure handler, write a class that conforms to the
[GREYFailureHandler](../EarlGrey/Exception/GREYFailureHandler.h) protocol:


```objc
@interface MyFailureHandler : NSObject <GREYFailureHandler>
@end

@implementation MyFailureHandler

- (void)handleException:(GREYFrameworkException *)exception details:(NSString *)details {
  // Log the failure and state of the app if required.
  // Call thru to XCTFail() with an appropriate error message.
}

- (void)setInvocationFile:(NSString *)fileName
        andInvocationLine:(NSUInteger)lineNumber {
  // Record the file name and line number of the statement which was executing before the
  // failure occurred.
}
@end
```

#### Assertions Macros

EarlGrey provides its own macros that can be used within a testcase for
assertion and verification. These macros are similar to the macros provided by
XCTest and invoke the global failure handler upon assertion failure.

  * `GREYAssert(expression, reason, ...)` — Fails if the expression evaluates to false
  * `GREYAssertTrue(expression, reason, ...)` — Fails if the expression evaluates to
false. Use for BOOL expressions
  * `GREYAssertFalse(expression, reason, ...)` — Fails if the expression evaluates to
true. Use for BOOL expressions
  * `GREYAssertNotNil(expression, reason, ...)` — Fails if the expression evaluates to
nil
  * `GREYAssertNil(expression, reason, ...)` — Fails if the expression evaluates to a
non-nil value
  * `GREYAssertEqual(left, right, reason, ...)` — Fails if left != right for scalar
types
  * `GREYAssertNotEqual(left, right, reason, ...)` — Fails if left == right for scalar
types
  * `GREYAssertEqualObjects(left, right, reason, ...)` — Fails if [left isEqual:right] returns
false
  * `GREYAssertNotEqualObjects(left, right, reason, ...)` — Fails if [left isEqual:right] returns
true
  * `GREYFail(reason, ...)` — Fails immediately with the provided reason
  * `GREYFailWithDetails(reason, details, ...)` — Fails immediately with the provided reason and
  details

#### Layout Testing

EarlGrey provides APIs to verify the layout of UI elements; for example, to verify that element X
is to the left of element Y. Layout assertions are modeled after [NSLayoutConstraint](https://developer.apple.com/library/ios/DOCUMENTATION/AppKit/Reference/NSLayoutConstraint_Class/index.html).
To verify the layout, you need to first create a constraint that specifies the layout,
select an element constrained by it, and then assert that it matches the constraint using
`grey_layout(...)`. Note that `grey_layout(...)` takes an array of constraints, all of which must
be satisfied. This allows for easy specification of complex layout assertions.

For example, the following constraint specifies that the selected element is to the right of any
other arbitrary element used as a reference.


```objc
GREYLayoutConstraint *rightConstraint =
    [GREYLayoutConstraint layoutConstraintWithAttribute:kGREYLayoutAttributeLeft
                                              relatedBy:kGREYLayoutRelationGreaterThanOrEqual
                                   toReferenceAttribute:kGREYLayoutAttributeRight
                                             multiplier:1.0
                                               constant:0.0];
```

You can now select the element with the `RelativeRight` accessibility ID and use
`grey_layout(@[rightConstraint])` to assert if it's on the right of the reference element, which in
our example is the element with `TheReference` accessibility ID.

```objc
[[EarlGrey selectElementWithMatcher:grey_accessibilityID(@”RelativeRight”)]
    assertWithMatcher:grey_layout(@[rightConstraint], grey_accessibilityID(@”TheReference”))];
```

You can also create simple directional constraints using `layoutConstraintForDirection:`. The
following code is equivalent to the previous example:

```
GREYLayoutConstraint *rightConstraint =
    [GREYLayoutConstraint layoutConstraintForDirection:kGREYLayoutDirectionRight
                                  andMinimumSeparation:0.0];
```

## Synchronization APIs

These APIs let you control how EarlGrey synchronizes with the app under test.

### GREYCondition

If your test case requires special handling, you can use `GREYCondition` to wait or synchronize
with certain conditions. `GREYCondition` takes a block that returns a `BOOL` to indicate whether
the condition has been met. The framework polls this block until the condition is met before
proceeding with rest of the test case. The following snippet illustrates how to create and use a
`GREYCondition`:

```objc
GREYCondition *myCondition = [GREYCondition conditionWithName:@"my condition"
                                                        block:^BOOL {
  ... do your condition check here ...
  return yesIfMyConditionWasSatisfied;
}];
// Wait for my condition to be satisfied or timeout after 5 seconds.
BOOL success = [myCondition waitWithTimeout:5];
if (!success) {
  // Handle condition timeout.
}
```

### Synchronization

EarlGrey automatically waits for the app to idle by tracking the main dispatch queue, main
operation queue, network, animations and several other signals and performs interactions only when
the app is Idle. However there may be situations where the interactions must be performed in spite
of app being busy. For example in a messaging app, a photo might be uploading and corresponding animation
running but the test might still want to type and send a text message. To address such situations, you can
disable EarlGrey's synchronization using `kGREYConfigKeySynchronizationEnabled`, as shown in the following snippet:

```objc
[[GREYConfiguration sharedInstance] setValue:@(NO)
                                forConfigKey:kGREYConfigKeySynchronizationEnabled];
```

Once disabled all interactions will proceed without waiting for the app to idle until synchronization is
reenabled again. Note that to maximize test effectiveness, synchronization must be reenabled as soon
as possible. Also instead of disabling synchronization completely you can configure the synchronization parameters
to suit the needs of your app. For example:

- `kGREYConfigKeyNSTimerMaxTrackableInterval` can be used to specify the maximum interval of non-repeating
NSTimers that EarlGrey should synchronize with.
- `kGREYConfigKeyDispatchAfterMaxTrackableDelay` can be used to specify the maximum delay
for future executions using `dispatch_after` calls that EarlGrey must synchronize with.
- `kGREYConfigKeyURLBlacklistRegex` can be used to specify a list of URLs for which EarlGrey should
**not** wait.

And several such configurations are available in [GREYConfiguration](../EarlGrey/Common/GREYConfiguration.h).
See below for some specific use cases in detail.

### Network

By default, EarlGrey synchronizes with all network calls, but you can customize this behavior by
providing regular expressions to skip over certain URLs. To blacklist a URL, create a regular
expression that matches the URL, add it to an `NSArray` and pass it to `GREYConfiguration`.
For multiple URLs, repeat the same process by creating one regular expression for each URL.
For example, to tell the framework not to wait for www.google.com and www.youtube.com,
do something like:

```objc
NSArray *blacklist = @[ @".*www\\.google\\.com", @".*www\\.youtube\\.com" ];
[[GREYConfiguration sharedInstance] setValue:blacklist
                                forConfigKey:kGREYConfigKeyURLBlacklistRegex];
```

### Interaction Timeout

By default, a thirty second timeout is used for any interaction. In that time, if the app under
test fails to idle, a timeout exception is thrown and the test is marked as failed. You can use
[GREYConfiguration](../EarlGrey/Common/GREYConfiguration.h) to change this timeout value. For
example, to increase the timeout to 60 seconds (one minute):

```objc
[[GREYConfiguration sharedInstance] setValue:@(60.0)
                                forConfigKey:kGREYConfigKeyInteractionTimeoutDuration];
```

### Animation Timeout

Animations that repeat indefinitely — or that run for a long time — affect synchronization.
Animations that run longer than the test timeout value result in a timeout exception. To avoid such
cases, EarlGrey limits the animation duration to five seconds and disables repeating animations
(continuous animations run once). To instruct EarlGrey to allow animations to run longer, change
the maximum allowable animation duration value. Make sure this doesn’t affect your test timeouts.
The following snippet increases the maximum animation duration to 30 seconds.

```objc
[[GREYConfiguration sharedInstance] setValue:@(30.0)
                                forConfigKey:kGREYConfigKeyCALayerMaxAnimationDuration];
```

### Invocation From Non-Main Thread

Due to limitation of dispatch queues and the way EarlGrey synchronizes with them, calling into EarlGrey
statements from a `dispatch_queue` leads to a livelock. To mitigate this, we've introduced new block-based
APIs that wrap EarlGrey statements, and that can be safely called from non-main threads:

  * `grey_execute_sync(void (^block)())` — Synchronous. Blocks until execution is
complete.
  * `grey_execute_async(void (^block)())` — Asynchronous.

## Other Top Level APIs

Outside of UI interaction, you can use EarlGrey to control the device and system in various ways.

### Global Configuration

The `GREYConfiguration` class lets you configure the behavior of the framework. It provides a
means to configure synchronization, interaction timeouts, action constraints checks, logging, etc.
As soon as a configuration is changed, it is applied globally. For instance, the following code
changes the delay limit for dispatch after calls that EarlGrey tracks:


```objc
[[GREYConfiguration sharedInstance] setValue:@(5)
                                forConfigKey:kGREYConfigKeyDispatchAfterMaxTrackableDelay];
```

### Controlling Device Orientation

To rotate a device, use `[EarlGrey rotateDeviceToOrientation:errorOrNil:]` to simulate a device in
a specific orientation. For instance, the following causes the system (and your app) to act as if
the device is in **Landscape** mode with the device held upright and the **Home** button on the
right side:


```objc
[EarlGrey rotateDeviceToOrientation:UIDeviceOrientationLandscapeLeft errorOrNil:nil];
```

You can choose from the following orientation modes (for more information, see [UIDeviceOrientation](https://developer.apple.com/library/ios/documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html#//apple_ref/doc/c_ref/UIDeviceOrientation)):

  * `UIDeviceOrientationUnknown`
  * `UIDeviceOrientationPortrait`
  * `UIDeviceOrientationPortraitUpsideDown`
  * `UIDeviceOrientationLandscapeLeft`
  * `UIDeviceOrientationLandscapeRight`
  * `UIDeviceOrientationFaceUp`
  * `UIDeviceOrientationFaceDown`

### Shake Gesture

You can use `[EarlGrey shakeDeviceWithError:]` to simulate a shake gesture in a simulator.