Katalon and Javascript Promises Revisited

Hi @kevin.jackey,

Just do some quick research.

You’re encountering an issue because of how Katalon handles asynchronous JavaScript execution. The problem is that your getLargestCLS function returns a Promise, but Katalon’s executeJavaScript method does not inherently support handling JavaScript Promises directly.

Why is Katalon Returning 0.0?

  1. JavaScript Executes Asynchronously

    • The getLargestCLS function runs asynchronously and returns a Promise.
    • Katalon executes WebUI.executeJavaScript(jsCommandString, null), but since it doesn’t wait for the Promise to resolve, largestCLS is not set before the next command executes.
  2. Katalon Executes return largestCLS Too Early

    • Since largestCLS is not updated immediately (due to the 10-second delay in JS), WebUI.executeJavaScript("return largestCLS", null) retrieves 0.0, which was set initially.

Workaround
Instead of using a Promise that Katalon can’t handle, I suggest that you should wait for the Promise to resolve inside JavaScript and then return the value synchronously.

Updated JavaScript Code

Modify your script to use an async function that waits for the largest CLS value and then immediately returns it.

// Declare initial Katalon and JS Variables
double chromeCLS
WebUI.executeJavaScript("window.largestCLS = 0;", null)

// Modified JavaScript Execution
jsCommandString = """
    (async function() {
        let largestCLS = 0;
        const observer = new PerformanceObserver((entryList) => {
            entryList.getEntries().forEach(entry => {
                if (entry.entryType === 'layout-shift' && !entry.hadRecentInput && entry.value > largestCLS) {
                    largestCLS = entry.value;
                }
            });
        });

        observer.observe({ type: 'layout-shift', buffered: true });

        // Wait for 10 seconds before resolving
        await new Promise(resolve => setTimeout(resolve, 10000));

        observer.disconnect();
        window.largestCLS = largestCLS; // Store value in global scope
    })();
"""

WebUI.executeJavaScript(jsCommandString, null)

// Allow time for largest CLS to be recorded
WebUI.delay(12)

// Retrieve the recorded CLS value
chromeCLS = WebUI.executeJavaScript("return window.largestCLS", null)

println("Largest CLS Value: " + chromeCLS)

Key Fixes

  1. Stores CLS Value in window.largestCLS

    • JavaScript now assigns window.largestCLS, which persists in the page context.
  2. Uses async function

    • await new Promise(resolve => setTimeout(resolve, 10000)); makes JavaScript pause execution for 10 seconds before assigning the value.
  3. Ensures JavaScript Finishes Before Retrieval

    • WebUI.delay(12) ensures the script has enough time to complete before Katalon retrieves the CLS value.

Hope this can help