How to query labels in Xcode UI testing - xcode-ui-testing

I see I can query textfields, tables, buttons, but not labels, why?
app.textFields["Username"].typeText("bcyops")
app.secureTextFields["Password"].typeText("ops15")
app.buttons["Submit"].tap()
app.tabBars.buttons["Main"].tap()
let tablesQuery = app.tables

If you mean label as static text element, you can query label:
let label = app.staticTexts["yourLabelIdentifier"]
If you need a text in the label
let textInLabel = app.staticTexts["yourLabelIdentifier"].label
documentation with all elements types is here: https://developer.apple.com/documentation/xctest/xcuielementtypequeryprovider

Labels are referred to as staticTexts in XCTest UI testing.
app.staticTexts["myLabel"].exists

You can use NSPredicates to query elements with specified labels:
app.textViews.element(matching: NSPredicate(format: "label LIKE theLabelYoureLookingFor"))

Related

Xcode UITest scrolling to the bottom of an UITableView

I am writing an UI test case, in which I need to perform an action, and then on the current page, scroll the only UITableView to the bottom to check if specific text shows up inside the last cell in the UITableView.
Right now the only way I can think of is to scroll it using app.tables.cells.element(boundBy: 0).swipeUp(), but if there are too many cells, it doesn't scroll all the way to the bottom. And the number of cells in the UITableView is not always the same, I cannot swipe up more than once because there might be only one cell in the table.
One way you could go about this is by getting the last cell from the tableView. Then, run a while loop that scrolls and checks to see if the cell isHittable between each scroll. Once it's determined that isHittable == true, the element can then be asserted against.
https://developer.apple.com/documentation/xctest/xcuielement/1500561-ishittable
It would look something like this (Swift answer):
In your XCTestCase file, write a query to identify the table. Then, a subsequent query to identify the last cell.
let tableView = app.descendants(matching: .table).firstMatch
guard let lastCell = tableView.cells.allElementsBoundByIndex.last else { return }
Use a while loop to determine whether or not the cell isHittable/is on screen. Note: isHittable relies on the cell's userInteractionEnabled property being set to true
//Add in a count, so that the loop can escape if it's scrolled too many times
let MAX_SCROLLS = 10
var count = 0
while lastCell.isHittable == false && count < MAX_SCROLLS {
apps.swipeUp()
count += 1
}
Check the cell's text using the label property, and compare it against the expected text.
//If there is only one label within the cell
let textInLastCell = lastCell.descendants(matching: .staticText).firstMatch
XCTAssertTrue(textInLastCell.label == "Expected Text" && textInLastCell.isHittable)
Blaines answer lead me to dig a little bit more into this topic and I found a different solution that worked for me:
func testTheTest() {
let app = XCUIApplication()
app.launch()
// Opens a menu in my app which contains the table view
app.buttons["openMenu"].tap()
// Get a handle for the tableView
let listpagetableviewTable = app.tables["myTableView"]
// Get a handle for the not yet existing cell by its content text
let cell = listpagetableviewTable.staticTexts["This text is from the cell"]
// Swipe down until it is visible
while !cell.exists {
app.swipeUp()
}
// Interact with it when visible
cell.tap()
}
One thing I had to do for this in order to work is set isAccessibilityElement to true and also assign accessibilityLabel as a String to the table view so it can be queried by it within the test code.
This might not be best practice but for what I could see in my test it works very well. I don't know how it would work when the cell has no text, one might be able to reference the cell(which is not really directly referenced here) by an image view or something else. It's obviously missing the counter from Blaines answer but I left it out for simplicity reasons.

Tornadofx Tableview row count

Hey guys can someone please enlighten me. what is the best way to have a label display SortedFilteredList size. I have a tableview and I want a label showing the current table row count while filtering using filterwhen
All you need to do is to create a StringBinding towards the sizeProperty of the SortedFilteredList. I've added an example to the TableViewSortFilterTest in the framework, check out https://github.com/edvin/tornadofx/blob/master/src/test/kotlin/tornadofx/testapps/TableViewSortFilterTest.kt for a complete example. Here I add an informational hbox to the bottom of the screen:
hbox(5) {
label("Filter count:")
label(data.sizeProperty.stringBinding { "$it records matching filter" })
}
The data property is my SortedFilteredList instance.

NSTableView with two custom table cell views alternating per row (MacOS)

I have a single column, view-based NSTableView in which I want to place two different custom cell views, one alternating with the other in each row, like so:
Odd rows: OddRowNumberCellView.
Even rows: EvenRowNumberCellView.
There a solution for iOS from Natasha in her highly rated answer UITableview with more than One Custom Cells with Swift but it depends on the Dynamic Prototypes setting in the Attributes Inspector, a feature that is not available for MacOS.
Does anyone know how to do this on Mac please? (I'm on macOS Sierra 10.12.4.)
You do exactly the same but instead of Dynamic Protoypes you set an Identifier "OddRow" or "EvenRow" and then in your datasource implementation:
if indexPath.row % 2 == 0 {
let cellView: tableView.make(withIdentifier: "EvenRow")
//set the data here
return cellView
} else {
let cellView: tableView.make(withIdentifier: "OddRow")
//set the data here
return cellView
}

UI Testing in Xcode 7: Selecting a row number in a UIPickerView / PickerWheel

Is there a way in Xcode 7 UI Testing to select the 3rd row in a UIPickerView?
I have tried various things like this to identify the rows in each picker but all the requests below return 0 found:
XCUIApplication().pickers.element.cells.count
XCUIApplication().pickers.element.staticTexts.count
Any ideas?
Updated: I am aware of adjustToPickerWheelValue method where you can select a particular value you already know, but I am trying to select the 3rd value (index = 4) when I don't know the values that exist in the picker.
You can use -adjustToPickerWheelValue: to select items on a UIPickerView.
When there is one UIPickerView on the screen you can select the element directly, like so.
let app = XCUIApplication()
app.launch()
app.pickerWheels.element.adjustToPickerWheelValue("Books")
If the picker has multiple wheels you will need to first select the wheel via it's accessibility identifier, then adjust it.
app.pickerWheels["Feet"].adjustToPickerWheelValue("5")
Here's a GitHub repo with a working example. And some more information in a blog post I wrote.
Workaround:
let pickerWheel = XCUIApplication().pickers.pickerWheels.element
let appWindowHeight = XCUIApplication().windows.elementBoundByIndex(0).frame.height
let pickerWheelCellHeight = GFloat(44)
func advancePickerWheelOneValue() -> Self {
let topScrollPoint = Double(pickerWheel.frame.midY/appWindowHeight)
let bottomScrollPoint = Double((pickerWheel.frame.midY + pickerWheelCellHeight)/appWindowHeight)
let topScreenPoint = XCUIApplication().windows.elementBoundByIndex(0).coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: topScrollPoint))
let bottomScreenPoint = XCUIApplication().windows.elementBoundByIndex(0).coordinateWithNormalizedOffset(CGVector(dx: 0.5, dy: bottomScrollPoint))
bottomScreenPoint.pressForDuration(0, thenDragToCoordinate: topScreenPoint)
return self
}
You may need to adjust the dx value depending on where the picker is.
.coordinateWithNormalizedOffset(CGVector(dx: 0.5,
But 0.5 works if the picker occupies the width of the screen.
With this method you an move the picker on value at a time. Call it multiple times and you get to the value you want.
Its not ideal but it can help if you want to check certain indexes. Hopefully you would have to use it on a picker with hundreds of values ;)
Example with Date picker (UIDatePicker)
XCUIApplication().datePickers.pickerWheels.elementBoundByIndex(0).adjustToPickerWheelValue("March")
XCUIApplication().datePickers.pickerWheels.elementBoundByIndex(1).adjustToPickerWheelValue("24")
XCUIApplication().datePickers.pickerWheels.elementBoundByIndex(2).adjustToPickerWheelValue("2000")
And here is example with Picker view (UIPickerView)
XCUIApplication().pickerWheels.element.adjustToPickerWheelValue("Male")

How to select object at index in WP7?

I have an array that has specified colors like this,
Object[] l_colarray = new Object[13] { Colors.Black,Colors.Blue,Colors.Brown,Colors.Cyan,Colors.DarkGray,
Colors.Gray,Colors.Green,Colors.LightGray,Colors.Magenta,Colors.Orange,Colors.Purple,Colors.Red,Colors.White};
How do i select an index,(objectatindex:i, was used in iOS). Kindly help me with this.
Thanks,
It's not really clear what you mean by "select an index". Do you mean simply:
object color = l_colarray[index];
? Note that if all the values are Color values you'd be better off with:
Color[] colors = { Colors.Black, Colors.Blue, Colors.Brown, Colors.Cyan,
Colors.DarkGray, Colors.Gray, Colors.Green, Colors.LightGray,
Colors.Magenta, Colors.Orange,Colors.Purple,Colors.Red,Colors.White };
...
Color color = colors[index];
Notes:
When you're initializing an array variable in the same statement as its declaration, you don't need the "new TypeName[]" part
You don't need to specify the size when you use "new TypeName[] { ... }"
Assuming you are talking about selecting in a ui...
There's an excellent q&a set of info for listbox and selecteditem (and selectedindex) at http://www.windowsphonegeek.com/tips/WP7-ListBox-SelectedItem
The answer you need depends on how you are entering sata into the list box - e.g. Are you using databinding.
At a simple level, if you're using codebehind to manipulate the list box then you can use:
ListBox1.SelectedIndex = 6;
If you are talking about objective-c language level selecting... Then you can just use array accessors in c#:
var item = l_colarray[6];
One good place To start on iOS to wp7 porting is http://wp7mapping.interoperabilitybridges.com/library

Resources