[Tͪ#n$;<:a4sX[d|W~u|rÇXc-9%ahHS|$"oF+(@FqG].	˯P/Gla7
vOsLTbH&w;%7~XIشKjQiR`QKҘ36
#:koꭳtl=OE0QO:wyqm!sn	R2Q뙃3(zf@uMՑ,&sy`~|BVˊimc#y̓K,}p9 Le-N}mhss `Y#RIŝ֭&<lo*ݏc@_pmSUt3}kW8z88mfu.MP+c\6	+I\3lSFOü<tS /|h2ǘ̌%r~.t
nTq++455yLtAќCX;Lϧc=^kLQ+	nNnTٷ]diƻЉ~n);	AD CP>!g+@SNSeӳ;+) |jP[z
S#Qz@7WΑpWk'dg8&__o`zLb.2?."It2C3/G!qο7cX"9V{rg)٩Lv"MSQ[?*ȫ@2Luz631JKqk>P;)?͑ \=5W!lr-+}5NX&(:@[*wi49pppO!?#wgZe/g{.gߤ"/O"Jf̿Niw:0
0e/g{.gߤP|98"038^'SHz+mKfM9}k[NV"fr3n9˖)Dvad/y?QTs/Qmwދr>@{j(?oФ.|fBvQc5S ).CRv빈PAJ iOcb
"WX+))<}E
ۤʟVO߯w,Nü?Ί>$jVlvچqwl ]B+8^'SHz+托:>n7bF{}6ן.5'ket#Wmu$_D'G
DKc4(LNfL;)zp?(ݯѦϚ[TB=I"Mz_a0>Bm([* 	T+%qyTiXEjh[S`%	|:_%sk6`y"(JwښU*)lc	69cp申?T14Wة_,a@UZj&_gʬɹKŰZGѡ״0b4R dxo82{StBL!Z[6월K0 4XI=糓ٰjW;SÐK,"Z09}AqơҒu-s{~,~.|AFGJu;g:icUԿq@FxRQJyki2F-*tk=w@u[\v


 |nteAFGJu;g:icS4(1C,VxR^G4Aw^stny@mHHAd%)9eh|z1evN}Ԝ:EW8ˮїP[[7Օ!δRM"xAH~L?|^M<x_$sMͰGNf.#zdPL&`f@14䛬*U9I?3S8^'SHz+bMI>Qh4X\cܲٳ@be#?0*5pG/g`z59zB&CK Aލ&G^\Y2a=.s'	rМ'.MC<\]>ӓTm;Q@qzxPGM6}A!?c1Dzbq@3r+	⎗?,>8S>Xy_')'!j=gJ	'/
yWƷ"rE:ڬMOIib?xr؅-&[5O!(AvvCS݁(i*aEשe1`9uA-*!G41W HBrX ٤BeOּbմ!2Q@c)5q
da820ʋW8VQ&`Ã'ZDq
uA*I<Cbj	nAuw<<'|ULQ 4p<f\L;a:^m;$trTVmRa[6o3F>9Y>)9e{8'JGwa&YKCk_*!*뒥kB\qug稝pNS}&ᗏT_joQv@z{3Nᾣ1#Ɏz濹_F5Cǭf9T=.qum⎗?,>d"3~7:=<o{ VǖRS&ppz\K91 *5rbs9/jY#6^Pӗ	s4>2 RRrsc]bp@(z#Aq&jsD{2Cn򴅾Mi9Fnh<X#_x%LSsfk%cV*گBz7J+
-đN+[#%ybk(kЅﱛ'E.%x
>`=\3?ODYje$O\YPpȂFBh:KNDE,03Nᾣ1#Ɏzrb,t!#bu~!
nρ# 3Nᾣ1#Ɏz/E(0.w!ޡX}As4 3Nᾣ1#ɎzkR }%"@AIc+ZmxJryv\GGBh!iKNoi΁1}B%"\3?OD48DtW=rG})|j_k 1bͰōzlvy/w׻r>}u#-Jk$N3Nᾣ1#Ɏz1yBD'.;<SZ[`$BQ4]/PEW8ˮNR	vnl"y*D1ʅ&J{EW8ˮ%KZv$64`e'9L@I7[&W|IWID%jh|V3$ +NT4?D)E
xVJ3#7ӌ^
mT}&U[ZU2-_ԏqM	{-犍>`AxAH~L?k`/KШT'	{0wxrԳ[d+<}s79B]np|D_d[-XFP~*¥dJ
=7QL.#IQ̅p;)VrAU4!ftwbwlђ@lC)>B2*m%l>MpDDg<
V*66c61_0 qly/}E	ހ3Nᾣ1#ɎzT;|/(S{YZ^>1RPh                    'os' => 'windows',
                        'os_version' => '7',
                    )
                )
            );
            */
            return $result;
        } elseif (! empty($GLOBALS['TESTSUITE_SELENIUM_HOST'])) {
            self::$_selenium_enabled = true;
            return array(
                array(
                    'browserName' => $GLOBALS['TESTSUITE_SELENIUM_BROWSER'],
                    'host' => $GLOBALS['TESTSUITE_SELENIUM_HOST'],
                    'port' => intval($GLOBALS['TESTSUITE_SELENIUM_PORT']),
                )
            );
        } else {
            return array();
        }
    }

    /**
     * Configures the selenium and database link.
     *
     * @return void
     *
     * @throws Exception
     */
    protected function setUp()
    {
        if (! self::$_selenium_enabled) {
            $this->markTestSkipped('Selenium testing not configured.');
        }

        $caps = $this->getDesiredCapabilities();
        $this->setDesiredCapabilities(
            array_merge(
                $caps,
                array('name' => get_class($this) . '__' . $this->getName())
            )
        );

        parent::setUp();
        $this->setBrowserUrl($GLOBALS['TESTSUITE_URL']);
        $this->_mysqli = new mysqli(
            $GLOBALS['TESTSUITE_SERVER'],
            $GLOBALS['TESTSUITE_USER'],
            $GLOBALS['TESTSUITE_PASSWORD']
        );
        if ($this->_mysqli->connect_errno) {
            throw new Exception(
                'Failed to connect to MySQL (' . $this->_mysqli->error . ')'
            );
        }
        $this->database_name = $GLOBALS['TESTSUITE_DATABASE']
            . mb_substr(md5(rand()), 0, 7);
        $this->dbQuery(
            'CREATE DATABASE IF NOT EXISTS ' . $this->database_name
        );
        $this->dbQuery(
            'USE ' . $this->database_name
        );
    }

    /**
     * Checks whether user is a superuser.
     *
     * @return boolean
     */
    protected function isSuperUser()
    {
        $result = $this->dbQuery('SELECT COUNT(*) FROM mysql.user');
        if ($result !== false) {
            $result->free();
            return true;
        }
        return false;
    }

    /**
     * Skips test if test user is not a superuser.
     *
     * @return void
     */
    protected function skipIfNotSuperUser()
    {
        if (! $this->isSuperUser()) {
            $this->markTestSkipped('Test user is not a superuser.');
        }
    }

    /**
     * Skips test if pmadb is not configured.
     *
     * @return void
     */
    protected function skipIfNotPMADB()
    {
        $this->url('chk_rel.php');
        if ($this->isElementPresent("byXPath", "//*[@color=\"red\"]")) {
            $this->markTestSkipped(
                'The phpMyAdmin configuration storage is not working.'
            );
        }
    }

    /**
     * Tear Down function for test cases
     *
     * @return void
     */
    public function tearDown()
    {
        if ($this->_mysqli != null) {
            $this->dbQuery('DROP DATABASE IF EXISTS ' . $this->database_name);
            $this->_mysqli->close();
            $this->_mysqli = null;
        }
    }

    /**
     * perform a login
     *
     * @param string $username Username
     * @param string $password Password
     *
     * @return void
     */
    public function login($username = '', $password = '')
    {
        if ($username == '') {
            $username = $GLOBALS['TESTSUITE_USER'];
        }
        if ($password == '') {
            $password = $GLOBALS['TESTSUITE_PASSWORD'];
        }
        $this->url('');
        $this->waitForElementNotPresent('byId', 'cfs-style');

        /* Return if already logged in */
        if ($this->isSuccessLogin()) {
            return;
        }
        $usernameField = $this->waitForElement('byId', 'input_username');
        $usernameField->value($username);
        $passwordField = $this->byId('input_password');
        $passwordField->value($password);
        $this->byId('input_go')->click();
    }

    /**
     * Checks whether the login is successful
     *
     * @return boolean
     */
    public function isSuccessLogin()
    {
        if ($this->isElementPresent("byXPath", "//*[@id=\"serverinfo\"]")) {
            return true;
        } else {
            return false;
        }
    }

    /**
    * Checks whether the login is unsuccessful
    *
    * @return boolean
    */
    public function isUnsuccessLogin()
    {
        if ($this->isElementPresent("byCssSelector", "div.error")) {
            return true;
        } else {
            return false;
        }
    }

    /**
    * Used to go to the homepage
    *
    * @return void
    */
    public function gotoHomepage()
    {
        $e = $this->byPartialLinkText("Server: ");
        $e->click();
        $this->waitForElementNotPresent('byCssSelector', 'div#loading_parent');
    }

    /**
     * Executes a database query
     *
     * @param string $query SQL Query to be executed
     *
     * @return void|boolean|mysqli_result
     *
     * @throws Exception
     */
    public function dbQuery($query)
    {
        return $this->_mysqli->query($query);
    }

    /**
     * Check if user is logged in to phpmyadmin
     *
     * @return boolean Where or not user is logged in
     */
    public function isLoggedIn()
    {
        return $this->isElementPresent(
            'byXPath', '//*[@id="serverinfo"]/a[1]'
        );
    }

    /**
     * Perform a logout, if logged in
     *
     * @return void
     */
    public function logOutIfLoggedIn()
    {
        if ($this->isLoggedIn()) {
            $this->byCssSelector("img.icon.ic_s_loggoff")->click();
        }
    }

    /**
     * Wait for an element to be present on the page
     *
     * @param string $func Locate using - byCss, byXPath, etc
     * @param string $arg  Selector
     *
     * @return PHPUnit_Extensions_Selenium2TestCase_Element  Element waited for
     */
    public function waitForElement($func, $arg)
    {
        $this->timeouts()->implicitWait(10000);
        $element = call_user_func_array(
            array($this, $func), array($arg)
        );
        $this->timeouts()->implicitWait(0);
        return $element;
    }

    /**
     * Wait for an element to disappear
     *
     * @param string $func Locate using - byCss, byXPath, etc
     * @param string $arg  Selector
     *
     * @return bool Whether or not the element disappeared
     */
    public function waitForElementNotPresent($func, $arg)
    {
        while (true) {
            if (!$this->isElementPresent($func, $arg)) {
                return true;
            }
            usleep(5000);
        }
    }

    /**
     * Sleeps while waiting for browser to perform an action.
     *
     * @todo This method should not be used, but rather there would be
     *       explicit waiting for some elements.
     *
     * @return void
     */
    public function sleep()
    {
        usleep(5000);
    }

    /**
     * Check if element is present or not
     *
     * @param string $func Locate using - byCss, byXPath, etc
     * @param string $arg  Selector
     *
     * @return bool Whether or not the element is present
     */
    public function isElementPresent($func, $arg)
    {
        try {
            $element = call_user_func_array(
                array($this, $func), array($arg)
            );
        } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
            // Element not present
            return false;
        } catch (InvalidArgumentException $e) {
            // Element not present
            return false;
        }
        // Element Present
        return true;
    }

    /**
     * Get table cell data by the ID of the table
     *
     * @param string $tableID Table identifier
     * @param int    $row     Table row
     * @param int    $column  Table column
     *
     * @return text Data from the particular table cell
     */
    public function getCellByTableId($tableID, $row, $column)
    {
        $sel = "table#{$tableID} tbody tr:nth-child({$row}) "
            . "td:nth-child({$column})";
        $element = $this->byCssSelector(
            $sel
        );
        return $element->text();
    }

    /**
     * Get table cell data by the class attribute of the table
     *
     * @param string $tableClass Class of the table
     * @param int    $row        Table row
     * @param int    $column     Table column
     *
     * @return text Data from the particular table cell
     */
    public function getCellByTableClass($tableClass, $row, $column)
    {
        $sel = "table.{$tableClass} tbody tr:nth-child({$row}) "
            . "td:nth-child({$column})";
        $element = $this->byCssSelector(
            $sel
        );
        return $element->text();
    }

    /**
     * Wrapper around keys method to not use it on not supported
     * browsers.
     *
     * @param string $text Keys to send
     *
     * @return void
     */
    public function keys($text)
    {
        /**
         * Not supported in Safari Webdriver, see
         * https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/4136
         */
        if (mb_strtolower($this->getBrowser()) == 'safari') {
            $this->markTestSkipped('Can not send keys to Safari browser.');
        }
        parent::keys($text);
    }

    /**
     * Wrapper around moveto method to not use it on not supported
     * browsers.
     *
     * @param object $element element
     *
     * @return void
     */
    public function moveto($element)
    {
        /**
         * Not supported in Safari Webdriver, see
         * https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/4136
         */
        if (mb_strtolower($this->getBrowser()) == 'safari') {
            $this->markTestSkipped('MoveTo not supported on Safari browser.');
        }
        parent::moveto($element);
    }

    /**
     * Wrapper around alertText method to not use it on not supported
     * browsers.
     *
     * @return mixed
     */
    public function alertText()
    {
        /**
         * Not supported in Safari Webdriver, see
         * https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/4136
         */
        if (mb_strtolower($this->getBrowser()) == 'safari') {
            $this->markTestSkipped('Alerts not supported on Safari browser.');
        }
        return parent::alertText();
    }

    /**
     * Type text in textarea (CodeMirror enabled)
     *
     * @param string $text Text to type
     *
     * @return void
     */
    public function typeInTextArea($text)
    {
        /**
         * Firefox needs some escaping of a text, see
         * https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/1723
         */
        if (mb_strtolower($this->getBrowser()) == 'firefox') {
            $text = str_replace(
                "(",
                PHPUnit_Extensions_Selenium2TestCase_Keys::SHIFT
                . PHPUnit_Extensions_Selenium2TestCase_Keys::NUMPAD9
                . PHPUnit_Extensions_Selenium2TestCase_Keys::NULL,
                $text
            );
        }

        $this->byClassName("CodeMirror-scroll")->click();
        $this->keys($text);
    }

    /**
     * Kills the More link in the menu
     *
     * @return void
     */
    public function expandMore()
    {
        try {
            $this->waitForElement('byCssSelector', 'li.submenu > a');
        } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
            return;
        }
        /* We need to resize to ensure it fits into accessible area */
        $this->execute(
            array(
                'script' => "$('#topmenu').css('font-size', '50%');"
                    . "$(window).resize()",
                'args' => array()
            )
        );
        $this->sleep();
    }

    /**
     * Navigates browser to a table page.
     *
     * @param string $table Name of table
     *
     * @return void
     */
    public function navigateTable($table)
    {
        // go to database page
        $this->waitForElement("byLinkText", $this->database_name)->click();

        /* Wait for loading and expanding tree */
        $this->waitForElement(
            'byCssSelector',
            'li.last.table'
        );

        /* TODO: Timing issue of expanding navigation tree */
        $this->sleep();

        // go to table page
        $this->waitForElement(
            "byXPath",
            "//*[@id='pma_navigation_tree_content']//a[contains(., '$table')]"
        )->click();

        // Wait for it to load
        $this->waitForElement(
            "byXPath",
            "//a[@class='tabactive' and contains(., 'Browse')]"
        );
    }
}
