Wrap a returned Geb Navigator with an interface - functional-testing

I have a span element in a page that emulates a checkbox. Whether this "checkbox" is "checked" is set by giving the element some class.
In my Page, I've got a method that returns this element using a $() selector (I.E. a Navigator instance):
class MyPage extends page {
def getCheckbox(String searchStr) {
$("div.parent").find(".class-a", text: searchStr)
}
def myFunc() {
def cb = getCheckbox("foo")
if (cb.has(".class-B") {
// checkbox is ticked. do something...
}
}
}
I'm looking for a way to decorate the object returned from getCheckbox(), so that clients wishing to check the status of the checkbox can do cb.isChecked() instead of the more-obscure has(".class-B") (I.E to attain a similar interface to the builtin checkbox form control module)
Any suggestions?
Thanks!

Your checkbox emulating span element is a prime candidate for becoming a Geb module - simply define a module class with the methods that you want to exists on your wrapper and then pass it to the Navigator's module() method for the navigator representing your span element.

how about this:
class CheckBoxNavigator extends NonEmptyNavigator {
def isChecked(){
return this.has(".class-B")
}
}
Then you just need to define your checkBox element as a "CheckBoxNavigator" and then you can use isChecked()

Related

In Gradle, how do you perform validation of lazily evaluated properties (on extensions)?

Is there a way to validate a property value when the property is evaluated? I can't do it in the getter because that returns the Property object - I want the validation to run only when the actual value is calculated (i.e. I want to be lazy evaluation friendly).
They show extensions using the Property object here:
https://docs.gradle.org/current/userguide/lazy_configuration.html#connecting_properties_together
However, they don't explain how to do property validation when the value is calculated. Here is the snipet of code from the Gradle documentation provided example:
// A project extension
class MessageExtension {
// A configurable greeting
final Property<String> greeting
#javax.inject.Inject
MessageExtension(ObjectFactory objects) {
greeting = objects.property(String)
}
}
If I wanted to make sure the value of greeting was not equal to test, then how would I do that when it is evaluated?
For most use cases, it should be sufficient to just validate the property value once you resolve it in your task or in other internal parts of your plugin. Only a few extensions are actually designed to be consumed by other plugins or the build script.
Gradle does not provide some validation that can be attached to a property, however you can build this functionality on your own like in the example below:
class MessageExtension {
private final Property<String> _greeting
final Provider<String> greeting
#javax.inject.Inject
MessageExtension(ObjectFactory objects) {
_greeting = objects.property(String)
greeting = _greeting.map { value ->
if (value.equals('test'))
throw new RuntimeException('Invalid greeting')
return value
}
}
def setGreeting(String value) {
_greeting.set(value)
}
def setGreeting(Provider<String> value) {
_greeting.set(value)
}
}
project.extensions.create('message', MessageExtension)
message {
greeting = 'test'
}
println message.greeting.get()
I turned the Property into a backing field for a Provider that runs the validation when resolved. If you do not want to throw an exception, but just return an empty Provider, you may replace the map with a flatMap.

Difference between "def" and "static def" in Gradle

As the title, what is exactly the difference of these two defs in Groovy?
Maybe it's a documentation problem, I can't find anything...
A method declaration without static marks a method as an instance method. Whereas a declaration with static will make this method static - can be called without creating an instance of that class - see https://www.geeksforgeeks.org/static-methods-vs-instance-methods-java/
def in groovy defines a value as duck typed. The capabilities of the value are not determined by its type, they are checked at runtime. The question if you can call a method on that value is answered at runtime - see optional typing.
static def means that the method will return a duck typed value and can be called without having instance of the class.
Example:
Suppose you have these two classes:
class StaticMethodClass {
static def test(def aValue) {
if (aValue) {
return 1
}
return "0"
}
}
class InstanceMethodClass {
def test(def aValue) {
if (aValue) {
return 1
}
return "0"
}
}
You are allowed to call StaticMethodClass.test("1"), but you have to create an instance of InstanceMethodClass before you can call test - like new InstanceMethodClass().test(true).

Microsoft Bot: Show options from database instead of enums

In the example bot implementations from Microsoft, they use enums to define options for dialog, as shown in the example below:
public enum LengthOptions { SixInch, FootLong };
public enum BreadOptions { NineGrainWheat, NineGrainHoneyOat, Italian, ItalianHerbsAndCheese, Flatbread };
Can we use a normal list to fetch the values from the database and display it as options?
Thanks
You can't do this out of the box, but you could subclass FormBuilderBase<T>, overriding various methods to build the Form using whatever datasource you prefer.
Edit:
You can find the base class and implementation of FormBuilder here: https://github.com/Microsoft/BotBuilder/blob/master/CSharp/Library/FormFlow/FormBuilder.cs
Basically, there are a mess of virtual methods that you can override to customize how you want to form to behave, but the main one is Build. In the default implementation, it iterates though the enums to create a list of Field, which are basically each step in you form. Instead of that, you can iterate through whatever data you have pulled from your database and create a new Field for each item. It may look something like this:
public override IForm<T> Build(Assembly resourceAssembly = null, string resourceName = null)
{
var list = GetListOfItemsFromDatabase();
foreach (var item in _list)
{
// FieldFromItem is an IField and will also need to be created
Field(new FieldFormItem<T>(item));
}
Confirm(new PromptAttribute(_form.Configuration.Template(TemplateUsage.Confirmation)));
}
return base.Build(resourceAssembly, resourceName);
}
I know its late but found myself struggling with the same and found that below would be the right solution for this.In your FormFlow class just add the Terms and Descriptions manually.From your example if we are talking about length options then change the type of LengthOptions to string add following code when you build the form.
return new FormBuilder<SandwichForm>()
.Field(new FieldReflector<SandwichForm>(nameof(LengthOptions))
.SetDefine(async (state, field) =>
{
// Call database and get options and iterate over the options
field
.AddDescription("SixInch","Six Inch")
.AddTerms("SixInch", "Six Inch")
.AddDescription("FootLong ","Foot Long")
.AddTerms("FootLong ", "Foot Long")
return true;
}))
.OnCompletion(completionDelegate)
.Build();

Why can not I get my class methods defined as an array of instances of the index contains the variable?

That's what we have. It's Swift code:
class Process {
// Some methods and properties
}
class SomeClass {
var list: [Process]? = nil
// ...
func someFunc () {
// ...
if list !=nil {
for i in list! {
if list[i].
}
}
Inserting a point (.) in the last line, I do not get a list of methods and properties.
If I change the index i to digit, then I'll get a list of methods and properties of its class Process
How it's look like
What should I do to use a variable in the index I could use the methods of its class?
P.S. Sorry for my English, I used machine translation
With for x in y you don't have to subscript because x is not an index, it's the current iterator object:
func someFunc () {
if let list = list {
for item in list {
item.
} ^^^^ here auto-suggest will work
}
}
If the suggested methods don't work or don't make sense it's usually because you have a syntax error. Same for auto-indenting the code.
Here what you're doing is iterating the list, and expecting that to give you an index, when what it's really doing is giving you the objects in list.
So the code should simply be:
for i in list! {
if i.XXX ...
where XXX is whatever you're trying to test.

UISearchDisplayController doesn't reload data when searching only by scope

I have a UITableViewController that that use a simple SearchBar for filtering result. I'm using an array of candies with name and category and I'm using these categories as options for the scope bar of my SearchBar.
I have an utility function to apply the filter:
func filterContentForSearchText(searchText: String, scope: String = "All") {
// Filter the array using the filter method
self.filteredCandies = self.candies.filter(){( candy: Candy) -> Bool in
let categoryMatch = (scope == "All") || (candy.category == scope)
let stringMatch = candy.name.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
return categoryMatch && (stringMatch != nil)
}
}
I call this function in the searchDisplayController:shouldReloadTableForSearchScope: method and in the searchDisplayController:shouldReloadTableForSearchString: method.
If I put some text in the SearchBar everything works, even when I choose a scope from the scope bar. The problem is that when I clear the text (or when I choose a scope without put any text) the filter doesn't applied. With some debugging I saw that the array is well filtered when the tableView:cellForRowAtIndexPath: is called but the tableView simply show all the elements, not the filtered ones.
The functionality of the UISearchDisplayController is to only display the searchResultsTableView when there is text in the search bar. The best way to work around this that I have found is to create your own segmented controller to use as a scope bar and filter the actual data source for your tableview by the scope and then filter that by search text when a search string is entered.
Sorry!
I accomplished this by reloading my tableview from the delegate method.
func searchBar(searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
println("Scope Changed")
updateSearchResultsForSearchController(searchController)
}
That last function should contain code for resetting your filter / remaking your array / fetching all objects from coredata (if that's what you're doing) AND reloading your tableView.

Resources