Your code, refactored…
Let’s clean up your code here:
final double ttfb = WebUI.executeJavaScript("""
new PerformanceObserver((entryList) => {
const [pageNav] = entryList.getEntriesByType('navigation');
var TTFB = (pageNav.responseStart/1000).toFixed(2);
return TTFB;
}).observe({
type: 'navigation',
buffered: true,
});
""",
null);
log.logInfo("Returned amount (TTFB) = ${ttfb}")
Breakdown of your approach, and an initial suggestion…
If we look at your function, we see that you are writing a variable to the global JavaScript scope, called TTFB
, with use of that var
keyword.
Also, PerformanceObserver.observe()
does not return a value, so this approach, as it is written, is incorrect.
Why not pull the var declaration out of the function, and separate concerns?
Implementing Russ’s suggestion
Russ is spot on about how to handle this. Let’s jump-start our implementation with some code at this blog post.
We’re going to create a general web UI util keyword, let’s call it WaitForCondition
:
public final class GeneralWebUIUtils {
public static boolean WaitForCondition(Closure<Boolean> onCheckCondition, int timeOut, Closure<String> onErrorMessage, FailureHandling failureHandling = FailureHandling.STOP_ON_FAILURE) {
final long startTime = System.currentTimeMillis()
boolean isConditionSatisfied = false;
while ((System.currentTimeMillis() < startTime + timeOut * 1000) && (!isConditionSatisfied)) {
isConditionSatisfied = onCheckCondition()
}
if ((!isConditionSatisfied) && (failureHandling.equals(FailureHandling.STOP_ON_FAILURE))) {
KeywordUtil.markFailedAndStop("${onErrorMessage()} after ${(System.currentTimeMillis() - startTime) / 1000} seconds");
}
return isConditionSatisfied;
}
}
We now have our util method, now let’s use it:
WebUI.executeJavaScript("TTFB = 0;", null); // set up the sentry variable
WebUI.executeJavaScript("""
new PerformanceObserver((entryList) => {
const [pageNav] = entryList.getEntriesByType('navigation');
TTFB = (pageNav.responseStart/1000).toFixed(2);
}).observe({
type: 'navigation',
buffered: true,
});
""",
null);
// TODO: do some action to trigger that obsever here, I guess...
// you might want to make this another general WebUI util...
GeneralWebUIUtils.WaitForCondition({ return (boolean)WebUI.executeJavaScript("return (TTFB > 0)", null)},
10, // or however long you want to wait before failing the test
{ return "Time To First Byte (TTFB) exceeded the wait time."},
)
final double ttfb = (double)WebUI.executeJavaScript("return TTFB;", null);
WebUI.verifyNotEqual(ttfb, 0);
DISCLAIMER: I have NOT run this.