How to find button with predicate under UITests in Xcode7? - swift

I need to access following button:
This line works fine:
app.buttons["Reorder 1, $27 000, LondonStreet, ok, Pending"]
but this don't:
app.buttons.elementMatchingPredicate(NSPredicate(format: "accessibilityTitle BEGINSWITH[cd] %#", "Reorder 1"))

When finding elements via predicates you must use the XCUIElementAttributes Protocol. For this example, I don't think title will actually work, but try using label (which should map to accessibilityLabel).
For some reason the %# format option doesn't seem to work in Swift. Also note the extra single quotes around "Reorder 1".
let predicate = NSPredicate(format: "label BEGINSWITH[cd] 'Reorder 1'")
let button = app.buttons.elementMatchingPredicate(predicate)

Related

Having issues retrieving values from a Multiple Selector Row

I've been trying to figure this one out all day and have been unsuccessful. What I'm trying to do is retrieve selected values from a multiple selector row. The row so far is fully functioning and I've been able to set it up so that my options are structs.
The problem I'm having is towards the end when I need to retrieve the data from the form. I'm able to use form.values() and know how to work with the dictionary for the most part.
When I call for the values in the multi-row, they come through as 'Sets'. I am still relatively new to Swift so I hadn't dealt with these before, but from what I've read so far they are collection types like Arrays?
this is the part that is giving me issues:
//
<<< ButtonRow("btnnRow") { row in
row.title = "Confirm selection."
row.onCellSelection({ (cell, row) in
let formValues = self.form.values()
let koko = formValues["multiSelectTest"] as! Set<MultiTestStruct>
switch koko.isEmpty {
case true:
print("Set is empty")
case false:
print("Set is NOT empty!")
}
})
}
This is the latest iteration of what I've attempted. It's able to print 'empty' on first load, but as soon as I select an option and unselect it again, crash!
I think I'm having problems after selection because when I print all values, it's initially "multiSelectTest": nil, but after making a selection in the Multi-row then unselecting it, this is what it turns into: "multiSelectTest": Optional(Set([])).
Apologies if this makes no sense, I'd be happy to explain further if needed, it's currently 2am and my brain is pretty frazzled!
TL:DR - How to get values from a multiple selection row.
Thank you for reading.
Update: error message- Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value - I get this error if I try to get the rows value before selecting and unselecting. Once selection has been toggled, there is no issue.
This is the console output of all values prior to making a selection:
["btnRow": nil, "btnRow2": nil, "multiSelectTest": nil]
This is the console output after selecting an option:
["btnRow": nil, "btnRow2": nil, "multiSelectTest": Optional(Set([theDD_Admin.MultiTestStruct(name: "HELLO!")]))]
And finally, this is after I've cleared the multi-row of all options:
["btnRow": nil, "btnRow2": nil, "multiSelectTest": Optional(Set([]))]
My main plan of action was to call for the multi-row values if multi was nil but as you can see it is only nil whilst untouched. After making an option an even unselecting, it turns into a set and I get lost from there.
thanks
From #koropok's comment, this is what I've managed to come up with. In the multi-row, I set the .onChange behaviour -
row.onChange({ (row) in
if row.value?.isEmpty == true {
// if row Set<> is empty then this row will be cleared and set to nil
self.form.setValues(["multiSelectTest" : nil])
}
})
I was running into an error when I tried to do row.value = nil and this way is working as intended.
This is what I've come up with and is working well for me so far. For those with more experience than I, is this the correct/best approach? Would like to know if anyone would do anything differently.
Thanks again!

How to apply an NSPredicate to a custom XLForm row?

I have a row of type XLFormRowDescriptionTypeSelectorPush
I set row.value to a custom class Agreement and row.addValidator(AgreementValidator())
I want another to be hidden/shown depending upon the value of Agreement.agree (which is "Accepted" or "Declined").
I can't figure out how to do this. Here's where I am so far:
other_row.hidden = NSPredicate(format:"$other_tag.value != "Accepted")
But the value of the other_tag row is Agreement and not a string. How can I compare with Agreement.agree?
Try this.
other_row.hidden = NSPredicate(format: "NOT $other_tag.value.agree != 'Accepted'")

Swift: String Concatenation for Outlet names

I'm looking to reduce the number of lines in my code, I have quite a lot of label names that correspond to their values. I was wondering if there is a way of setting these values in a for-in loop or something similar. Right now I'm struggling to find a way of concatenating the label names to make them dynamic. I'm not sure if I'm able to do this in Swift, any thoughts? Thanks.
This code
LabelGiraffe1.text = "This is Giraffe 1"
LabelGiraffe2.text = "This is Giraffe 2"
LabelGiraffe3.text = "This is Giraffe 3"
LabelGiraffe4.text = "This is Giraffe 4"
LabelGiraffe5.text = "This is Giraffe 5"
To something cleaner like...
for number in 1...5 {
LabelGiraffe + /(number).text = "This is Giraffe /(number)"
}
Make an array of labels and over them:
let giraffeLabels = [LabelGiraffe1, LabelGiraffe2, LabelGiraffe3, LabelGiraffe4, LabelGiraffe5]
for (index, label) in enumerate(giraffeLabels) {
label.text = "This is Giraffe \(index + 1)"
}
You can also make giraffeLabels as stored or calculated property of your view controller.
Use an IBOutletCollection. It's effectively like putting all your outlets into an array (which is what it does in the background, I believe). You can then iterate over them, or access them by index, as you're trying to do.
More information here: http://nshipster.com/ibaction-iboutlet-iboutletcollection/

iPhone Objective-C Form Validation

I am an old developer but new to Objective-C and iPhone development. I am looking for the best way to do form validation for values entered. I have been googling for a while and can't find any good code, but might be using the wrong key worrds, etc... I am looking for things like catching for empty string, numeric validation, date validation, etc... where it catches this either while the user is entering data (input mask type) or on the lost focus of the control.
If you can point me to some good resources that would be great!
Thanks!
Simon.
I don't know particular resources but you could begin usin NSPredicate to validate fields with regular expressions. For example, for mail validation
BOOL result;
NSString* emailRegex = #"[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
NSPredicate* emailTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
result = [emailTest evaluateWithObject:anEmailAddress];
The emailRegex suggested by Espuz has a slight problem. The range operator "-" within the [] brackets should be escaped otherwise emails having "-" character are returned as invalid.
I am using the following regex string for pattern matching that allows "_", "-" and "." characters in the address:
NSString *emailRegex = #"[a-zA-Z0-9.\\-_]{2,32}#[a-zA-Z0-9.\\-_]{2,32}\.[A-Za-z]{2,4}";
NSPredicate *regExPredicate =
[NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
BOOL validEmail = [regExPredicate evaluateWithObject:txtField.text];

Core Data Predicates with Subclassed NSManagedObjects

I have an AUDIO class. This audio has a SOUND_A subclass and a SOUND_B subclass. This is all done correctly and is working fine.
I have another model, lets call it PLAYLIST_JOIN, and this can contain (in the real world) SOUND_A's and SOUND_B's, so we give it a relationship of AUDIO and PLAYLIST.
This all works in the app.
The problem I am having now is querying the PLAYLIST_JOIN table with an NSPredicate. What I want to do is find an exact PLAYLIST_JOIN item by giving it 2 keys in the predicate
sound_a._sound_a_id = %# && playlist.playlist_id = %#
and
sound_b.sound_b_id = %# && playlist.playlist_id = %#
The main problem is that because the table does not store sound_a and sound_b, but stored audio, I cannot use this syntax. I do not have the option of reorganizing the sound_a and sound_b to use the same _id attribute name, so how do I do this?
Can I pass a method to the predicate? something like this:
[audio getID] = %# && playlist_id = %#
It gets a little complicated but you need to add a third condition to the predicate:
(entity.name = sound_a && _sound_a_id = %# && playlist.playlist_id = %#) && (entity.name = sound_b && sound_b_id = %# && playlist.playlist_id = %#)
This is assuming you are querying against the audio abstract and telling it to return subclasses. Because the condition is checked left to right, if the first condition fails it will move on and not throw errors because _sound_a_id does not exist.
The first condition is referencing the NSEntityDescription that is a part of the NSManagedObject and its name attribute is just a string.