Issue with Kotlin lambdas halting code using Spoon plug-in by jaredsburrows - kotlin

I'm attempting to run an espresso test on a simple pre-fabricated Android app using the Spoon plugin to take screenshots and test on multiple devices in Kotlin. I looked at the official Github example but can't seem to get it working. I'm thinking it might be an issue with my understanding of lambda functions in Kotlin, as I've never used them before.
Currently, my code is freezing after the first command in the lambda function.
#Test
fun firstFragmentTest()
{
scenario.scenario.onActivity { activity ->
Log.d("First Fragment Test: ", "Testing to make sure first fragment is accurate")
//checking to see if center text is accurate
onView(withId(R.id.textview_first)).check(matches(withText("Hello first fragment")))
Log.d("First Fragment Test: ", "Center text is accurate")
Spoon.screenshot(activity, "FirstFragment", "ButtonTests", "firstFragmentTest")
//checking to see if button text is accurate
onView(withId(R.id.button_first)).check(matches(withText("Next")))
Log.d("First Fragment Test: ", "Button text is accurate")
//checking to see if top text is accurate
//onView(withId(R.id.FirstFragment)).check(matches(withText("First Fragment")))
Log.d("First Fragment Test: ", "First fragment text is accurate")
}
}
This is my logcat:
2022-05-31 13:43:39.640 2155-2190/com.example.problem2_21 D/Previous Button Test:: Testing functionality of previous button
2022-05-31 13:43:39.643 2155-2155/com.example.problem2_21 I/ViewInteraction: Performing 'single click' action on view view.getId() is <2131230815/com.example.problem2_21:id/button_second>
2022-05-31 13:43:39.972 2155-2190/com.example.problem2_21 D/Previous Button Test:: Previous button pressed
2022-05-31 13:43:39.973 2155-2190/com.example.problem2_21 D/Previous Button Test:: First fragment screen should be displayed
2022-05-31 13:43:39.974 2155-2155/com.example.problem2_21 D/First Fragment Test:: Testing to make sure first fragment is accurate
As you can see, the test stops running after the first line of the lambda. I have multiple test functions that lead into this one, which aren't set-up for Spoon yet and don't use lambda functions, that work fine.

I actually figured it out, in case anyone else has the same issue. I just had to place the lambda with the screenshot after the test code like this:
#Test
fun firstFragmentTest()
{
Log.d("First Fragment Test: ", "Testing to make sure first fragment is accurate")
//checking to see if center text is accurate
onView(withId(R.id.textview_first)).check(matches(withText("Hello first fragment")))
Log.d("First Fragment Test: ", "Center text is accurate")
//checking to see if button text is accurate
onView(withId(R.id.button_first)).check(matches(withText("Next")))
Log.d("First Fragment Test: ", "Button text is accurate")
//checking to see if top text is accurate
//onView(withId(R.id.FirstFragment)).check(matches(withText("First Fragment")))
Log.d("First Fragment Test: ", "First fragment text is accurate")
scenario.scenario.onActivity { activity ->
Spoon.screenshot(activity, "FirstFragment", "ButtonTests", "firstFragmentTest")
}
}

Related

Navigating from fragment A to fragment B and back to fragment A when i click back button in Kotlin

Hey guys i'll just get straight to the point. Here's my problem :
adapterProduk.onItemClick = {
val fragment = FragmentKeteranganProduk()
val transaction = fragmentManager?.beginTransaction()
transaction?.replace(R.id.layoutFragment,fragment)?.commit()
}
This code is already working perfectly and no error can be found, but what i want to know that if there's any solution to go back into starting point after the fragment is already changed when i click the back button? It's like intent finish() method but i don't want to "finish()" it yet. Any solution will be appreciated, thanks!

Java FX Dialog "appears" with no size

I'm using JFX 11 on Fedora 33 (GNU/Linux) with the Xorg GUI server (v 1.20.11), creating a dialog thus (kotlin):
fun YNdialog (txt : String) : Boolean {
val dlog = Dialog<ButtonType>()
dlog.dialogPane.apply {
contentText = txt
buttonTypes.apply {
add(ButtonType.OK)
add(ButtonType.CANCEL)
}
minWidth = 200.0
minHeight = 100.0
}
dlog.initOwner(theStage.scene.window)
val r = dlog.showAndWait()
return r.isPresent && r.get() == ButtonType.OK
}
This is called from an EventHandler<ActionEvent> associated with a Button:
if (YNdialog("hello world")) ...
There does seem to be a window created. If I remove the initOwner() call, an icon for it appears in the desktop taskbar (KDE), allowing me to do things like move it, but "maximize" and "resize" are greyed out, and the mouse cursor appears to be dragging nothing, ie., it has no width or height.
With the initOwner() it does much the same thing, except it gets no taskbar icon. Also, there is a visible vertical line one or two pixels thick where it should be (centered over the main window). What's more interesting is a second close button appears in the titlebar of the main window:
This is not part of the javafx interface, but I've never seen the window manager (?) do this before.
Occasionally (maybe one in five or ten times) the dialog does appear, and curiously,
the close button there is offset with space for a second one:
When this happens and I can dismiss the dialog window, the second close button on the main window disappears.
Using Alert
Replacing that function, etc. with:
Alert(Alert.AlertType.CONFIRMATION, "hello world").showAndWait()
.filter { res -> res == ButtonType.OK }
.ifPresent { _ -> log.msg("ok!") }
The result is identical to the YNdialog with initOwner().
Am I missing something here? I got all of this pretty much straight from the docs. I have done custom popup windows (instantiated via FXMLLoader) and have not had any problem with that. Does this experience imply the dialog hierarchy is glitchy in this context and I should roll my own?

talkback not focusing by default on any view on start of inner fragment

I am using accessibility talkback functionality and I am facing one problem I have one bottom navigation in the parent activity and from the setting tab I am opening another fragment(inner fragment) using .add but the inner fragment view not getting focus by default
I also tried with . replace but it's not focusing by default on fragment creation.
open fragment code
val details = DetailsFragment.newInstance();
getSupportFragmentManager().setupForAccessibility()
getSupportFragmentManager().beginTransaction().add(android.R.id.content, details).commit()
and I used this extension function to not get focus on the previous fragment from this source
fun FragmentManager.setupForAccessibility() {
addOnBackStackChangedListener {
val lastFragmentWithView = fragments.lastOrNull { it.view != null }
for (fragment in fragments) {
if (fragment == lastFragmentWithView) {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_YES
} else {
fragment.view?.importantForAccessibility =
View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
}
}
}
}
in normal I show that at the start of the first fragment it's focusing top first Textview and speaking automatic but in the inner fragment it's not focusing by default so what should I do to get focus by default on the first view by default
I already try
android:focusable="true"
android:focusableInTouchMode="true"
and request focus but it's not working
Please suggest me any help would be highly appriciated
I've had the best luck using
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
on the view you want to focus, or maybe
Handler().postDelayed({
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
}, someDelayMillis)
to let the system do whatever it does, and then jump in after a moment and force a focus change.
But this might be considered bad accessibility, if it's interfering with the usual navigation, and that might be why it's so hard to get focus working consistently! It might be better to just announce the new fragment (with something like view.announceForAccessibility("new fragment")) and let the user start navigating from the top. It depends on your app, it's your call
Also you probably want to use replace for your fragment instead of add, if you add a fragment on top of an old one, TalkBack can get stuck looking at the "invisible" views on the old fragment
this is my improved code that extends from #cactustictacs
//target to specific a view
binding.getRoot().postDelayed(new Runnable() {
#Override
public void run() {
binding.textView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
}, 300);
full: https://github.com/dotrinh-PM/AndroidTalkback

see if the div is present or not in geb

We are using Geb for automation. I have spinner loaded before every page gets loaded. we are using waitFor() , but it takes a long time and the scripts are getting run more than the specified time.The DOM element is
<div classname="loader"></div>
i tried to see if the element is present.
if(!$(".loader").displayed== true)
{}
But i am getting error as ,
geb.waiting.WaitTimeoutException: condition did not pass in 40.0 seconds (failed with exception)
at geb.waiting.Wait.waitFor(Wait.groovy:138)
at geb.waiting.DefaultWaitingSupport.doWaitFor(DefaultWaitingSupport.groovy:51)
at geb.waiting.DefaultWaitingSupport.waitFor(DefaultWaitingSupport.groovy:46)
at geb.Page.waitFor(Page.groovy:516)
at geb.Browser.methodMissing(Browser.groovy:206)
at geb.spock.GebSpec.methodMissing(GebSpec.groovy:56)
at loaderSpec(loaderSpec.groovy:415)
Caused by: Assertion failed:
$(".loader").displayed== false
| | |
| true false
[[[ChromeDriver: chrome on XP (1b3943691dd96ebaf9098b1720c87ee9)] -> css
selector: .loader]]
at loaderSpec(loaderSpec.groovy:415)
at loaderSpec(loaderSpec.groovy:415)
at geb.waiting.Wait.waitFor(Wait.groovy:127)
... 6 more
I am not sure how to check if the div is present or not present. If I extend the time to wait for, I am getting element not found error.
Kindly let me know your input.
Are you checking that the div is visible while you are waiting for the spinner to go away?
I've had an issue exactly like this that plagued me. Here is the solution my coworkers and I came up with:
try{
waitFor(10) { element.isDisplayed() } //wait for spinner to kick in
waitFor() { !element.isDisplayed() } //wait for spinner to go away
} catch(WaitTimeoutException e) {
// if spinner loads & deloads faster than this code is reached
// then WTE will be caught and we dont need to handle the spinner any more
//println(e.printStackTrace())
}
Your boolean expression is more complicated than it needs to be, and in this case you might be noting (!) something you don't mean to be.
in general, you never need to compare booleans. (bool1==true) is the same as saying (bool1).
instead of saying
if(!$(".loader").displayed== true){}
just say:
if($(".loader").displayed){} //to check if the div is displayed
or
if(!$(".loader").displayed){} //to check if the div is not displayed
You can try with code if(!$(".loader")==undefined){}

Chrome WebDriver hungs when currently selected frame closed

I am working on creation of automated test for some Web Application. This application is very complex. In fact it is text editor for specific content. As a part of functionality it has some pop-up frames. You may open this pop-up? make some changes and save them - closing current frame. May problem is in that fact, that close button situated inside frame will be eliminating. And this force Chrome WebDriver to hung. My first try was like this:
driver.findElement(By.xpath("//input[#id='insert']")).click();
driver.switchTo().defaultContent();
But it hungs on first line after executinh click command as this command close frame.
Then I change to this(I have JQuery on the page):
driver.executeScript("$(\"input#insert\").click()");
driver.switchTo().defaultContent();
But this leads to same result.
Then I use this solution:
driver.executeScript("setTimeout(function(){$(\"input#insert\").click()}, 10)");
driver.switchTo().defaultContent();
And it hungs on second line. Only this solution works:
driver.executeScript("setTimeout(function(){$(\"input#insert\").click()}, 100)");
driver.switchTo().defaultContent();
but only if you don't take into account, that it is unstable - some timing issue may occur.
So may question is there more cleaner and more stable way for switch out from closed frame?
P.S.: executeScript - self defined function to decrease amount of code. It simply executer some js on page.
Update:
I realized I was wrong. This problem is not for all iframes. It's occur when tinyMCE popup used. Situation is exactly like in this topic. So it's doubtful I will find answer here, but who knows. Solution described above will help, but only for very short amount of time, meaning that after several seconds pass chromedriver will hangs on next command.
This is how i would do it in Ruby, hopefully you can change it for java
$driver.find_element(:xpath, "//input[#id='insert']").click
$wait.until {$driver.window_handles.size < 2} #this will "explicitly wait" for the window to close
handles = $driver.window_handles #get available window handles
$driver.switch_to.window(handles[0]) #navigate to default in this case the First window handle
hope this helps
Problem was in this line of tinyMCEPopup code:
DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak
Executing this script on page fix hang problem(but possibly creates leaks :) ):
(function() {
var domVar;
if (window.tinymce && window.tinymce.DOM) {
domVar = window.tinymce.DOM
}
else if (window.tinyMCE && window.tinyMCE.DOM) {
domVar = window.tinyMCE.DOM
}
else {
return;
}
var tempVar = domVar.setAttrib;console.log(123)
domVar.setAttrib = function(id, attr, val) {
if (attr == 'src' && typeof(val)== 'string' &&(val + "").trim().match(/javascript\s*:\s*("\s*"|'\s*')/)) {
console.log("Cool");
return;
}
else {
tempVar.apply(this, arguments);
}
}
}());
Bug and solution also described here
Note. Code above should be added to parent frame, not into popup frame.