HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/apklausos/tests/LimeSurveyWebDriver.php
<?php

namespace ls\tests;

use Facebook\WebDriver\Exception\TimeoutException;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\RemoteWebElement;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\Exception\NoSuchElementException;

/**
 * Subclass of Facebook webdriver.
 * This class contains helper methods to interact with a LimeSurvey
 * survey, like filling in questions, going to next question group,
 * changing language etc.
 */
class LimeSurveyWebDriver extends RemoteWebDriver
{
    /**
     * Change language using the <select> element
     * on survey welcome page.
     * @param string $newLang Like 'de' or 'en'.
     * @return void
     */
    public function changeLanguageSelect($newLang)
    {
        // Try with welcome page select first.
        $langSelectOption = $this->findElement(
            WebDriverBy::cssSelector(
                sprintf(
                    '#lang option[value="%s"]',
                    $newLang
                )
            )
        );
        $langSelectOption->click();
        $langSubmit = $this->findElement(
            WebDriverBy::cssSelector('button[value=changelang]')
        );
        $langSubmit->click();
    }

    /**
     * Change language using links in top-right corner.
     * @param string $newLang Like 'de' or 'en'.
     * @return void
     */
    public function changeLanguage($newLang)
    {
        $langSelect = $this->findElement(
            WebDriverBy::cssSelector('.form-change-lang')
        );
        $langSelect->click();
        $langSelectLink = $this->findElement(
            WebDriverBy::cssSelector(
                sprintf(
                    '.form-change-lang a[data-limesurvey-lang="%s"]',
                    $newLang
                )
            )
        );
        $langSelectLink->click();
    }

    /**
     * @param string $sgqa Like 123X345X567
     * @param string $answer Answer to question.
     * @return void
     */
    public function answerTextQuestion($sgqa, $answer)
    {
        $firstQuestion = $this->findElement(
            WebDriverBy::cssSelector(
                sprintf(
                    'textarea[name="%s"], input[name="%s"]',
                    $sgqa,
                    $sgqa
                )
            )
        );
        $firstQuestion->sendKeys($answer);
    }

    /**
     * Go to next question/question group.
     * @return void
     */
    public function next()
    {
        $nextButton = $this->wait(5)->until(
            WebDriverExpectedCondition::elementToBeClickable(
                WebDriverBy::id('ls-button-submit')
            )
        );
        $nextButton->click();
    }

    /**
     * Wait until element with $id gets clickable. Max 5 sec.
     *
     * @param string $id
     * @return void
     */
    public function waitById($id)
    {
        $this->wait(5)->until(
            WebDriverExpectedCondition::elementToBeClickable(
                WebDriverBy::id($id)
            )
        );
    }

    /**
     * Alias for next().
     */
    public function submit()
    {
        $this->next();
    }

    /**
     * @return void
     * @todo Should be clickById
     */
    public function clickButton($id)
    {
        $button = $this->findElement(WebDriverBy::id($id));
        $button->click();
    }

    /**
     * Click on element found by $css
     *
     * @param string $css
     * @return void
     */
    public function clickByCss($css)
    {
        $elem = $this->findByCss($css);
        $elem->click();
    }

    /**
     * Debug method to dump all text in <body></body>.
     * @return void
     */
    public function dumpBody()
    {
        $body = $this->findElement(WebDriverBy::tagName('body'));
        var_dump('body text = ' . $body->getText());
    }

    /**
     * @param string $id
     * @return \Facebook\WebDriver\Remote\RemoteWebElement
     */
    public function findById($id)
    {
        return $this->findElement(WebDriverBy::id($id));
    }

    /**
     * @param string $name Name of <input>
     * @return \Facebook\WebDriver\Remote\RemoteWebElement?
     */
    public function findByName($name)
    {
        return $this->findElement(WebDriverBy::name($name));
    }

    /**
     * @param string $css
     * @return \Facebook\WebDriver\Remote\RemoteWebElement
     */
    public function findByCss($css)
    {
        return $this->findElement(WebDriverBy::cssSelector($css));
    }

    public function findManyByCss($css)
    {
        return $this->findElements(WebDriverBy::cssSelector($css));
    }

    /**
     * @param string $text
     * @return \Facebook\WebDriver\Remote\RemoteWebElement
     */
    public function findByLinkText($text)
    {
        return $this->findElement(WebDriverBy::linkText($text));
    }

    /**
     * @param string $text
     * @return \Facebook\WebDriver\Remote\RemoteWebElement
     */
    public function findByPartialLinkText($text)
    {
        return $this->findElement(WebDriverBy::partialLinkText($text));
    }

    /**
     * Click "Close" on notification modal.
     *
     * @return void
     */
    public function dismissModal()
    {
        try {
            // If not clickable, dismiss modal.
            $button = $this->findElement(
                WebDriverBy::cssSelector('#admin-notification-modal .modal-footer .btn')
            );
            $button->click();
            sleep(1);
        } catch (\Exception $ex) {
            // Do nothing.
        }
    }

    /**
     * Scroll to the bottom of the page
     * @see https://stackoverflow.com/questions/45610679/how-can-i-scroll-page-in-php-webdriver
     * @return void
     */
    public function scrollToBottom()
    {
        $this->executeScript('window.scrollTo(0,document.body.scrollHeight);');
        sleep(1);
    }

    public function scrollToTop()
    {
        $this->executeScript('window.scrollTo(0, 0);');
    }

    /**
     * Fixes php-webdriver error when scrolling and instead use the browsers function
     * @param $element RemoteWebElement
     * @return RemoteWebElement
     */
    public function click(RemoteWebElement $element): RemoteWebElement
    {
        $this->executeScript('window.scrollTo({top: (arguments[0].offsetTop + arguments[0].offsetHeight - window.innerHeight), behavior: "instant"});', [$element]);
        return $element->click();
    }
}