OffsetDateTime startTime = OffsetDateTime.now();

String v_server_protocol = "https://";
String v_server_path = "/fantasy-classic/team";
String v_fact_category = "FIFA:Synthetic Actions";
String v_fact_name = "Login Action";
List<String> v_action_xpaths = 
[
    ["get_page", "","Get page...", true, 0],
    ["click", "//*[@id=\"onetrust-accept-btn-handler\"]","Accept Cookies...", true, 30],
    ["click", "//*[@id=\"root\"]/div/div/div/button","Close welcome message...", true, 30],
    ["click", "//*[@id=\"root\"]/header/div[3]/div[2]/div/button/img","Open login prompt...", true, 30],
    ["click", "(//button[contains(text(), 'SIGN IN')])[last()]","Navigate to login page...", true, 30],
    ["fill", "//*[@id=\"email\"]","Filling username...", true, 30, credentials.username],
    ["fill", "//*[@id=\"password\"]","Filling password...", true, 30, credentials.password.value],
    ["click", "//*[@id=\"loginFormSubmitBtn\"]","Click login...", true, 30],
    ["contains", "Leaderboard","Confirming login...", true, 30]
];

def synthetic_action (v_params) {
    //Instantiate webdriverwait
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(v_params[4]));

      //Get page
    if (v_params[0] == "get_page") {
        String base = String.format("%s%s%s", v_server_protocol, server.hostname, v_server_path);
        driver.get(base);
        return true;
    } //Get page with authentication credentials
    else if (v_params[0] == "get_page_with_auth") {
        String base = String.format("%s%s:%s@%s%s", v_server_protocol, v_params[5], v_params[6], server.hostname, v_server_path);
        driver.get(base);
        return true;
    } //Accept alert
    else if (v_params[0] == "accept_alert") {
        wait.until(ExpectedConditions.alertIsPresent());
        driver.switchTo().alert().accept();
        return true;
    }  //Dismiss alert
    else if (v_params[0] == "dismiss_alert") {
        wait.until(ExpectedConditions.alertIsPresent());
        driver.switchTo().alert().dismiss();
        return true;
    } //Construct xpath of contains search
    else if (v_params[0] == "contains") {
        v_params[1] = String.format("//*[contains(.,\"%s\")]", v_action_xpaths[i][1]);
    }

    List<WebElement> v_elements = [];
    int v_status = 0;

    for (int j = 0; j < v_params[4] * 2; j++) {
        //Grab all elements matching specified xpath
        v_elements = driver.findElements(By.xpath(v_params[1]));

        //Chect to ensure interactivity of element(s) except for text search (contains)
        if (v_params[0] == "contains") {
            v_status = v_elements.size();
        } else {
            foreach (l : v_elements) {
                if (l.isEnabled() && l.isDisplayed()) {
                    v_status = v_status + 1;
                }
            } 
        }

        //Process action on found element(s) when ready
        if (v_elements.size() > 0 && v_elements.size() == v_status) {
            if (v_params[0] == "click") {
                foreach (k : v_elements) {
                    driver.executeScript("arguments[0].click();", k);
                }
            } else if (v_params[0] == "fill") {
                driver.findElement(By.xpath(v_params[1])).clear();
                driver.findElement(By.xpath(v_params[1])).sendKeys(v_params[5]);
            }
            return true;
        }
        Thread.sleep(500);
    }
    return false;
}

// Create transaction
GenericTransaction tx = new GenericTransaction();
tx.type = v_fact_category;
tx.name = v_fact_name;
tx.timestamp = startTime;
tx.user.name = credentials.username;

// Perform validation checks and actions
for (int i=0; i < v_action_xpaths.size(); i++) {
    // Print description of each step
    log.info(v_action_xpaths[i][2]);

    //Record status of latest action
    tx.success = synthetic_action(v_action_xpaths[i]);

    //Halt execution and exit if flag is set to true on failure of current action
    if (tx.success == false && v_action_xpaths[i][3] == true) {
        i = v_action_xpaths.size();
    }
}
log.info("{} Status: {}", v_fact_name, tx.success);
// Compute time taken and log transaction to DB
tx.duration = DateTimeUtils.computeDuration(startTime, OffsetDateTime.now());
datamart.insert(tx, context);