Skip to content
Snippets Groups Projects
WebqueryTest.php 23.7 KiB
Newer Older
namespace Tests\Library;

use GuzzleHttp\Psr7\Response;

class WebqueryTest extends \PHPUnit_Framework_TestCase {


    public function test_attributes() {

        $wq = new \Library\Webquery();
        $expect = [
            "host" => "library.wur.nl",
            "suffix" => "xml",
        ];
        $this->assertEquals($expect, $wq->get_attributes(), 'default attributes');

        $attribs = [
            "host" => "devel.library.wur.nl",
            "service" => "any",
        ];
        $wq->set_attributes($attribs);
        $this->assertEquals($attribs, $wq->get_attributes(), 'attributes after set_attributes()');

        $wq = new \Library\Webquery();
        $attribs = [
            "host" => "devel.library.wur.nl",
            "service" => "any",
        ];
        $expect = [
            "host" => "devel.library.wur.nl",
            "service" => "any",
            "suffix" => "xml",
        ];
        $wq->add_attributes($attribs);
        $this->assertEquals($expect, $wq->get_attributes(), 'attributes after add_attributes()');

        $wq = new \Library\Webquery();
        $value = "newhost";
        $wq->set_host($value);
        $this->assertEquals($value, $wq->get_host(), "set/get attribute host");
        $value = "newservice";
        $wq->set_service($value);
        $this->assertEquals($value, $wq->get_service(), "set/get attribute service");
        $value = "newsuffix";
        $wq->set_suffix($value);
        $this->assertEquals($value, $wq->get_suffix(), "set/get attribute suffix");
        $this->assertEquals("newservice", $wq->get_record_name(), "get attribute record_name if not yet set");
        $value = "newrecord";
        $wq->set_record_name($value);
        $this->assertEquals($value, $wq->get_record_name(), "set/get attribute record_name");

        $this->assertFalse($wq->is_dryrun(), "is dryrun mode, dryrun not set");
        $value = "<status>OK</status>";
        $wq->set_dryrun($value);
        $this->assertEquals($value, $wq->get_dryrun(), "set/get attribute dryrun");
        $this->assertTrue($wq->is_dryrun(), "is dryrun mode, dryrun is set");

        $value = ["timeout" => "40"];
        $wq->set_http_options($value);
        $this->assertEquals($value, $wq->get_http_options(), "set/get attribute http_options");
        $attribs = [
            "host" => "newhost",
            "service" => "newservice",
            "suffix" => "newsuffix",
            "record_name" => "newrecord",
            "dryrun" => "<status>OK</status>",
            "http_options" => ["timeout" => "40"],
        ];
        $this->assertEquals($attribs, $wq->get_attributes(), 'attributes after set_*');
    }


    public function test_get_query_string() {

        $tests = [
            ["qry" => "", "exp" => "", "ofs" => null, "max" => null, "msg" => "empty query string"],
            ["qry" => "a=1&b=2", "exp" => "a=1&b=2", "ofs" => null, "max" => null, "msg" => "simple query string"],
            ["qry" => "a=1&b=2", "exp" => "wq_ofs=3&a=1&b=2", "ofs" => 3, "max" => null, "msg" => "simple query string and wq_ofs"],
            ["qry" => "a=1&b=2", "exp" => "wq_ofs=3&wq_max=4&a=1&b=2", "ofs" => 3, "max" => 4, "msg" => "simple query string and wq_ofs and wq_max"],
            ["qry" => ["a" => 1], "exp" => "a=1", "ofs" => null, "max" => null, "msg" => "hash with 1 key/val pair"],
            ["qry" => ["a" => 1, "b" => "2"], "exp" => "wq_ofs=3&wq_max=4&a=1&b=2", "ofs" => 3, "max" => 4, "msg" => "hash with 2 key/val pairs and wq_ofs and wq_max"],
            ["qry" => ["a" => ["11", 12, "13"]], "exp" => "a=11&a=12&a=13", "ofs" => null, "max" => null, "msg" => "1 key/value pair, value is array with 3 values"],
            ["qry" => ["c" => "c1", "a" => ["11", 12], "b" => "b2"], "exp" => "c=c1&a=11&a=12&b=b2", "ofs" => null, "max" => null, "msg" => "3 key/value pairs, 2nd value is array with 2 values"],
            ["qry" => ["a" => "1", "!b" => "2"], "exp" => "a=1&wq_rel=AND+NOT&b=2", "ofs" => null, "max" => null, "msg" => "2 key/value pairs, second key has NOT prefix"],
            ["qry" => ["a"  => "1", "!b" => "2", "c"  => "3"], "exp" => "a=1&wq_rel=AND+NOT&b=2&c=3", "ofs" => null, "max" => null, "msg" => "3 key/value pairs, 2nd key has NOT prefix"],
            ["qry" => ["a"  => "1", "!b" => "2", "!c"  => "3"], "exp" => "a=1&wq_rel=AND+NOT&b=2&wq_rel=AND+NOT&c=3", "ofs" => null, "max" => null, "msg" => "3 key/value pairs, 2nd and 3rd key have NOT prefix"],
            ["qry" => ["c" => "3", "!a" => ["11", 12, "13"], "d" => "4"], "exp" => "c=3&wq_rel=AND+NOT&wq_par=open&a=11&a=12&a=13&wq_par=close&d=4", "ofs" => null, "max" => null, "msg" => "3 key/value pairs, 2nd value is array and has NOT prefix"],
            ["qry" => ["status" => "wacht op lener", "a" => "1"], "exp" => "status=wacht%20op%20lener&a=1", "ofs" => null, "max" => null, "msg" => "2 key/value pairs, value must be urlencoded"],
            ["qry" => ["status" => ["wacht op lener", "wacht op item"]], "exp" => "status=wacht%20op%20lener&status=wacht%20op%20item", "ofs" => null, "max" => null, "msg" => "1 key/value pair, value is array with 2 values which must be urlencoded"],
        ];

        $t = 0;
        foreach ($tests as $test) {
            $result = \Library\Webquery::get_query_string($test["qry"], $test["ofs"], $test["max"]);
            $this->assertEquals($test["exp"], $result, "$t: ".$test["msg"]);
            $t++;
        }
    }


    public function test_get_search_url() {

        // with default settings
        $wq = new \Library\Webquery();
        $expect = 'http://library.wur.nl/WebQuery//xml';
        $this->assertEquals($expect, $wq->get_search_url(), 'no properties set, default url');

        // with url properties set
        $wq = new \Library\Webquery();
        $wq->set_host('devel.library.wur.nl')
            ->set_service('testservice')
            ->set_suffix('record');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/record';
        $this->assertEquals($expect, $wq->get_search_url(), 'url properties set');
        // with isn set
        $wq = new \Library\Webquery();
        $wq->set_host('devel.library.wur.nl')
            ->set_service('testservice')
            ->set_suffix('record')
            ->set_isn("123");
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/record/123';
        $this->assertEquals($expect, $wq->get_search_url(), 'url properties set');

        // with query string set
        $wq = new \Library\Webquery();
        $wq->set_host('devel.library.wur.nl')
            ->set_service('anotherservice')
            ->set_query('q=*');
        $expect = 'http://devel.library.wur.nl/WebQuery/anotherservice/xml?q=*';
        $this->assertEquals($expect, $wq->get_search_url(), 'query string set');

        // with query array set
        $wq = new \Library\Webquery();
        $wq->set_service('aservice')
            ->set_query(["first" => "1", "second" => "2"]);
        $expect = 'http://library.wur.nl/WebQuery/aservice/xml?first=1&second=2';
        $this->assertEquals($expect, $wq->get_search_url(), 'query array set');

        // with query array set
        $wq = new \Library\Webquery();
        $wq->set_service('aservice')
            ->set_query("q=*")
            ->set_wq_ofs(10)
            ->set_wq_max(50);
        $expect = 'http://library.wur.nl/WebQuery/aservice/xml?wq_ofs=10&wq_max=50&q=*';
        $this->assertEquals($expect, $wq->get_search_url(), 'wq_ofs and wq_max set');
    }


    public function test_get_new_url() {

        // with default settings
        $wq = new \Library\Webquery();
        $expect = 'http://library.wur.nl/WebQuery//new_xml';
        $this->assertEquals($expect, $wq->get_new_url(), 'no properties set, default url');

        // with url properties set
        $wq = new \Library\Webquery();
        $wq->set_host('devel.library.wur.nl')
            ->set_service('testservice')
             ->set_suffix('record');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/new_record';
        $this->assertEquals($expect, $wq->get_new_url(), 'url properties set, default url');
    }


    public function test_get_update_url() {

        // with default settings
        $wq = new \Library\Webquery();
        $expect = 'http://library.wur.nl/WebQuery//update_xml/';
        $this->assertEquals($expect, $wq->get_update_url(), 'no properties set, default url');

        // with url properties set
        $wq = new \Library\Webquery();
        $wq->set_host('devel.library.wur.nl')
            ->set_service('testservice')
            ->set_suffix('record')
            ->set_isn("13");
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/update_record/13';
        $this->assertEquals($expect, $wq->get_update_url(), 'url properties set, default url');
    }


    public function test_search() {

        // create mock http client that stores requests and responses
        $request_history = [];
        $record_xml = <<<EOT
<record isn='13' crc='123abcde' cu='tester'>
    <sub1>subval1</sub1>
    <sub2>
        <child1>childval1</child1>
        <child2>childval2</child2>
    </sub2>
    <sub3>subval 3</sub3>
</record>
EOT;
        $resp1 = "<recordset><hits>1</hits>$record_xml<next wq_ofs='1' wq_max='1' /></recordset>";
        $resp2 = '<recordset><error code="WQW_NO_HITS"><message>nothing found</message></error></recordset>';
            new Response(200, [], $resp1),
            new Response(404, [], $resp2),
        ];
        $mock_httpclient = get_mock_httpclient($responses, $request_history);

        $wq = new \Library\Webquery();
        $wq->set_http_client($mock_httpclient);
        //$wq->set_logger(new \Monolog\Logger('search'));

        $wq->set_host('devel.library.wur.nl')
            ->set_service('testservice')
            ->set_record_name("record")
            ->set_query('record=*');

        // first request succeeds
        $result = $wq->search();
        $this->assertEquals($wq, $result, '1st: search returns self');
        $this->assertEquals('200', $wq->get_http_status(), '1st: response http status');
        $resp_body = $wq->get_response()->getBody();
        $this->assertEquals($resp1, $resp_body, '1st: search response body');
        $resp_xml = $wq->get_resp_xml();
        $expect = simplexml_load_string($resp_body);
        $this->assertEquals($expect, $resp_xml, '1st: search response xml');
        $record = $wq->get_record();
        $expect = simplexml_load_string($record_xml);
        $this->assertEquals($expect, $record, '1st: search response record');
        $records = $wq->get_records();
        $expect = [$expect];  // array with 1 record
        $this->assertEquals($expect, $records, '1st: search response records');
        $this->assertEquals('', $wq->get_error_code(), '1st: search response error code');
        $this->assertEquals('', $wq->get_error_message(), '1st: search response error message');
        $this->assertEquals(1, $wq->get_hits(), '1st: search response hits');
        $this->assertTrue($wq->has_next(), '1st: search response has next element');
        $this->assertEquals(1, $wq->get_next_ofs(), '1st: search response next wq_ofs');

        // second request fails
        $wq->set_query('record=nothing');
        $result = $wq->search();
        $this->assertEquals($wq, $result, '2nd: search returns self');
        $this->assertEquals('404', $wq->get_http_status(), '2nd: response http status');
        $resp_body = $wq->get_response()->getBody();
        $this->assertEquals($resp2, $resp_body, '2nd: search response body');
        $resp_xml = $wq->get_resp_xml();
        $expect = simplexml_load_string($resp_body);
        $this->assertEquals($expect, $resp_xml, '2nd: search response xml');
        $record = $wq->get_record();
        $expect = false;
        $this->assertEquals($expect, $record, '2nd: search response record');
        $records = $wq->get_records();
        $expect = [];
        $this->assertEquals($expect, $records, '2nd: search response records');
        $this->assertEquals('WQW_NO_HITS', $wq->get_error_code(), '2nd: search response error code');
        $this->assertEquals('nothing found', $wq->get_error_message(), '2nd: search response error message');
        $this->assertEquals(false, $wq->get_hits(), '2nd: search response hits');
        $this->assertFalse($wq->has_next(), '1st: search response has next element');
        $this->assertEquals(false, $wq->get_next_ofs(), '2nd: search response next wq_ofs');

        $this->assertEquals(2, count($request_history), 'request history count');
        // check first request
        $request = $request_history[0]['request'];
        $this->assertEquals('GET', $request->getMethod(), 'request 1 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/xml?record=*';
        $this->assertEquals($expect, $request->getUri(), 'request 1 url');
        // check second request
        $request = $request_history[1]['request'];
        $this->assertEquals('GET', $request->getMethod(), 'request 2 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/xml?record=nothing';
        $this->assertEquals($expect, $request->getUri(), 'request 2 url');

    public function test_search_all_records() {

        // create mock http client that stores requests and responses
        $request_history = [];
        $record1 = "<record isn='1' crc='11111111'><seq>1</seq></record>";
        $record2 = "<record isn='2' crc='22222222'><seq>2</seq></record>";
        $record3 = "<record isn='3' crc='33333333'><seq>3</seq></record>";
        $record4 = "<record isn='4' crc='44444444'><seq>4</seq></record>";
        $record5 = "<record isn='5' crc='55555555'><seq>5</seq></record>";
        $resp1 = "<recordset><hits>2</hits>${record1}${record2}<next wq_ofs='2' wq_max='2' /></recordset>";
        $resp2 = "<recordset><hits>2</hits>${record3}${record4}<next wq_ofs='4' wq_max='2' /></recordset>";
        $resp3 = "<recordset><hits>1</hits>$record5</recordset>";
        $resp4 = '<recordset><error code="WQW_NO_HITS"><message>nothing found</message></error></recordset>';
        $responses = [
            new Response(200, [], $resp1),
            new Response(200, [], $resp2),
            new Response(200, [], $resp3),
            new Response(404, [], $resp4),
        ];
        $mock_httpclient = get_mock_httpclient($responses, $request_history);

        $wq = new \Library\Webquery();
        $wq->set_http_client($mock_httpclient);
        //$wq->set_logger(new \Monolog\Logger('search_all_records'));

        $wq->set_host('devel.library.wur.nl')
            ->set_service('test')
            ->set_record_name("record")
            ->set_wq_max(2)
            ->set_query('record=*');

        // search request succeeds
        $result = $wq->search_all_records();
        $this->assertEquals(5, count($result), 'number of records returned');
        $this->assertEquals('200', $wq->get_http_status(), 'response http status last request');

        // check request history
        $this->assertEquals(3, count($request_history), 'request history count');
        // check first request
        $request = $request_history[0]['request'];
        $this->assertEquals('GET', $request->getMethod(), 'request 1 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/test/xml?wq_max=2&record=*';
        $this->assertEquals($expect, (string) $request->getUri(), 'request 1 url');
        // check second request
        $request = $request_history[1]['request'];
        $this->assertEquals('GET', $request->getMethod(), 'request 2 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/test/xml?wq_ofs=2&wq_max=2&record=*';
        $this->assertEquals($expect, (string) $request->getUri(), 'request 2 url');
        // check third request
        $request = $request_history[2]['request'];
        $this->assertEquals('GET', $request->getMethod(), 'request 3 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/test/xml?wq_ofs=4&wq_max=2&record=*';
        $this->assertEquals($expect, (string) $request->getUri(), 'request 3 url');
    public function test_xml_to_wwwform() {

        $xml = get_test_xml();
        $wq = new \Library\Webquery();
        $wwwform = $wq->xml_to_wwwform($xml);
        $expect = 'sub1=subval1&sub2=&child1=childval1&child2=childval2&sub3=subval+3';
        $this->assertEquals($expect, $wwwform, 'record in x-www-form-urlencoded string');
    }

    public function test_create_record() {

        // create mock http client that stores requests and responses
        $request_history = [];
        $responses = [
            new Response(200, [], '<recordset><error status="200" isn="13"><code>WQW_UPDATE_OK</code><message>record created</message></error></recordset>'),
            new Response(500, [], '<recordset><error status="501"><code>WQE_FAILED</code><message>record not created</message></error></recordset>'),
        ];
        $mock_httpclient = get_mock_httpclient($responses, $request_history);

        $wq = new \Library\Webquery();
        $wq->set_http_client($mock_httpclient);
        //$wq->set_logger(new \Monolog\Logger('create_record'));

        $wq->set_host('devel.library.wur.nl')
            ->set_service('testservice');

        $xml = get_test_xml();

        // first request succeeds
        $result = $wq->create_record($xml);
        $this->assertTrue($result, 'first request return value');
        $this->assertEquals('200', $wq->get_error_status(), 'first response error status');
        $this->assertEquals('WQW_UPDATE_OK', $wq->get_error_code(), 'first response error code');
        $this->assertEquals('record created', $wq->get_error_message(), 'first response error message');
        $this->assertEquals('13', $wq->get_new_isn(), 'first response isn');

        // second request fails
        $wq->set_suffix('record');
        $result = $wq->create_record($xml);
        $this->assertFalse($result, 'second request return value');
        $this->assertEquals('501', $wq->get_error_status(), 'second response error status');
        $this->assertEquals('WQE_FAILED', $wq->get_error_code(), 'second response error code');
        $this->assertEquals('record not created', $wq->get_error_message(), 'second response error message');
        $this->assertEquals('', $wq->get_new_isn(), 'second response isn');

        $this->assertEquals(2, count($request_history), 'request history count');
        // check first request
        $request = $request_history[0]['request'];
        $this->assertEquals('POST', $request->getMethod(), 'request 1 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/new_xml';
        $this->assertEquals($expect, $request->getUri(), 'request 1 url');
        $expect = 'sub1=subval1&sub2=&child1=childval1&child2=childval2&sub3=subval+3';
        $this->assertEquals($expect, $request->getBody(), 'request 1 body');
        // check second request
        $request = $request_history[1]['request'];
        $this->assertEquals('POST', $request->getMethod(), 'request 2 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/new_record';
        $this->assertEquals($expect, $request->getUri(), 'request 2 url');
        $expect = 'sub1=subval1&sub2=&child1=childval1&child2=childval2&sub3=subval+3';
        $this->assertEquals($expect, $request->getBody(), 'request 2 body');
    }

    public function test_update_record() {

        // create mock http client that stores requests and responses
        $request_history = [];
        $record_13 = "<record isn='13' crc='123abcde' cu='tester'><a>0</a><a>1</a><b>2</b></record>";
        $resp_13 = "<recordset><error status='200' isn='13'><code>WQW_UPDATE_OK</code><message>record updated</message></error>$record_13</recordset>";
        $resp_err = "<recordset><error status='501'><code>WQE_FAILED</code><message>record not updated</message></error></recordset>";
        $responses = [
            new Response(200, [], $resp_13),
            new Response(500, [], $resp_err),
        ];
        $mock_httpclient = get_mock_httpclient($responses, $request_history);
        $wq = new \Library\Webquery();
        $wq->set_http_client($mock_httpclient);
        //$wq->set_logger(new \Monolog\Logger('create_record'));

        $wq->set_host('devel.library.wur.nl')
            ->set_service('testservice');

        $data = "a=&a=1&b=2";

        // first request succeeds
        $result = $wq->set_isn("13")->update_record($data);
        $this->assertTrue($result, 'first request return value');
        $this->assertEquals('200', $wq->get_error_status(), 'first response error status');
        $this->assertEquals('WQW_UPDATE_OK', $wq->get_error_code(), 'first response error code');
        $this->assertEquals('record updated', $wq->get_error_message(), 'first response error message');
        $this->assertEquals('13', $wq->get_new_isn(), 'first response isn');

        // second request fails
        $wq->set_suffix('record')->set_isn("14");
        $result = $wq->update_record("$data&c=3");
        $this->assertFalse($result, 'second request return value');
        $this->assertEquals('501', $wq->get_error_status(), 'second response error status');
        $this->assertEquals('WQE_FAILED', $wq->get_error_code(), 'second response error code');
        $this->assertEquals('record not updated', $wq->get_error_message(), 'second response error message');
        $this->assertEquals('', $wq->get_new_isn(), 'second response isn');

        $this->assertEquals(2, count($request_history), 'request history count');
        // check first request
        $request = $request_history[0]['request'];
        $this->assertEquals('POST', $request->getMethod(), 'request 1 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/update_xml/13';
        $this->assertEquals($expect, $request->getUri(), 'request 1 url');
        $this->assertEquals($data, $request->getBody(), 'request 1 body');
        // check second request
        $request = $request_history[1]['request'];
        $this->assertEquals('POST', $request->getMethod(), 'request 2 method');
        $expect = 'http://devel.library.wur.nl/WebQuery/testservice/update_record/14';
        $this->assertEquals($expect, $request->getUri(), 'request 2 url');
        $this->assertEquals("$data&c=3", $request->getBody(), 'request 2 body');
    }


    public function test_dryrun() {

        $wq = new \Library\Webquery();
        //$wq->set_logger(new \Monolog\Logger('dryrun'));
        $dryrun_resp = "<test-set><hits>1</hits><test>OK</test><test-set>";
        $wq->set_attributes([
                "host" => "localhost",
                "service" => "test",
                "dryrun" => $dryrun_resp,
            ])
            ->set_query('test=*');

        // test post
        $result = $wq->set_isn("1")->http_client_post($wq->get_update_url(), "post=data");
        $this->assertEquals('200', $result->getStatusCode(), 'http get response http status');
        $this->assertEquals($dryrun_resp, $result->getBody(), 'http get response body');
    }

/***********  Helper Functions    **************/

function get_test_xml() {

    $xml_txt = <<<EOT
<record>
    <sub1>subval1</sub1>
    <sub2>
        <child1>childval1</child1>
        <child2>childval2</child2>
    </sub2>
    <sub3>subval 3</sub3>
</record>
EOT;
    $wq = new \Library\Webquery();
    return $wq->parse_xml($xml_txt);
}


function get_mock_httpclient(array $mock_responses, array &$history = null) {

    foreach ($mock_responses as $key => $value) {
        if (is_int($value)) {
            $mock_responses[$key] = new \GuzzleHttp\Psr7\Response($value);
        }
    }
    $mock_handler = new \GuzzleHttp\Handler\MockHandler($mock_responses);
    $mock_stack = \GuzzleHttp\HandlerStack::create($mock_handler);
    if (isset($history)) {
        $mock_history = \GuzzleHttp\Middleware::history($history);
        $mock_stack->push($mock_history);
    }
    return new \GuzzleHttp\Client(['handler' => $mock_stack]);
}