How do I check if Geb Module "content" is present? - geb

I'm a bit new to the whole Selenium/Geb thing, so I'm probably going about this a bit wrong, but I'm trying to get the exists() method in the following code to work properly.
class Question extends Module {
static base = { $("fieldset") }
static content = {
input { $("input[type=text]") }
name { input.getAttribute("name").toString() }
}
boolean exists() {
return input.isPresent()
}
Frustratingly, when I try to execute that code (from a Spock Test, "go"ing to a PageObjectm including this module, I get the following:
The required page content 'input - SimplePageContent (owner: question - Question (owner: MyPage, args: [], value: null), args: [], value: null)' is not present
I've tried a number of other things, including:
if (input) return true; return false,
... input.size() == 0,
Using static at = {...} (doesn't seem to be supported for modules"
Any ideas

By default Geb ensures that your content definitions return non empty elements. If your content is optional you can tell it using required content option:
name(required: false) { input.getAttribute("name").toString() }
Because Geb utilizes Groovy Truth to redefine how navigator are coerced to boolean values(empty navigators are falsey and non-empty are truthy) you can simplify your exists method to:
boolean exists() {
input
}

Related

Add onClick to Button in Ktor with Kotlinx

I am currently trying out Ktor. But it already fails on registering a onClickListener to the button.
I am just wondering because the onClick extends from String. If I click on the onClick the Code I get is this one:
var CommonAttributeGroupFacade.onClick : String
get() = attributeStringString.get(this, "onclick")
set(newValue) {attributeStringString.set(this, "onclick", newValue)}
So I think onClick has a getter and setter but not more. I installed location and FreeMarker so this is my route:
get<CharityRoute> {
val id = it.id
call.respondHtml {
body {
h1 { +"${it.id}" }
ul {
for (n in it.list) {
li { +"$n" }
}
}
button {
text("Run function")
onClick = "Hello"
}
}
}
}
Maybe someone has more experience with Ktor and especially with Kotlinx.
Problem
It depends which module you are working in.
On the server-side (JVM) you can not write Javascript-Code in Kotlin and assign it to a function like that.
To find a solution, I have to further know, what exactly it is you want to achieve.
Here are two of many possibilities, what you could do:
Solution 1
You can assign a javascript-code as string. You did just that by assigning the code "Hello".
Maybe you want to call a function, which was globally made available in the window object?
Solution 2
In client-side JS code, you can import kotlinx.html.js.onClickFunction and simply write
button{
onClickFunction = { println("clicked") }
}
to execute code written in Kotlin.

Possible to manipulate CasperJS assertions?

My CasperJS asserts seem to be overly strict. I have a function where I am trying to test the names of client logo images from an array, using Casperjs. However I do not seem to be able to use a variable from a forLoop in casperJS.
I understand there are probably hoisting issues that I am not accounting for, but this does not seem to be the primary problem. I have tried several things to resolve hoisting issues, such as immediately invoked functions, try catch blocks, and using ES6 term "Let" in my loop. None seem to work. Then I notice if I simply hard-code the string my variable should represent, and stick a console.log into my assert of a PASSING test, right before the return, the passing test fails.
Here is my failing code
var clients = 'https://www.google.com/';
var logoArray = ["images/logos/AC.png", "images/logos/Affiny.png", "images/logos/ffintus.png", "images/logos/agileAsset.png"]
function checkClientsArrayTest() {
casper.test.begin('The layout is as expected', 10, function suite(test) {
casper.start(clients, function () {
casper.then(function () {
for (var i = 0; i < logoArray.length; i++) {
try { throw i }
catch (ii) {
console.log(ii);
console.log(i);
test.assertEvalEquals(function () {
return document.querySelectorAll('div.client_logo a img')[ii].getAttribute('src')
.match(logoArray[ii]).toString();
}, logoArray[ii], 'Test searches for Client Logos in DOM.');
}
}
});
}).run(function () {
test.done();
});
});
}
If I change logoArray[ii] to a hardcoded string from the first index of the array, it passes. If I consolelog logoArray[ii], it seems to be what I expect. But if I pass a variable to the assert, or even stick a console.log inside of it, the test fails with the following
Running check for the layout of URL: https://www.google.com
0
0
FAIL Test searches for Client Logos in DOM.
type: assertEvalEquals
file: headlessTester.js
subject: null
fn: undefined
params: undefined
expected: "images/logos/AC.png"
Is this an issue of me getting hoisting wrong (shouldn't fail by sticking in a logger if this is the case afaik), or is this due to strictly structured asserts in CasperJS?

Return from `buildSequence` in Kotlin

I'm using the buildSequence function in Kotlin. How do I end the iteration in the middle of the function? I'm looking for something similar to C#'s yield break statement.
My code looks something like the following. I'm stuck at the TODO.
fun foo(list:List<Number>): Sequence<Number> = buildSequence {
if (someCondition) {
// TODO: Bail out early with an empty sequence
// return doesn't seem to work....
}
list.forEach {
yield(someProcessing(it))
}
}
EDIT
Apparently, I misdiagnosed the source. The issue is not returning from the buildSequence function. The following works for me:
fun foo(list:List<Number>): Sequence<Number> = buildSequence {
return#buildSequence
list.forEach {
yield(someProcessing(it))
}
}
EDIT 2
The issue is that I put the return in a local helper function that validates data at multiple points in the buildSequence (Hence the helper function). Apparently I'm not able to return from buildSequence within the helper function. The error message was not terribly helpful...
Just use return#buildSequence, which is a labeled return from lambda, while an unlabeled return would mean 'return from the function foo'.
See also: Whats does “return#” mean?
Since Kotlin v 1.3.x preferred sequence syntax changed. (buildSequence is replaced by kotlin.sequences.sequence)
Updated "early return from generator" code snippet (includes try-catch and == null early return examples) for post 1.3.x Kotlin:
// gen# is just a subjective name i gave to the code block.
// could be `anything#` you want
// Use of named returns prevents "'return' is not allowed here" errors.
private fun getItems() = sequence<Item> gen# {
val cursor: Cursor?
try {
cursor = contentResolver.query(uri,*args)
} catch (e: SecurityException) {
Log.w(APP_NAME, "Permission is not granted.")
return#gen
}
if (cursor == null) {
Log.w(APP_NAME, "Query returned nothing.")
return#gen
}
// `.use` auto-closes Closeable. recommend.
// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
cursor.use {
// iterate over cursor to step through the yielded records
while (cursor.moveToNext()) {
yield(Item.Factory.fromCursor(cursor))
}
}
}
(Thx for all the prior posts that helped me get on "named return" track.)

what does `args.unshift(this)` do in Vue's use.js?

I am reading vuejs source code, and got confused by these two lines of code:
const args = toArray(arguments, 1)
args.unshift(this)
in the following snippet, why bother do this ?
/* #flow */
import { toArray } from '../util/index'
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
/* istanbul ignore if */
if (plugin.installed) {
return
}
// additional parameters
const args = toArray(arguments, 1)
args.unshift(this)
if (typeof plugin.install === 'function') {
plugin.install.apply(plugin, args)
} else {
plugin.apply(null, args)
}
plugin.installed = true
return this
}
}
Since you are inside of a Vueinstance, the lines in question are in the function defined on Vue.use the this most likely will reference the current Vue instance.
You will have to browse the source of toArray to understand the first line, it might takes the arguments and returning an array from them, and maybe substracting the first argument (the 1 in toArray(arguments, 1) give me this impression but to be sure browse the source of that function).
But then when the call args.unshift(this)comes it puts the Vue instance as the first element of the args array which is then used to provide arguments to the plugin function.
Hope that helps ;-)
Seb

How to tell IDEA/Studio that the null check has been done?

I'm developing with Android Studio/IntelliJ IDEA.
I have enabled the inspection check called "Constant conditions & exceptions" that shows a warning if I am risking a NPE, such as:
String foo = foo.bar(); // Foo#bar() is #nullable
if (foo.contains("bar")) { // I'm living dangerously
...
}
I have the following in my code:
String encoding = contentEncoding == null ? null : contentEncoding.getValue();
if (!TextUtils.isEmpty(encoding) && encoding.equalsIgnoreCase("gzip")) {
inputStream = new GZIPInputStream(entity.getContent());
} else {
inputStream = entity.getContent();
}
Here's the source code of TextUtils#isEmpty(String):
/**
* Returns true if the string is null or 0-length.
* #param str the string to be examined
* #return true if str is null or zero length
*/
public static boolean isEmpty(CharSequence str) {
if (str == null || str.length() == 0)
return true;
else
return false;
}
I'm not risking any NPE because TextUtils#isEmpty(String) would return true to a null pointer.
However I'm still getting the little Method invocation 'encoding.equalsIgnoreCase("gzip")' may produce 'java.lang.NullPointerException' warning, which can be annoying.
Is it possible to make this check smarter and ignore the NPE warning if there's already a null-check done?
You can look into the link that Peter Gromov mention in his answer.
Created some simple classes that resemble your setup:
A class with a method annotated with #Nullable:
The TextUtil class with it's isEmpty method:
And finally the main class calling the TextUtil#isEmpty:
Now if you enter the File -> Settings... and go to Inspections ->Constant conditions & exceptions part you can change the Configure Assert/Check Methods to cater for your isEmpty method:
Add a new IsNull check method:
Enter the TextUtil class, isEmpty method and CharSequence parameter:
This gives this Assert/Check Method Configuration window:
Press Ok and then Ok again to go back to the editor view and you'll see that the inspection disappeared:
You are actually telling IntelliJ that the isEmpty method is doing a null check on the str parameter.
You could use //noinspection ConstantConditions that will remove the NPE warning for the following line, like this:
String encoding = contentEncoding == null ? null : contentEncoding.getValue();
//noinspection ConstantConditions
if (!TextUtils.isEmpty(encoding) && encoding.equalsIgnoreCase("gzip")) {
inputStream = new GZIPInputStream(entity.getContent());
} else {
inputStream = entity.getContent();
}
You can use #SuppressWarnings("ConstantConditions") annotation.
#SuppressWarnings("ConstantConditions")
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int indexViewType) {
if (inflater == null) {
inflater = LayoutInflater.from(parent.getContext());
}
ItemViewProvider provider = getProviderByIndex(indexViewType);
provider.adapter = MultiTypeAdapter.this;
return provider.onCreateViewHolder(inflater, parent);
}
Select "TextUtils.isEmpty".
Right Click -> Show Context Actions -> Add Method Contract.
Enter "null -> true".
Save the configuration xml.
Please check the details here
See http://www.jetbrains.com/idea/webhelp/configuring-check-assert-methods.html for IDEA 12.
In IDEA 13 EAP, you can add method contract: http://youtrack.jetbrains.com/issue/IDEA-93372
Unfortunately marked as "right answer" solution is of date. But I found equivalent for me solution.
The new versions of IDE work correctly with static methods. So the example from the question won't throw warning anymore.
TextUtils#isEmpty(String);
public static boolean isEmpty(CharSequence str) {
// your checks
}