google / EarlGrey

:tea: iOS UI Automation Test Framework
http://google.github.io/EarlGrey/
Apache License 2.0
5.62k stars 744 forks source link

Assert the label in a UITableViewCell with EarlGrey 2.0 #1281

Open whoyawn opened 4 years ago

whoyawn commented 4 years ago

Trying to assert that the first cell in the table view contains the string "first":

EarlGrey.selectElement(with: grey_kindOfClass(UITableViewCell.self))
  .atIndex(0)
  .assert(grey_text("First"))

Failure:

  "Description Glossary" :   {
    "M" : "((kindOfClass('UILabel') || kindOfClass('UITextField') || kindOfClass('UITextView')) && hasText('First'))",
    "E" : "<App.SubclassCell:0x7fa0c011d600; isAccessible=N; AX.id='Subclass Cell'; AX.frame={{0, 88}, {414, 56}}; AX.activationPoint={207, 116}; AX.traits='UIAccessibilityTraitButton'; AX.focused='N'; frame={{0, 0}, {414, 56}}; opaque; alpha=1; text=''>",
    "S" : "kindOfClass('UILabel'), kindOfClass('UITextField'), kindOfClass('UITextView')"
  },
  "User Info" :   {
    "NSLocalizedDescription" : "Assertion with matcher [M] failed: UI element [E] failed to match the following matcher(s): [S]"
  },

How do I confirm that a specific index of the table view contains certain text?

chan-park commented 4 years ago

grey_text only accepts element whose class type is either UILabel, UITextField, or UITextView. https://github.com/google/EarlGrey/blob/earlgrey2/AppFramework/Matcher/GREYMatchers.m#L275-L277

You might want to assert with a custom matcher you created that checks if UITableViewCell contains some text.

whoyawn commented 4 years ago

Seems to be a bug on Swift 5 / iOS 13 / Xcode 11:

class UITests: TestCase {

    func testEveryoneTag() throws {
        let workaroundArray: NSArray = [grey_kindOfClass(UITableViewCell.self), grey_tableCellWithText("test")]
        let matcher = grey_allOf(workaroundArray as! [GREYMatcher])
        EarlGrey.selectElement(with: matcher)
            .perform(grey_doubleTap())
    }
}

func grey_tableCellWithText(_ text: String) -> GREYMatcher {
    let matches: GREYMatchesBlock = { (element: Any?) -> Bool in
      if let cell = element as? UITableViewCell {
        return true
      } else {
        return false // always goes here
      }
    }

    // Create a description for the matcher.
    let describe: GREYDescribeToBlock = { (description: Any) -> Void in
      let greyDescription:GREYDescription = description as! GREYDescription
      greyDescription.appendText("Table Cell with Text ('\(text)')")
    }

    // Create an EarlGrey custom matcher.
    return GREYElementMatcherBlock.init(matchesBlock: matches, descriptionBlock: describe)
}

When I step through the match block and test element is UIView, I always get false.

whoyawn commented 4 years ago

Tested custom matcher in the example project, also fails:

// EarlGreyExampleSwiftUITests.swift
    func testCustomMatcher() {
        let workaroundArray: NSArray = [grey_kindOfClass(UITableViewCell.self), grey_tableCell()]
        let matcher = grey_allOf(workaroundArray as! [GREYMatcher])
        EarlGrey.selectElement(with: matcher)
            .perform(grey_doubleTap())
    }

    func grey_tableCell() -> GREYMatcher {
        let matches: GREYMatchesBlock = { (element: Any?) -> Bool in
          if let cell = element as? UITableViewCell { // fails
            return true
          } else {
            print("goes here")
            return false
          }
        }

        // Create a description for the matcher.
        let describe: GREYDescribeToBlock = { (description: Any) -> Void in
          let greyDescription:GREYDescription = description as! GREYDescription
          greyDescription.appendText("Table Cell")
        }

        // Create an EarlGrey custom matcher.
        return GREYElementMatcherBlock.init(matchesBlock: matches, descriptionBlock: describe)
    }

Error message:

cannot proceed
    t =     3.54s Assertion Failure: EarlGreyExampleSwiftUITests.swift:78: Exception: com.google.earlgrey.ElementInteractionErrorDomain

Exception Name: com.google.earlgrey.ElementInteractionErrorDomain
Exception Reason: {
  "User Info" :   {
    "NSLocalizedDescription" : "Interaction cannot continue because the desired element was not found."
  },
  "Error Info" :   {
    "Search API Info" : "",
    "Action Name" : "Tap 2 times",
    "Recovery Suggestion" : "Check if the element exists in the UI hierarchy printed below. If it exists, adjust the matcher so that it accurately matches element.",
    "Element Matcher" : "(kindOfClass('UITableViewCell') && Table Cell)"
  },
  "Bundle ID" : "com.google.earlgrey.samples.EarlGrey",
  "File Name" : "GREYElementInteraction.m",
  "Stack Trace" :   [
    "0   AppFramework                        0x000000010047dbce -[GREYElementInteraction matchElementsWithTimeout:syncBeforeMatch:completionBlock:] + 3198",
    "1   AppFramework                        0x000000010047fed1 -[GREYElementInteraction performAction:error:] + 1617",
    "2   CoreFoundation                      0x00007fff23e44c4c __invoking___ + 140",
    "3   CoreFoundation                      0x00007fff23e41e31 -[NSInvocation invoke] + 321",
    "4   AppFramework                        0x00000001004b2401 __38+[EDOInvocationRequest requestHandler]_block_invoke + 4433",
    "5   AppFramework                        0x00000001004aed4b -[EDOExecutor edo_handleMessage:] + 331",
    "6   AppFramework                        0x00000001004aebeb __37-[EDOExecutor handleRequest:context:]_block_invoke_2 + 43",
    "7   libdispatch.dylib                   0x00007fff51978951 _dispatch_call_block_and_release + 12",
    "8   libdispatch.dylib                   0x00007fff519798cb _dispatch_client_callout + 8",
    "9   libdispatch.dylib                   0x00007fff5197f60c _dispatch_lane_serial_drain + 707",
    "10  libdispatch.dylib                   0x00007fff51980044 _dispatch_lane_invoke + 388",
    "11  libdispatch.dylib                   0x00007fff5198a0c4 _dispatch_workloop_worker_thread + 626",
    "12  libsystem_pthread.dylib             0x00007fff51b9ea3d _pthread_wqthread + 290",
    "13  libsystem_pthread.dylib             0x00007fff51b9db77 start_wqthread + 15"
  ],
  "Line" : "160",
  "Error Code" : "0",
  "App Screenshots" :   {
    "Screenshot At Failure" : <UIImage:0x600002cb5830 anonymous {414, 896}>
  },
  "Function Name" : "-[GREYElementInteraction matchElementsWithTimeout:syncBeforeMatch:completionBlock:]",
  "Description" : "Interaction cannot continue because the desired element was not found.",
  "Error Domain" : "com.google.earlgrey.ElementInteractionErrorDomain"
}
Exception Details: (kindOfClass('UITableViewCell') && Table Cell)

Bundle ID: com.google.EarlGreyExampleSwiftUITests.xctrunner

Stack Trace: (
    0   EarlGreyExampleSwiftUITests         0x000000010546e96e -[GREYDefaultFailureHandler handleException:details:] + 2078
    1   EarlGreyExampleSwiftUITests         0x000000010546eede +[GREYElementInteractionErrorHandler handleInteractionError:outError:] + 542
    2   EarlGreyExampleSwiftUITests         0x000000010546f372 -[GREYElementInteractionProxy performAction:error:] + 498
    3   EarlGreyExampleSwiftUITests         0x000000010546f14f -[GREYElementInteractionProxy performAction:] + 79
    4   EarlGreyExampleSwiftUITests         0x0000000105464d3b $sSo15GREYInteractionP15EarlGreyExampleE7performyxSo10GREYAction_pF + 59
    5   EarlGreyExampleSwiftUITests         0x0000000105466130 $s15EarlGreyExample0abC12SwiftUITestsC17testCustomMatcheryyF + 608
    6   EarlGreyExampleSwiftUITests         0x000000010546637b $s15EarlGreyExample0abC12SwiftUITestsC17testCustomMatcheryyFTo + 43
    7   CoreFoundation                      0x00007fff23e44c4c __invoking___ + 140
    8   CoreFoundation                      0x00007fff23e41e31 -[NSInvocation invoke] + 321
    9   EarlGreyExampleSwiftUITests         0x000000010547c168 -[GREYTestCaseInvocation invoke] + 104
    10  XCTest                              0x0000000103463037 __24-[XCTestCase invokeTest]_block_invoke_2 + 52
    11  XCTest                              0x0000000103462fe3 __24-[XCTestCase invokeTest]_block_invoke.206 + 320
    12  XCTest                              0x00000001034bddc2 +[XCTestCase(Failures) performFailableBlock:testCase:testCaseRun:shouldInterruptTest:] + 69
    13  XCTest                              0x00000001034bdcd4 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 115
    14  XCTest                              0x00000001034629f6 -[XCTestCase invokeTest] + 1183
    15  EarlGreyExampleSwiftUITests         0x00000001054844f0 -[XCTestCase(GREYTest) grey_invokeTest] + 992
    16  XCTest                              0x0000000103464329 __26-[XCTestCase performTest:]_block_invoke_2 + 43
    17  XCTest                              0x00000001034bddc2 +[XCTestCase(Failures) performFailableBlock:testCase:testCaseRun:shouldInterruptTest:] + 69
    18  XCTest                              0x00000001034bdcd4 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 115
    19  XCTest                              0x0000000103464260 __26-[XCTestCase performTest:]_block_invoke.359 + 86
    20  XCTest                              0x00000001034d0a0d +[XCTContext runInContextForTestCase:block:] + 211
    21  XCTest                              0x0000000103463b14 -[XCTestCase performTest:] + 566
    22  XCTest                              0x00000001034aa38e -[XCTest runTest] + 57
    23  XCTest                              0x000000010345dd50 __27-[XCTestSuite performTest:]_block_invoke + 354
    24  XCTest                              0x000000010345d4a2 __59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 24
    25  XCTest                              0x00000001034d0a0d +[XCTContext runInContextForTestCase:block:] + 211
    26  XCTest                              0x000000010345d459 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 148
    27  XCTest                              0x000000010345d7be -[XCTestSuite performTest:] + 348
    28  XCTest                              0x00000001034aa38e -[XCTest runTest] + 57
    29  XCTest                              0x000000010345dd50 __27-[XCTestSuite performTest:]_block_invoke + 354
    30  XCTest                              0x000000010345d4a2 __59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 24
    31  XCTest                              0x00000001034d0a0d +[XCTContext runInContextForTestCase:block:] + 211
    32  XCTest                              0x000000010345d459 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 148
    33  XCTest                              0x000000010345d7be -[XCTestSuite performTest:] + 348
    34  XCTest                              0x00000001034aa38e -[XCTest runTest] + 57
    35  XCTest                              0x000000010345dd50 __27-[XCTestSuite performTest:]_block_invoke + 354
    36  XCTest                              0x000000010345d4a2 __59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 24
    37  XCTest                              0x00000001034d0a0d +[XCTContext runInContextForTestCase:block:] + 211
    38  XCTest                              0x000000010345d459 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 148
    39  XCTest                              0x000000010345d7be -[XCTestSuite performTest:] + 348
    40  XCTest                              0x00000001034aa38e -[XCTest runTest] + 57
    41  XCTest                              0x00000001034dff14 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 171
    42  XCTest                              0x00000001034e0001 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke.100 + 96
    43  XCTest                              0x0000000103478746 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 682
    44  XCTest                              0x00000001034dfc9f -[XCTTestRunSession runTestsAndReturnError:] + 615
    45  XCTest                              0x0000000103441744 -[XCTestDriver runTestsAndReturnError:] + 456
    46  XCTest                              0x00000001034cc64c _XCTestMain + 2496
    47  EarlGreyExampleSwiftUITests-Runner  0x000000010324ee1a -[_XCTRunnerAppDelegate applicationWillResignActive:] + 0
    48  EarlGreyExampleSwiftUITests-Runner  0x000000010324ed18 _XCTRunnerRunTests + 0
    49  CoreFoundation                      0x00007fff23da1a9c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
    50  CoreFoundation                      0x00007fff23da1193 __CFRunLoopDoBlocks + 195
    51  CoreFoundation                      0x00007fff23d9bf83 __CFRunLoopRun + 995
    52  CoreFoundation                      0x00007fff23d9b884 CFRunLoopRunSpecific + 404
    53  GraphicsServices                    0x00007fff38b5ac1a GSEventRunModal + 139
    54  UIKitCore                           0x00007fff48c19220 UIApplicationMain + 1605
    55  EarlGreyExampleSwiftUITests-Runner  0x000000010324efd5 main + 183
    56  libdyld.dylib                       0x00007fff519b910d start + 1
)

Screenshots: {
  "Screenshot At Failure" : <UIImage:0x6000003ccbd0 anonymous {414, 896}>
}

UI Hierarchy (ordered by window level, front to back):

Legend: {
  "[Window 1]" : "Frontmost Window",
  "[AX]" : "Accessibility",
  "[UIE]" : "User Interaction Enabled"
}

========== Window 1 ==========

<UITextEffectsWindow:0x7faa256250b0; isAccessible=N; AX.frame={{0, 0}, {414, 896}}; AX.activationPoint={207, 448}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 896}}; alpha=1>
  |--<UIInputSetContainerView:0x7faa2780ea50; isAccessible=N; AX.frame={{0, 0}, {414, 896}}; AX.activationPoint={207, 448}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 896}}; opaque; alpha=1>
  |  |--<UIEditingOverlayGestureView:0x7faa27c0cec0; isAccessible=N; AX.frame={{0, 0}, {414, 896}}; AX.activationPoint={207, 448}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 896}}; opaque; alpha=1>
  |  |--<UIInputSetHostView:0x7faa27810db0; isAccessible=N; AX.frame={{0, 896}, {414, 0}}; AX.activationPoint={207, 896}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 896}, {414, 0}}; opaque; alpha=1>

**** No Animating Views Found. ****

========== Window 2 ==========

<UIWindow:0x7faa25408850; isAccessible=N; AX.frame={{0, 0}, {414, 896}}; AX.activationPoint={207, 448}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 896}}; opaque; alpha=1>
  |--<UITransitionView:0x7faa2780fd70; isAccessible=N; AX.frame={{0, 0}, {414, 896}}; AX.activationPoint={207, 448}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 896}}; opaque; alpha=1>
  |  |--<UIDropShadowView:0x7faa27813130; isAccessible=N; AX.frame={{0, 0}, {414, 896}}; AX.activationPoint={207, 448}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 896}}; opaque; alpha=1>
  |  |  |--<UIView:0x7faa27809c40; isAccessible=N; AX.frame={{0, 0}, {414, 896}}; AX.activationPoint={207, 448}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 896}}; opaque; alpha=1>
  |  |  |  |--<UITableView:0x7faa28029e00; isAccessible=N; AX.id='table'; AX.frame={{10, 180}, {320, 716}}; AX.activationPoint={170, 538}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{10, 180}, {320, 716}}; opaque; alpha=1>
  |  |  |  |  |--<_UIScrollViewScrollIndicator:0x7faa27b090c0; isAccessible=N; AX.label='Horizontal scroll bar, 1 page'; AX.value='0%'; AX.frame={{31.333333333333332, 863}, {288, 30}}; AX.activationPoint={175.33333333333334, 891.5}; AX.traits='UIAccessibilityTraitAdjustable'; AX.focused='N'; frame={{24.333333333333343, 710}, {282, 3}}; opaque; alpha=0>
  |  |  |  |  |  |--<UIView:0x7faa27b09460; isAccessible=N; AX.frame={{34.333333333333343, 890}, {282, 3}}; AX.activationPoint={175.33333333333334, 891.5}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {282, 3}}; opaque; alpha=1>
  |  |  |  |  |--<_UIScrollViewScrollIndicator:0x7faa2780a510; isAccessible=N; AX.label='Vertical scroll bar, 6 pages'; AX.value='0%'; AX.frame={{297, 180}, {30, 716}}; AX.activationPoint={325.5, 242.33333333333334}; AX.traits='UIAccessibilityTraitAdjustable'; AX.focused='N'; frame={{314, 3}, {3, 118.66666666666667}}; opaque; alpha=0>
  |  |  |  |  |  |--<UIView:0x7faa27813900; isAccessible=N; AX.frame={{324, 183}, {3, 118.66666666666669}}; AX.activationPoint={325.5, 242.33333333333334}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {3, 118.66666666666667}}; opaque; alpha=1>
  |  |  |  |  |--<UITableViewCell:0x7faa25616f30; isAccessible=N; AX.id='Cell1'; AX.frame={{10, 180}, {320, 44}}; AX.activationPoint={170, 202}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1; text='Cell1'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa2561e340; isAccessible=N; AX.frame={{26, 223.66666666666666}, {304, 0.33333333333334281}}; AX.activationPoint={178, 223.83333333333331}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa25615040; isAccessible=N; AX.frame={{10, 180}, {320, 44}}; AX.activationPoint={170, 202}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa256174d0; isAccessible=Y; AX.label='Cell1'; AX.frame={{26, 180}, {288, 44}}; AX.activationPoint={170, 202}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell1'>
  |  |  |  |  |--<UITableViewCell:0x7faa2561f6a0; isAccessible=N; AX.id='April 22, 2020'; AX.frame={{10, 224}, {320, 44}}; AX.activationPoint={170, 246}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 44}, {320, 44}}; opaque; alpha=1; text='April 22, 2020'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b2d650; isAccessible=N; AX.frame={{26, 267.66666666666663}, {304, 0.33333333333331439}}; AX.activationPoint={178, 267.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa2561fc40; isAccessible=N; AX.frame={{10, 224}, {320, 44}}; AX.activationPoint={170, 246}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b27a50; isAccessible=Y; AX.label='April 22, 2020'; AX.frame={{26, 224}, {288, 44}}; AX.activationPoint={170, 246}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='April 22, 2020'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b2d7f0; isAccessible=N; AX.id='April 23, 2020'; AX.frame={{10, 268}, {320, 44}}; AX.activationPoint={170, 290}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 88}, {320, 44}}; opaque; alpha=1; text='April 23, 2020'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b2e070; isAccessible=N; AX.frame={{26, 311.66666666666663}, {304, 0.33333333333331439}}; AX.activationPoint={178, 311.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b2db90; isAccessible=N; AX.frame={{10, 268}, {320, 44}}; AX.activationPoint={170, 290}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b296c0; isAccessible=Y; AX.label='April 23, 2020'; AX.frame={{26, 268}, {288, 44}}; AX.activationPoint={170, 290}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='April 23, 2020'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b2e210; isAccessible=N; AX.id='April 24, 2020'; AX.frame={{10, 312}, {320, 44}}; AX.activationPoint={170, 334}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 132}, {320, 44}}; opaque; alpha=1; text='April 24, 2020'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b2a210; isAccessible=N; AX.frame={{26, 355.66666666666663}, {304, 0.33333333333331439}}; AX.activationPoint={178, 355.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b2e5b0; isAccessible=N; AX.frame={{10, 312}, {320, 44}}; AX.activationPoint={170, 334}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b2e910; isAccessible=Y; AX.label='April 24, 2020'; AX.frame={{26, 312}, {288, 44}}; AX.activationPoint={170, 334}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='April 24, 2020'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b2a3b0; isAccessible=N; AX.id='April 25, 2020'; AX.frame={{10, 356}, {320, 44}}; AX.activationPoint={170, 378}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 176}, {320, 44}}; opaque; alpha=1; text='April 25, 2020'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b28620; isAccessible=N; AX.frame={{26, 399.66666666666663}, {304, 0.33333333333331439}}; AX.activationPoint={178, 399.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b2a750; isAccessible=N; AX.frame={{10, 356}, {320, 44}}; AX.activationPoint={170, 378}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b28200; isAccessible=Y; AX.label='April 25, 2020'; AX.frame={{26, 356}, {288, 44}}; AX.activationPoint={170, 378}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='April 25, 2020'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b287c0; isAccessible=N; AX.id='April 26, 2020'; AX.frame={{10, 400}, {320, 44}}; AX.activationPoint={170, 422}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 220}, {320, 44}}; opaque; alpha=1; text='April 26, 2020'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b2f8f0; isAccessible=N; AX.frame={{26, 443.66666666666669}, {304, 0.33333333333331439}}; AX.activationPoint={178, 443.83333333333337}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b29be0; isAccessible=N; AX.frame={{10, 400}, {320, 44}}; AX.activationPoint={170, 422}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b2f650; isAccessible=Y; AX.label='April 26, 2020'; AX.frame={{26, 400}, {288, 44}}; AX.activationPoint={170, 422}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='April 26, 2020'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b2fa90; isAccessible=N; AX.id='April 27, 2020'; AX.frame={{10, 444}, {320, 44}}; AX.activationPoint={170, 466}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 264}, {320, 44}}; opaque; alpha=1; text='April 27, 2020'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b305b0; isAccessible=N; AX.frame={{26, 487.66666666666669}, {304, 0.33333333333331439}}; AX.activationPoint={178, 487.83333333333337}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b2fe30; isAccessible=N; AX.frame={{10, 444}, {320, 44}}; AX.activationPoint={170, 466}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b30190; isAccessible=Y; AX.label='April 27, 2020'; AX.frame={{26, 444}, {288, 44}}; AX.activationPoint={170, 466}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='April 27, 2020'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b30750; isAccessible=N; AX.id='April 28, 2020'; AX.frame={{10, 488}, {320, 44}}; AX.activationPoint={170, 510}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 308}, {320, 44}}; opaque; alpha=1; text='April 28, 2020'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b31270; isAccessible=N; AX.frame={{26, 531.66666666666674}, {304, 0.33333333333337123}}; AX.activationPoint={178, 531.83333333333348}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b30af0; isAccessible=N; AX.frame={{10, 488}, {320, 44}}; AX.activationPoint={170, 510}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b30e50; isAccessible=Y; AX.label='April 28, 2020'; AX.frame={{26, 488}, {288, 44}}; AX.activationPoint={170, 510}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='April 28, 2020'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b31410; isAccessible=N; AX.id='Cell9'; AX.frame={{10, 532}, {320, 44}}; AX.activationPoint={170, 554}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 352}, {320, 44}}; opaque; alpha=1; text='Cell9'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b31f30; isAccessible=N; AX.frame={{26, 575.66666666666674}, {304, 0.33333333333337123}}; AX.activationPoint={178, 575.83333333333348}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b317b0; isAccessible=N; AX.frame={{10, 532}, {320, 44}}; AX.activationPoint={170, 554}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b31b10; isAccessible=Y; AX.label='Cell9'; AX.frame={{26, 532}, {288, 44}}; AX.activationPoint={170, 554}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell9'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b322d0; isAccessible=N; AX.id='Cell10'; AX.frame={{10, 576}, {320, 44}}; AX.activationPoint={170, 598}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 396}, {320, 44}}; opaque; alpha=1; text='Cell10'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b32df0; isAccessible=N; AX.frame={{26, 619.66666666666674}, {304, 0.33333333333337123}}; AX.activationPoint={178, 619.83333333333348}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b32670; isAccessible=N; AX.frame={{10, 576}, {320, 44}}; AX.activationPoint={170, 598}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b329d0; isAccessible=Y; AX.label='Cell10'; AX.frame={{26, 576}, {288, 44}}; AX.activationPoint={170, 598}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell10'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b32f90; isAccessible=N; AX.id='Cell11'; AX.frame={{10, 620}, {320, 44}}; AX.activationPoint={170, 642}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 440}, {320, 44}}; opaque; alpha=1; text='Cell11'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b33ab0; isAccessible=N; AX.frame={{26, 663.66666666666674}, {304, 0.33333333333337123}}; AX.activationPoint={178, 663.83333333333348}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b33330; isAccessible=N; AX.frame={{10, 620}, {320, 44}}; AX.activationPoint={170, 642}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b33690; isAccessible=Y; AX.label='Cell11'; AX.frame={{26, 620}, {288, 44}}; AX.activationPoint={170, 642}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell11'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b33c50; isAccessible=N; AX.id='Cell12'; AX.frame={{10, 664}, {320, 44}}; AX.activationPoint={170, 686}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 484}, {320, 44}}; opaque; alpha=1; text='Cell12'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b34770; isAccessible=N; AX.frame={{26, 707.66666666666663}, {304, 0.33333333333337123}}; AX.activationPoint={178, 707.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b33ff0; isAccessible=N; AX.frame={{10, 664}, {320, 44}}; AX.activationPoint={170, 686}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b34350; isAccessible=Y; AX.label='Cell12'; AX.frame={{26, 664}, {288, 44}}; AX.activationPoint={170, 686}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell12'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b34910; isAccessible=N; AX.id='Cell13'; AX.frame={{10, 708}, {320, 44}}; AX.activationPoint={170, 730}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 528}, {320, 44}}; opaque; alpha=1; text='Cell13'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b35430; isAccessible=N; AX.frame={{26, 751.66666666666663}, {304, 0.33333333333337123}}; AX.activationPoint={178, 751.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b34cb0; isAccessible=N; AX.frame={{10, 708}, {320, 44}}; AX.activationPoint={170, 730}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b35010; isAccessible=Y; AX.label='Cell13'; AX.frame={{26, 708}, {288, 44}}; AX.activationPoint={170, 730}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell13'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b355d0; isAccessible=N; AX.id='Cell14'; AX.frame={{10, 752}, {320, 44}}; AX.activationPoint={170, 774}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 572}, {320, 44}}; opaque; alpha=1; text='Cell14'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b36220; isAccessible=N; AX.frame={{26, 795.66666666666663}, {304, 0.33333333333337123}}; AX.activationPoint={178, 795.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b35970; isAccessible=N; AX.frame={{10, 752}, {320, 44}}; AX.activationPoint={170, 774}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b35cd0; isAccessible=Y; AX.label='Cell14'; AX.frame={{26, 752}, {288, 44}}; AX.activationPoint={170, 774}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell14'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b363c0; isAccessible=N; AX.id='Cell15'; AX.frame={{10, 796}, {320, 44}}; AX.activationPoint={170, 818}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 616}, {320, 44}}; opaque; alpha=1; text='Cell15'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b37120; isAccessible=N; AX.frame={{26, 839.66666666666663}, {304, 0.33333333333337123}}; AX.activationPoint={178, 839.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b36760; isAccessible=N; AX.frame={{10, 796}, {320, 44}}; AX.activationPoint={170, 818}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b36d00; isAccessible=Y; AX.label='Cell15'; AX.frame={{26, 796}, {288, 44}}; AX.activationPoint={170, 818}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell15'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b372c0; isAccessible=N; AX.id='Cell16'; AX.frame={{10, 840}, {320, 44}}; AX.activationPoint={170, 862}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 660}, {320, 44}}; opaque; alpha=1; text='Cell16'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b37de0; isAccessible=N; AX.frame={{26, 883.66666666666663}, {304, 0.33333333333337123}}; AX.activationPoint={178, 883.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b37660; isAccessible=N; AX.frame={{10, 840}, {320, 44}}; AX.activationPoint={170, 862}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b379c0; isAccessible=Y; AX.label='Cell16'; AX.frame={{26, 840}, {288, 44}}; AX.activationPoint={170, 862}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell16'>
  |  |  |  |  |--<UITableViewCell:0x7faa27b37f80; isAccessible=N; AX.id='Cell17'; AX.frame={{10, 884}, {320, 44}}; AX.activationPoint={170, 906}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 704}, {320, 44}}; opaque; alpha=1; text='Cell17'>
  |  |  |  |  |  |--<_UITableViewCellSeparatorView:0x7faa27b38aa0; isAccessible=N; AX.frame={{26, 927.66666666666663}, {304, 0.33333333333337123}}; AX.activationPoint={178, 927.83333333333326}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{16, 43.666666666666664}, {304, 0.33333333333333331}}; opaque; alpha=1>
  |  |  |  |  |  |--<UITableViewCellContentView:0x7faa27b38320; isAccessible=N; AX.frame={{10, 884}, {320, 44}}; AX.activationPoint={170, 906}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {320, 44}}; opaque; alpha=1>
  |  |  |  |  |  |  |--<UITableViewLabel:0x7faa27b38680; isAccessible=Y; AX.label='Cell17'; AX.frame={{26, 884}, {288, 44}}; AX.activationPoint={170, 906}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{16, 0}, {288, 44}}; opaque; alpha=1; UIE=N; text='Cell17'>
  |  |  |  |--<UIButton:0x7faa2780bb80; isAccessible=Y; AX.id='Send'; AX.label='SendForLayoutTest'; AX.frame={{130, 40}, {100, 30}}; AX.activationPoint={180, 55}; AX.traits='UIAccessibilityTraitButton'; AX.focused='N'; frame={{130, 40}, {100, 30}}; alpha=1>
  |  |  |  |  |--<UIButtonLabel:0x7faa2790a720; isAccessible=N; AX.label='Send'; AX.frame={{162, 46}, {36, 18}}; AX.activationPoint={180, 55}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{32, 6}, {36, 18}}; alpha=1; UIE=N; text='Send'>
  |  |  |  |--<UIButton:0x7faa2780acd0; isAccessible=Y; AX.id='ClickMe'; AX.label='ClickMe'; AX.frame={{10, 40}, {100, 30}}; AX.activationPoint={60, 55}; AX.traits='UIAccessibilityTraitButton'; AX.focused='N'; frame={{10, 40}, {100, 30}}; alpha=1>
  |  |  |  |  |--<UIButtonLabel:0x7faa25616c90; isAccessible=N; AX.label='ClickMe'; AX.frame={{32.666666666666671, 46}, {55, 18}}; AX.activationPoint={60.166666666666671, 55}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{22.666666666666671, 6}, {55, 18}}; alpha=1; UIE=N; text='ClickMe'>
  |  |  |  |--<EarlGreyExampleSwift.SendMessageView:0x7faa27809a40; isAccessible=N; AX.frame={{0, 0}, {0, 0}}; AX.activationPoint={0, 0}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {0, 0}}; opaque; alpha=1>
  |  |  |  |  |--<UIButton:0x7faa2780c450; isAccessible=Y; AX.id='Send'; AX.label='Send'; AX.frame={{10, 110}, {100, 30}}; AX.activationPoint={60, 125}; AX.traits='UIAccessibilityTraitButton'; AX.focused='N'; frame={{10, 110}, {100, 30}}; alpha=1>
  |  |  |  |  |  |--<UIButtonLabel:0x7faa27b397b0; isAccessible=N; AX.label='Send'; AX.frame={{42, 116}, {36, 18}}; AX.activationPoint={60, 125}; AX.traits='UIAccessibilityTraitStaticText'; AX.focused='N'; frame={{32, 6}, {36, 18}}; alpha=1; UIE=N; text='Send'>
  |  |  |  |--<_UILayoutGuide:0x7faa2780a140; isAccessible=N; AX.frame={{0, 862}, {0, 34}}; AX.activationPoint={0, 879}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 862}, {0, 34}}; opaque; hidden; alpha=1>
  |  |  |  |--<_UILayoutGuide:0x7faa27809db0; isAccessible=N; AX.frame={{0, 0}, {0, 44}}; AX.activationPoint={0, 22}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {0, 44}}; opaque; hidden; alpha=1>
chan-park commented 4 years ago

Sorry about the late response. Can you put a breakpoint and see what type the element is in the following line?

      if let cell = element as? UITableViewCell {

I would guess this is an EDOObject. To give you an overview of EarlGrey 2.0, EarlGrey 2.0 is a multi-process architecture where the test process and application process talks to each other through our IPC library called 'eDistantObject' to perform the tests. Basically, eDistantObject wraps around objects with EDOObject when they are sending messages to each other. By instantiating the matcher on the test as in your example, when the matching happens, it's essentially doing an IPC call to the test side by wrapping the element with EDOObject. So when you are trying to cast it to a UITableViewCell, it's going to fail. Currently we do not support this behavior.

One way around this is to create the matcher on the application side and link it to the application. This is a better approach when creating custom matchers for a few reasons (1) you don't have the issue explained above because the element is not being sent over IPC. (2) it's more performant when testing because you're not doing an IPC call when matching. EarlGrey goes through all elements in your app hierarchy and calls matches for each of them. So if each of these calls is an IPC call, it's going to be a lot of overhead.

To create a custom matcher on the application, you might want to read this doc about white-boxing.

Let me know if you have any question!

joolurik commented 4 years ago

@chan-park Can you give us an example, As the white-box guide is not self-explanatory. I am trying implement below custom matcher


public func grey_accessibilityLabelContains(text subString: String, _ ignoreCase: Bool = true) -> GREYMatcher {
    let matches: GREYMatchesBlock = { (element: Any) -> Bool in
        let viewElement = element as? UIView
        guard let label: String = viewElement?.accessibilityLabel else { return false }
        return ignoreCase ? label.localizedCaseInsensitiveContains(subString) : label.contains(subString)
        } 

    let description: GREYDescribeToBlock = { (description: GREYDescription!) -> Void in
        guard let description = description else {
            return
        }
        let descriptionText:String = "accessibility label contains text " + subString + " with case ignorance " + ignoreCase.description
        description.appendText(descriptionText)
    }

    return GREYElementMatcherBlock.init(matchesBlock: matches, descriptionBlock: description)
}