<?php

class Robot {

    private 
$passTemplate ': <span style="color: green;">Pass</span>';
    private 
$failTemplate ': <span style="color: red;">Fail</span>';
    private 
$ch;
    
    function 
__construct() {
        
// Sometimes servers are configured with "&amp;" as their url separator.
        // This can break the url strings we construct so we'll change it to use the real "&" character.
        
ini_set('arg_separator.output''&');
        
$this->configureCurl();
    }
    
    
/**
     * Return a pass or fail template for test status reporting.
     *
     * @param $status String to tell us if the test passed or failed
     * @return Returns a string that contains a styled pass or fail message
     */
    
function getResultTemplate($status) {
        if (
$status == "passed") {
            return 
$this->passTemplate;
        } else {
            return 
$this->failTemplate;
        }
    }
    
    
/**
     * Encodes a string so it can be passed as a URL.
     *
     * @param $data Array of data to be used as arguments in a URL
     * @return Returns a URL encoded string
     */
    
function buildUrlQuery($data) {
        return 
http_build_query($data);
    }
    
    
/**
     * Sets up our cURL session.
     */
    
function configureCurl() {
        
// Open connection
        
$this->ch curl_init();
        
        
// Fake user agent
        //curl_setopt($this->ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1");

        // Handle cookies (this allows sessions to work)
        
curl_setopt($this->chCURLOPT_COOKIEFILE'cookies.txt');
        
        
// Automatically follow 302 HTTP redirects
        
curl_setopt($this->chCURLOPT_FOLLOWLOCATION1);
        
        
// Tells cURL to return any HTML instead of a boolean depending on request status
        
curl_setopt($this->chCURLOPT_RETURNTRANSFER1);
        
        
// Use a Post instead of usual Get
        
curl_setopt($this->chCURLOPT_POSTtrue);
    }

    
/**
     * Send a request (our test) to a server.
     *
     * @param $url String containing a URL that the test should be run against
     * @param $urlFields String containing URL encoded arguments
     * @return Returns a string containing the results of the curl request
     */
    
function runTest($url$urlFields) {
        
// Set the url
        
curl_setopt($this->chCURLOPT_URL$url);
        
        
// Assign form post fields from our data set
        
curl_setopt($this->chCURLOPT_POSTFIELDS$urlFields);
        
        
// Execute request
        
$result curl_exec($this->ch);
        
        
// Info about the post request
        //$info = curl_getinfo($this->ch);
        
        
return $result;
    }
}

class 
TodoRobot extends Robot {

    
/**
     * Tests our ability to login.
     *
     * @param $username String containing the username that should be used
     * @param $password String containing the password that should be used
     * @return Returns a formatted pass or fail string
     */
    
function testLogin($username$password) {
        
$urlArgs $this->buildUrlQuery(array("username" => $username"password" => $password));
        
$result $this->runTest("http://localhost/todo/login.php"$urlArgs);
        
        if (
preg_match('/Add\snew\sitem/'$result)) {
            return 
$this->getResultTemplate("passed");
        } else {
            return 
$this->getResultTemplate("failed");
        }    
    }
    
    
/**
     * Tests our ability to add a task.
     *
     * @return Returns a formatted pass or fail string
     */
    
function testAddingTask() {
        
$urlArgs $this->buildUrlQuery(array("item" => "Task added by robot!"));
        
$result $this->runTest("http://localhost/todo/addItem.php"$urlArgs);
        
        if (
preg_match('/Item\sadded/'$result)) {
            return 
$this->getResultTemplate("passed");
        } else {
            return 
$this->getResultTemplate("failed");
        }
    }
    
    
/**
     * Tests our ability to remove a task.
     *
     * @param $itemNumber String containing a numeric task ID
     * @return Returns a formatted pass or fail string
     */
    
function testRemovingTask($itemNumber) {
        
$urlArgs $this->buildUrlQuery(array("item" => $itemNumber));
        
$result $this->runTest("http://localhost/todo/remove.php"$urlArgs);
        
        if (
preg_match('/Item\sremoved/'$result)) {
            return 
$this->getResultTemplate("passed");
        } else {
            return 
$this->getResultTemplate("failed");
        }
    }
    
    
/**
     * Tests our ability to logout.
     *
     * @param $itemNumber String containing a numeric task ID
     * @return Returns a formatted pass or fail string
     */
    
function testLogout() {
        
$result $this->runTest("http://localhost/todo/logout.php""");
        
        if (
preg_match('/Logged\sout/'$result)) {
            return 
$this->getResultTemplate("passed");
        } else {
            return 
$this->getResultTemplate("failed");
        }
    }
}

$todoRobot = new TodoRobot();
echo 
"<h3>Login</h3>";
echo 
"Correct credentials"  $todoRobot->testLogin("test""password1");
echo 
"<br /><hr>";
echo 
"<h3>Add Task</h3>";
echo 
"Adding task" $todoRobot->testAddingTask();
echo 
"<br /><hr>";
echo 
"<h3>Remove Task</h3>";
echo 
"Remove task" $todoRobot->testRemovingTask("1");
echo 
"<br /><hr>";
echo 
"<h3>Logout</h3>";
echo 
"Logout" $todoRobot->testLogout();

?>