Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
    /**
3
     *	Base include file for SimpleTest.
4
     *	@package	SimpleTest
5
     *	@subpackage	WebTester
6
     *	@version	$Id: web_tester.php 1398 2006-09-08 19:31:03Z xue $
7
     */
8
 
9
    /**#@+
10
     *	include other SimpleTest class files
11
     */
12
    require_once(dirname(__FILE__) . '/test_case.php');
13
    require_once(dirname(__FILE__) . '/browser.php');
14
    require_once(dirname(__FILE__) . '/page.php');
15
    require_once(dirname(__FILE__) . '/expectation.php');
16
    /**#@-*/
17
 
18
    /**
19
     *    Test for an HTML widget value match.
20
	 *	  @package SimpleTest
21
	 *	  @subpackage WebTester
22
     */
23
    class FieldExpectation extends SimpleExpectation {
24
        protected $_value;
25
 
26
        /**
27
         *    Sets the field value to compare against.
28
         *    @param mixed $value     Test value to match. Can be an
29
         *                            expectation for say pattern matching.
30
         *    @param string $message  Optiona message override. Can use %s as
31
         *                            a placeholder for the original message.
32
         *    @access public
33
         */
34
        function FieldExpectation($value, $message = '%s') {
35
            $this->SimpleExpectation($message);
36
            if (is_array($value)) {
37
                sort($value);
38
            }
39
            $this->_value = $value;
40
        }
41
 
42
        /**
43
         *    Tests the expectation. True if it matches
44
         *    a string value or an array value in any order.
45
         *    @param mixed $compare        Comparison value. False for
46
         *                                 an unset field.
47
         *    @return boolean              True if correct.
48
         *    @access public
49
         */
50
        function test($compare) {
51
            if ($this->_value === false) {
52
                return ($compare === false);
53
            }
54
            if ($this->_isSingle($this->_value)) {
55
                return $this->_testSingle($compare);
56
            }
57
            if (is_array($this->_value)) {
58
                return $this->_testMultiple($compare);
59
            }
60
            return false;
61
        }
62
 
63
        /**
64
         *    Tests for valid field comparisons with a single option.
65
         *    @param mixed $value       Value to type check.
66
         *    @return boolean           True if integer, string or float.
67
         *    @access private
68
         */
69
        function _isSingle($value) {
70
            return is_string($value) || is_integer($value) || is_float($value);
71
        }
72
 
73
        /**
74
         *    String comparison for simple field with a single option.
75
         *    @param mixed $compare    String to test against.
76
         *    @returns boolean         True if matching.
77
         *    @access private
78
         */
79
        function _testSingle($compare) {
80
            if (is_array($compare) && count($compare) == 1) {
81
                $compare = $compare[0];
82
            }
83
            if (! $this->_isSingle($compare)) {
84
                return false;
85
            }
86
            return ($this->_value == $compare);
87
        }
88
 
89
        /**
90
         *    List comparison for multivalue field.
91
         *    @param mixed $compare    List in any order to test against.
92
         *    @returns boolean         True if matching.
93
         *    @access private
94
         */
95
        function _testMultiple($compare) {
96
            if (is_string($compare)) {
97
                $compare = array($compare);
98
            }
99
            if (! is_array($compare)) {
100
                return false;
101
            }
102
            sort($compare);
103
            return ($this->_value === $compare);
104
        }
105
 
106
        /**
107
         *    Returns a human readable test message.
108
         *    @param mixed $compare      Comparison value.
109
         *    @return string             Description of success
110
         *                               or failure.
111
         *    @access public
112
         */
113
        function testMessage($compare) {
114
            $dumper = $this->_getDumper();
115
            if (is_array($compare)) {
116
                sort($compare);
117
            }
118
            if ($this->test($compare)) {
119
                return "Field expectation [" . $dumper->describeValue($this->_value) . "]";
120
            } else {
121
                return "Field expectation [" . $dumper->describeValue($this->_value) .
122
                        "] fails with [" .
123
                        $this->_dumper->describeValue($compare) . "] " .
124
                        $this->_dumper->describeDifference($this->_value, $compare);
125
            }
126
        }
127
    }
128
 
129
    /**
130
     *    Test for a specific HTTP header within a header block.
131
	 *	  @package SimpleTest
132
	 *	  @subpackage WebTester
133
     */
134
    class HttpHeaderExpectation extends SimpleExpectation {
135
        protected $_expected_header;
136
        protected $_expected_value;
137
 
138
        /**
139
         *    Sets the field and value to compare against.
140
         *    @param string $header   Case insenstive trimmed header name.
141
         *    @param mixed $value     Optional value to compare. If not
142
         *                            given then any value will match. If
143
         *                            an expectation object then that will
144
         *                            be used instead.
145
         *    @param string $message  Optiona message override. Can use %s as
146
         *                            a placeholder for the original message.
147
         */
148
        function HttpHeaderExpectation($header, $value = false, $message = '%s') {
149
            $this->SimpleExpectation($message);
150
            $this->_expected_header = $this->_normaliseHeader($header);
151
            $this->_expected_value = $value;
152
        }
153
 
154
        /**
155
         *    Accessor for aggregated object.
156
         *    @return mixed        Expectation set in constructor.
157
         *    @access protected
158
         */
159
        function _getExpectation() {
160
            return $this->_expected_value;
161
        }
162
 
163
        /**
164
         *    Removes whitespace at ends and case variations.
165
         *    @param string $header    Name of header.
166
         *    @param string            Trimmed and lowecased header
167
         *                             name.
168
         *    @access private
169
         */
170
        function _normaliseHeader($header) {
171
            return strtolower(trim($header));
172
        }
173
 
174
        /**
175
         *    Tests the expectation. True if it matches
176
         *    a string value or an array value in any order.
177
         *    @param mixed $compare   Raw header block to search.
178
         *    @return boolean         True if header present.
179
         *    @access public
180
         */
181
        function test($compare) {
182
            return is_string($this->_findHeader($compare));
183
        }
184
 
185
        /**
186
         *    Searches the incoming result. Will extract the matching
187
         *    line as text.
188
         *    @param mixed $compare   Raw header block to search.
189
         *    @return string          Matching header line.
190
         *    @access protected
191
         */
192
        function _findHeader($compare) {
193
            $lines = split("\r\n", $compare);
194
            foreach ($lines as $line) {
195
                if ($this->_testHeaderLine($line)) {
196
                    return $line;
197
                }
198
            }
199
            return false;
200
        }
201
 
202
        /**
203
         *    Compares a single header line against the expectation.
204
         *    @param string $line      A single line to compare.
205
         *    @return boolean          True if matched.
206
         *    @access private
207
         */
208
        function _testHeaderLine($line) {
209
            if (count($parsed = split(':', $line, 2)) < 2) {
210
                return false;
211
            }
212
            list($header, $value) = $parsed;
213
            if ($this->_normaliseHeader($header) != $this->_expected_header) {
214
                return false;
215
            }
216
            return $this->_testHeaderValue($value, $this->_expected_value);
217
        }
218
 
219
        /**
220
         *    Tests the value part of the header.
221
         *    @param string $value        Value to test.
222
         *    @param mixed $expected      Value to test against.
223
         *    @return boolean             True if matched.
224
         *    @access protected
225
         */
226
        function _testHeaderValue($value, $expected) {
227
            if ($expected === false) {
228
                return true;
229
            }
230
            if (SimpleExpectation::isExpectation($expected)) {
231
                return $expected->test(trim($value));
232
            }
233
            return (trim($value) == trim($expected));
234
        }
235
 
236
        /**
237
         *    Returns a human readable test message.
238
         *    @param mixed $compare      Raw header block to search.
239
         *    @return string             Description of success
240
         *                               or failure.
241
         *    @access public
242
         */
243
        function testMessage($compare) {
244
            if (SimpleExpectation::isExpectation($this->_expected_value)) {
245
                $message = $this->_expected_value->testMessage($compare);
246
            } else {
247
                $message = $this->_expected_header .
248
                        ($this->_expected_value ? ': ' . $this->_expected_value : '');
249
            }
250
            if (is_string($line = $this->_findHeader($compare))) {
251
                return "Searching for header [$message] found [$line]";
252
            } else {
253
                return "Failed to find header [$message]";
254
            }
255
        }
256
    }
257
 
258
    /**
259
     *    Test for a specific HTTP header within a header block that
260
     *    should not be found.
261
	 *	  @package SimpleTest
262
	 *	  @subpackage WebTester
263
     */
264
    class NoHttpHeaderExpectation extends HttpHeaderExpectation {
265
        protected $_expected_header;
266
        protected $_expected_value;
267
 
268
        /**
269
         *    Sets the field and value to compare against.
270
         *    @param string $unwanted   Case insenstive trimmed header name.
271
         *    @param string $message    Optiona message override. Can use %s as
272
         *                              a placeholder for the original message.
273
         */
274
        function NoHttpHeaderExpectation($unwanted, $message = '%s') {
275
            $this->HttpHeaderExpectation($unwanted, false, $message);
276
        }
277
 
278
        /**
279
         *    Tests that the unwanted header is not found.
280
         *    @param mixed $compare   Raw header block to search.
281
         *    @return boolean         True if header present.
282
         *    @access public
283
         */
284
        function test($compare) {
285
            return ($this->_findHeader($compare) === false);
286
        }
287
 
288
        /**
289
         *    Returns a human readable test message.
290
         *    @param mixed $compare      Raw header block to search.
291
         *    @return string             Description of success
292
         *                               or failure.
293
         *    @access public
294
         */
295
        function testMessage($compare) {
296
            $expectation = $this->_getExpectation();
297
            if (is_string($line = $this->_findHeader($compare))) {
298
                return "Found unwanted header [$expectation] with [$line]";
299
            } else {
300
                return "Did not find unwanted header [$expectation]";
301
            }
302
        }
303
    }
304
 
305
    /**
306
     *    Test for a text substring.
307
	 *	  @package SimpleTest
308
	 *	  @subpackage UnitTester
309
     */
310
    class TextExpectation extends SimpleExpectation {
311
        protected $_substring;
312
 
313
        /**
314
         *    Sets the value to compare against.
315
         *    @param string $substring  Text to search for.
316
         *    @param string $message    Customised message on failure.
317
         *    @access public
318
         */
319
        function TextExpectation($substring, $message = '%s') {
320
            $this->SimpleExpectation($message);
321
            $this->_substring = $substring;
322
        }
323
 
324
        /**
325
         *    Accessor for the substring.
326
         *    @return string       Text to match.
327
         *    @access protected
328
         */
329
        function _getSubstring() {
330
            return $this->_substring;
331
        }
332
 
333
        /**
334
         *    Tests the expectation. True if the text contains the
335
         *    substring.
336
         *    @param string $compare        Comparison value.
337
         *    @return boolean               True if correct.
338
         *    @access public
339
         */
340
        function test($compare) {
341
            return (strpos($compare, $this->_substring) !== false);
342
        }
343
 
344
        /**
345
         *    Returns a human readable test message.
346
         *    @param mixed $compare      Comparison value.
347
         *    @return string             Description of success
348
         *                               or failure.
349
         *    @access public
350
         */
351
        function testMessage($compare) {
352
            if ($this->test($compare)) {
353
                return $this->_describeTextMatch($this->_getSubstring(), $compare);
354
            } else {
355
                $dumper = $this->_getDumper();
356
                return "Text [" . $this->_getSubstring() .
357
                        "] not detected in [" .
358
                        $dumper->describeValue($compare) . "]";
359
            }
360
        }
361
 
362
        /**
363
         *    Describes a pattern match including the string
364
         *    found and it's position.
365
         *    @param string $substring      Text to search for.
366
         *    @param string $subject        Subject to search.
367
         *    @access protected
368
         */
369
        function _describeTextMatch($substring, $subject) {
370
            $position = strpos($subject, $substring);
371
            $dumper = $this->_getDumper();
372
            return "Text [$substring] detected at character [$position] in [" .
373
                    $dumper->describeValue($subject) . "] in region [" .
374
                    $dumper->clipString($subject, 100, $position) . "]";
375
        }
376
    }
377
 
378
    /**
379
     *    Fail if a substring is detected within the
380
     *    comparison text.
381
	 *	  @package SimpleTest
382
	 *	  @subpackage UnitTester
383
     */
384
    class NoTextExpectation extends TextExpectation {
385
 
386
        /**
387
         *    Sets the reject pattern
388
         *    @param string $substring  Text to search for.
389
         *    @param string $message    Customised message on failure.
390
         *    @access public
391
         */
392
        function NoTextExpectation($substring, $message = '%s') {
393
            $this->TextExpectation($substring, $message);
394
        }
395
 
396
        /**
397
         *    Tests the expectation. False if the substring appears
398
         *    in the text.
399
         *    @param string $compare        Comparison value.
400
         *    @return boolean               True if correct.
401
         *    @access public
402
         */
403
        function test($compare) {
404
            return ! parent::test($compare);
405
        }
406
 
407
        /**
408
         *    Returns a human readable test message.
409
         *    @param string $compare      Comparison value.
410
         *    @return string              Description of success
411
         *                                or failure.
412
         *    @access public
413
         */
414
        function testMessage($compare) {
415
            if ($this->test($compare)) {
416
                $dumper = $this->_getDumper();
417
                return "Text [" . $this->_getSubstring() .
418
                        "] not detected in [" .
419
                        $dumper->describeValue($compare) . "]";
420
            } else {
421
                return $this->_describeTextMatch($this->_getSubstring(), $compare);
422
            }
423
        }
424
    }
425
 
426
    /**
427
     *    Test case for testing of web pages. Allows
428
     *    fetching of pages, parsing of HTML and
429
     *    submitting forms.
430
	 *    @package SimpleTest
431
	 *    @subpackage WebTester
432
     */
433
    class WebTestCase extends SimpleTestCase {
434
        protected $_browser;
435
        protected $_ignore_errors = false;
436
 
437
        /**
438
         *    Creates an empty test case. Should be subclassed
439
         *    with test methods for a functional test case.
440
         *    @param string $label     Name of test case. Will use
441
         *                             the class name if none specified.
442
         *    @access public
443
         */
444
        function WebTestCase($label = false) {
445
            $this->SimpleTestCase($label);
446
        }
447
 
448
        /**
449
         *    Announces the start of the test.
450
         *    @param string $method    Test method just started.
451
         *    @access public
452
         */
453
        function before($method) {
454
            parent::before($method);
455
            $this->setBrowser($this->createBrowser());
456
        }
457
 
458
        /**
459
         *    Announces the end of the test. Includes private clean up.
460
         *    @param string $method    Test method just finished.
461
         *    @access public
462
         */
463
        function after($method) {
464
            $this->unsetBrowser();
465
            parent::after($method);
466
        }
467
 
468
        /**
469
         *    Gets a current browser reference for setting
470
         *    special expectations or for detailed
471
         *    examination of page fetches.
472
         *    @return SimpleBrowser     Current test browser object.
473
         *    @access public
474
         */
475
        function &getBrowser() {
476
            return $this->_browser;
477
        }
478
 
479
        /**
480
         *    Gets a current browser reference for setting
481
         *    special expectations or for detailed
482
         *    examination of page fetches.
483
         *    @param SimpleBrowser $browser    New test browser object.
484
         *    @access public
485
         */
486
        function setBrowser($browser) {
487
            return $this->_browser = $browser;
488
        }
489
 
490
        /**
491
         *    Clears the current browser reference to help the
492
         *    PHP garbage collector.
493
         *    @access public
494
         */
495
        function unsetBrowser() {
496
            unset($this->_browser);
497
        }
498
 
499
        /**
500
         *    Creates a new default web browser object.
501
         *    Will be cleared at the end of the test method.
502
         *    @return TestBrowser           New browser.
503
         *    @access public
504
         */
505
        function &createBrowser() {
506
            $browser = new SimpleBrowser();
507
            return $browser;
508
        }
509
 
510
        /**
511
         *    Gets the last response error.
512
         *    @return string    Last low level HTTP error.
513
         *    @access public
514
         */
515
        function getTransportError() {
516
            return $this->_browser->getTransportError();
517
        }
518
 
519
        /**
520
         *    Accessor for the currently selected URL.
521
         *    @return string        Current location or false if
522
         *                          no page yet fetched.
523
         *    @access public
524
         */
525
        function getUrl() {
526
            return $this->_browser->getUrl();
527
        }
528
 
529
        /**
530
         *    Dumps the current request for debugging.
531
         *    @access public
532
         */
533
        function showRequest() {
534
            $this->dump($this->_browser->getRequest());
535
        }
536
 
537
        /**
538
         *    Dumps the current HTTP headers for debugging.
539
         *    @access public
540
         */
541
        function showHeaders() {
542
            $this->dump($this->_browser->getHeaders());
543
        }
544
 
545
        /**
546
         *    Dumps the current HTML source for debugging.
547
         *    @access public
548
         */
549
        function showSource() {
550
            $this->dump($this->_browser->getContent());
551
        }
552
 
553
        /**
554
         *    Dumps the visible text only for debugging.
555
         *    @access public
556
         */
557
        function showText() {
558
            $this->dump(wordwrap($this->_browser->getContentAsText(), 80));
559
        }
560
 
561
        /**
562
         *    Simulates the closing and reopening of the browser.
563
         *    Temporary cookies will be discarded and timed
564
         *    cookies will be expired if later than the
565
         *    specified time.
566
         *    @param string/integer $date Time when session restarted.
567
         *                                If ommitted then all persistent
568
         *                                cookies are kept. Time is either
569
         *                                Cookie format string or timestamp.
570
         *    @access public
571
         */
572
        function restart($date = false) {
573
            if ($date === false) {
574
                $date = time();
575
            }
576
            $this->_browser->restart($date);
577
        }
578
 
579
        /**
580
         *    Moves cookie expiry times back into the past.
581
         *    Useful for testing timeouts and expiries.
582
         *    @param integer $interval    Amount to age in seconds.
583
         *    @access public
584
         */
585
        function ageCookies($interval) {
586
            $this->_browser->ageCookies($interval);
587
        }
588
 
589
        /**
590
         *    Disables frames support. Frames will not be fetched
591
         *    and the frameset page will be used instead.
592
         *    @access public
593
         */
594
        function ignoreFrames() {
595
            $this->_browser->ignoreFrames();
596
        }
597
 
598
        /**
599
         *    Switches off cookie sending and recieving.
600
         *    @access public
601
         */
602
        function ignoreCookies() {
603
            $this->_browser->ignoreCookies();
604
        }
605
 
606
        /**
607
         *    Skips errors for the next request only. You might
608
         *    want to confirm that a page is unreachable for
609
         *    example.
610
         *    @access public
611
         */
612
        function ignoreErrors() {
613
            $this->_ignore_errors = true;
614
        }
615
 
616
        /**
617
         *    Issues a fail if there is a transport error anywhere
618
         *    in the current frameset. Only one such error is
619
         *    reported.
620
         *    @param string/boolean $result   HTML or failure.
621
         *    @return string/boolean $result  Passes through result.
622
         *    @access private
623
         */
624
        function _failOnError($result) {
625
            if (! $this->_ignore_errors) {
626
                if ($error = $this->_browser->getTransportError()) {
627
                    $this->fail($error);
628
                }
629
            }
630
            $this->_ignore_errors = false;
631
            return $result;
632
        }
633
 
634
        /**
635
         *    Adds a header to every fetch.
636
         *    @param string $header       Header line to add to every
637
         *                                request until cleared.
638
         *    @access public
639
         */
640
        function addHeader($header) {
641
            $this->_browser->addHeader($header);
642
        }
643
 
644
        /**
645
         *    Sets the maximum number of redirects before
646
         *    the web page is loaded regardless.
647
         *    @param integer $max        Maximum hops.
648
         *    @access public
649
         */
650
        function setMaximumRedirects($max) {
651
            if (! $this->_browser) {
652
                trigger_error(
653
                        'Can only set maximum redirects in a test method, setUp() or tearDown()');
654
            }
655
            $this->_browser->setMaximumRedirects($max);
656
        }
657
 
658
        /**
659
         *    Sets the socket timeout for opening a connection and
660
         *    receiving at least one byte of information.
661
         *    @param integer $timeout      Maximum time in seconds.
662
         *    @access public
663
         */
664
        function setConnectionTimeout($timeout) {
665
            $this->_browser->setConnectionTimeout($timeout);
666
        }
667
 
668
        /**
669
         *    Sets proxy to use on all requests for when
670
         *    testing from behind a firewall. Set URL
671
         *    to false to disable.
672
         *    @param string $proxy        Proxy URL.
673
         *    @param string $username     Proxy username for authentication.
674
         *    @param string $password     Proxy password for authentication.
675
         *    @access public
676
         */
677
        function useProxy($proxy, $username = false, $password = false) {
678
            $this->_browser->useProxy($proxy, $username, $password);
679
        }
680
 
681
        /**
682
         *    Fetches a page into the page buffer. If
683
         *    there is no base for the URL then the
684
         *    current base URL is used. After the fetch
685
         *    the base URL reflects the new location.
686
         *    @param string $url          URL to fetch.
687
         *    @param hash $parameters     Optional additional GET data.
688
         *    @return boolean/string      Raw page on success.
689
         *    @access public
690
         */
691
        function get($url, $parameters = false) {
692
            return $this->_failOnError($this->_browser->get($url, $parameters));
693
        }
694
 
695
        /**
696
         *    Fetches a page by POST into the page buffer.
697
         *    If there is no base for the URL then the
698
         *    current base URL is used. After the fetch
699
         *    the base URL reflects the new location.
700
         *    @param string $url          URL to fetch.
701
         *    @param hash $parameters     Optional additional GET data.
702
         *    @return boolean/string      Raw page on success.
703
         *    @access public
704
         */
705
        function post($url, $parameters = false) {
706
            return $this->_failOnError($this->_browser->post($url, $parameters));
707
        }
708
 
709
        /**
710
         *    Does a HTTP HEAD fetch, fetching only the page
711
         *    headers. The current base URL is unchanged by this.
712
         *    @param string $url          URL to fetch.
713
         *    @param hash $parameters     Optional additional GET data.
714
         *    @return boolean             True on success.
715
         *    @access public
716
         */
717
        function head($url, $parameters = false) {
718
            return $this->_failOnError($this->_browser->head($url, $parameters));
719
        }
720
 
721
        /**
722
         *    Equivalent to hitting the retry button on the
723
         *    browser. Will attempt to repeat the page fetch.
724
         *    @return boolean     True if fetch succeeded.
725
         *    @access public
726
         */
727
        function retry() {
728
            return $this->_failOnError($this->_browser->retry());
729
        }
730
 
731
        /**
732
         *    Equivalent to hitting the back button on the
733
         *    browser.
734
         *    @return boolean     True if history entry and
735
         *                        fetch succeeded.
736
         *    @access public
737
         */
738
        function back() {
739
            return $this->_failOnError($this->_browser->back());
740
        }
741
 
742
        /**
743
         *    Equivalent to hitting the forward button on the
744
         *    browser.
745
         *    @return boolean     True if history entry and
746
         *                        fetch succeeded.
747
         *    @access public
748
         */
749
        function forward() {
750
            return $this->_failOnError($this->_browser->forward());
751
        }
752
 
753
        /**
754
         *    Retries a request after setting the authentication
755
         *    for the current realm.
756
         *    @param string $username    Username for realm.
757
         *    @param string $password    Password for realm.
758
         *    @return boolean/string     HTML on successful fetch. Note
759
         *                               that authentication may still have
760
         *                               failed.
761
         *    @access public
762
         */
763
        function authenticate($username, $password) {
764
            return $this->_failOnError(
765
                    $this->_browser->authenticate($username, $password));
766
        }
767
 
768
        /**
769
         *    Gets the cookie value for the current browser context.
770
         *    @param string $name          Name of cookie.
771
         *    @return string               Value of cookie or false if unset.
772
         *    @access public
773
         */
774
        function getCookie($name) {
775
            return $this->_browser->getCurrentCookieValue($name);
776
        }
777
 
778
        /**
779
         *    Sets a cookie in the current browser.
780
         *    @param string $name          Name of cookie.
781
         *    @param string $value         Cookie value.
782
         *    @param string $host          Host upon which the cookie is valid.
783
         *    @param string $path          Cookie path if not host wide.
784
         *    @param string $expiry        Expiry date.
785
         *    @access public
786
         */
787
        function setCookie($name, $value, $host = false, $path = "/", $expiry = false) {
788
            $this->_browser->setCookie($name, $value, $host, $path, $expiry);
789
        }
790
 
791
        /**
792
         *    Accessor for current frame focus. Will be
793
         *    false if no frame has focus.
794
         *    @return integer/string/boolean    Label if any, otherwise
795
         *                                      the position in the frameset
796
         *                                      or false if none.
797
         *    @access public
798
         */
799
        function getFrameFocus() {
800
            return $this->_browser->getFrameFocus();
801
        }
802
 
803
        /**
804
         *    Sets the focus by index. The integer index starts from 1.
805
         *    @param integer $choice    Chosen frame.
806
         *    @return boolean           True if frame exists.
807
         *    @access public
808
         */
809
        function setFrameFocusByIndex($choice) {
810
            return $this->_browser->setFrameFocusByIndex($choice);
811
        }
812
 
813
        /**
814
         *    Sets the focus by name.
815
         *    @param string $name    Chosen frame.
816
         *    @return boolean        True if frame exists.
817
         *    @access public
818
         */
819
        function setFrameFocus($name) {
820
            return $this->_browser->setFrameFocus($name);
821
        }
822
 
823
        /**
824
         *    Clears the frame focus. All frames will be searched
825
         *    for content.
826
         *    @access public
827
         */
828
        function clearFrameFocus() {
829
            return $this->_browser->clearFrameFocus();
830
        }
831
 
832
        /**
833
         *    Clicks a visible text item. Will first try buttons,
834
         *    then links and then images.
835
         *    @param string $label        Visible text or alt text.
836
         *    @return string/boolean      Raw page or false.
837
         *    @access public
838
         */
839
        function click($label) {
840
            return $this->_failOnError($this->_browser->click($label));
841
        }
842
 
843
        /**
844
         *    Clicks the submit button by label. The owning
845
         *    form will be submitted by this.
846
         *    @param string $label    Button label. An unlabeled
847
         *                            button can be triggered by 'Submit'.
848
         *    @param hash $additional Additional form values.
849
         *    @return boolean/string  Page on success, else false.
850
         *    @access public
851
         */
852
        function clickSubmit($label = 'Submit', $additional = false) {
853
            return $this->_failOnError(
854
                    $this->_browser->clickSubmit($label, $additional));
855
        }
856
 
857
        /**
858
         *    Clicks the submit button by name attribute. The owning
859
         *    form will be submitted by this.
860
         *    @param string $name     Name attribute of button.
861
         *    @param hash $additional Additional form values.
862
         *    @return boolean/string  Page on success.
863
         *    @access public
864
         */
865
        function clickSubmitByName($name, $additional = false) {
866
            return $this->_failOnError(
867
                    $this->_browser->clickSubmitByName($name, $additional));
868
        }
869
 
870
        /**
871
         *    Clicks the submit button by ID attribute. The owning
872
         *    form will be submitted by this.
873
         *    @param string $id       ID attribute of button.
874
         *    @param hash $additional Additional form values.
875
         *    @return boolean/string  Page on success.
876
         *    @access public
877
         */
878
        function clickSubmitById($id, $additional = false) {
879
            return $this->_failOnError(
880
                    $this->_browser->clickSubmitById($id, $additional));
881
        }
882
 
883
        /**
884
         *    Clicks the submit image by some kind of label. Usually
885
         *    the alt tag or the nearest equivalent. The owning
886
         *    form will be submitted by this. Clicking outside of
887
         *    the boundary of the coordinates will result in
888
         *    a failure.
889
         *    @param string $label    Alt attribute of button.
890
         *    @param integer $x       X-coordinate of imaginary click.
891
         *    @param integer $y       Y-coordinate of imaginary click.
892
         *    @param hash $additional Additional form values.
893
         *    @return boolean/string  Page on success.
894
         *    @access public
895
         */
896
        function clickImage($label, $x = 1, $y = 1, $additional = false) {
897
            return $this->_failOnError(
898
                    $this->_browser->clickImage($label, $x, $y, $additional));
899
        }
900
 
901
        /**
902
         *    Clicks the submit image by the name. Usually
903
         *    the alt tag or the nearest equivalent. The owning
904
         *    form will be submitted by this. Clicking outside of
905
         *    the boundary of the coordinates will result in
906
         *    a failure.
907
         *    @param string $name     Name attribute of button.
908
         *    @param integer $x       X-coordinate of imaginary click.
909
         *    @param integer $y       Y-coordinate of imaginary click.
910
         *    @param hash $additional Additional form values.
911
         *    @return boolean/string  Page on success.
912
         *    @access public
913
         */
914
        function clickImageByName($name, $x = 1, $y = 1, $additional = false) {
915
            return $this->_failOnError(
916
                    $this->_browser->clickImageByName($name, $x, $y, $additional));
917
        }
918
 
919
        /**
920
         *    Clicks the submit image by ID attribute. The owning
921
         *    form will be submitted by this. Clicking outside of
922
         *    the boundary of the coordinates will result in
923
         *    a failure.
924
         *    @param integer/string $id   ID attribute of button.
925
         *    @param integer $x           X-coordinate of imaginary click.
926
         *    @param integer $y           Y-coordinate of imaginary click.
927
         *    @param hash $additional     Additional form values.
928
         *    @return boolean/string      Page on success.
929
         *    @access public
930
         */
931
        function clickImageById($id, $x = 1, $y = 1, $additional = false) {
932
            return $this->_failOnError(
933
                    $this->_browser->clickImageById($id, $x, $y, $additional));
934
        }
935
 
936
        /**
937
         *    Submits a form by the ID.
938
         *    @param string $id       Form ID. No button information
939
         *                            is submitted this way.
940
         *    @return boolean/string  Page on success.
941
         *    @access public
942
         */
943
        function submitFormById($id) {
944
            return $this->_failOnError($this->_browser->submitFormById($id));
945
        }
946
 
947
        /**
948
         *    Follows a link by name. Will click the first link
949
         *    found with this link text by default, or a later
950
         *    one if an index is given. Match is case insensitive
951
         *    with normalised space.
952
         *    @param string $label     Text between the anchor tags.
953
         *    @param integer $index    Link position counting from zero.
954
         *    @return boolean/string   Page on success.
955
         *    @access public
956
         */
957
        function clickLink($label, $index = 0) {
958
            return $this->_failOnError($this->_browser->clickLink($label, $index));
959
        }
960
 
961
        /**
962
         *    Follows a link by id attribute.
963
         *    @param string $id        ID attribute value.
964
         *    @return boolean/string   Page on success.
965
         *    @access public
966
         */
967
        function clickLinkById($id) {
968
            return $this->_failOnError($this->_browser->clickLinkById($id));
969
        }
970
 
971
        /**
972
         *    Will trigger a pass if the two parameters have
973
         *    the same value only. Otherwise a fail. This
974
         *    is for testing hand extracted text, etc.
975
         *    @param mixed $first          Value to compare.
976
         *    @param mixed $second         Value to compare.
977
         *    @param string $message       Message to display.
978
         *    @return boolean              True on pass
979
         *    @access public
980
         */
981
        function assertEqual($first, $second, $message = "%s") {
982
            return $this->assert(
983
                    new EqualExpectation($first),
984
                    $second,
985
                    $message);
986
        }
987
 
988
        /**
989
         *    Will trigger a pass if the two parameters have
990
         *    a different value. Otherwise a fail. This
991
         *    is for testing hand extracted text, etc.
992
         *    @param mixed $first           Value to compare.
993
         *    @param mixed $second          Value to compare.
994
         *    @param string $message        Message to display.
995
         *    @return boolean               True on pass
996
         *    @access public
997
         */
998
        function assertNotEqual($first, $second, $message = "%s") {
999
            return $this->assert(
1000
                    new NotEqualExpectation($first),
1001
                    $second,
1002
                    $message);
1003
        }
1004
 
1005
        /**
1006
         *    Tests for the presence of a link label. Match is
1007
         *    case insensitive with normalised space.
1008
         *    @param string $label     Text between the anchor tags.
1009
         *    @param string $message   Message to display. Default
1010
         *                             can be embedded with %s.
1011
         *    @return boolean          True if link present.
1012
         *    @access public
1013
         */
1014
        function assertLink($label, $message = "%s") {
1015
            return $this->assertTrue(
1016
                    $this->_browser->isLink($label),
1017
                    sprintf($message, "Link [$label] should exist"));
1018
        }
1019
 
1020
        /**
1021
         *    Tests for the non-presence of a link label. Match is
1022
         *    case insensitive with normalised space.
1023
         *    @param string/integer $label    Text between the anchor tags
1024
         *                                    or ID attribute.
1025
         *    @param string $message          Message to display. Default
1026
         *                                    can be embedded with %s.
1027
         *    @return boolean                 True if link missing.
1028
         *    @access public
1029
         */
1030
        function assertNoLink($label, $message = "%s") {
1031
            return $this->assertFalse(
1032
                    $this->_browser->isLink($label),
1033
                    sprintf($message, "Link [$label] should not exist"));
1034
        }
1035
 
1036
        /**
1037
         *    Tests for the presence of a link id attribute.
1038
         *    @param string $id        Id attribute value.
1039
         *    @param string $message   Message to display. Default
1040
         *                             can be embedded with %s.
1041
         *    @return boolean          True if link present.
1042
         *    @access public
1043
         */
1044
        function assertLinkById($id, $message = "%s") {
1045
            return $this->assertTrue(
1046
                    $this->_browser->isLinkById($id),
1047
                    sprintf($message, "Link ID [$id] should exist"));
1048
        }
1049
 
1050
        /**
1051
         *    Tests for the non-presence of a link label. Match is
1052
         *    case insensitive with normalised space.
1053
         *    @param string $id        Id attribute value.
1054
         *    @param string $message   Message to display. Default
1055
         *                             can be embedded with %s.
1056
         *    @return boolean          True if link missing.
1057
         *    @access public
1058
         */
1059
        function assertNoLinkById($id, $message = "%s") {
1060
            return $this->assertFalse(
1061
                    $this->_browser->isLinkById($id),
1062
                    sprintf($message, "Link ID [$id] should not exist"));
1063
        }
1064
 
1065
        /**
1066
         *    Sets all form fields with that label, or name if there
1067
         *    is no label attached.
1068
         *    @param string $name    Name of field in forms.
1069
         *    @param string $value   New value of field.
1070
         *    @return boolean        True if field exists, otherwise false.
1071
         *    @access public
1072
         */
1073
        function setField($label, $value) {
1074
            return $this->_browser->setField($label, $value);
1075
        }
1076
 
1077
        /**
1078
         *    Sets all form fields with that name.
1079
         *    @param string $name    Name of field in forms.
1080
         *    @param string $value   New value of field.
1081
         *    @return boolean        True if field exists, otherwise false.
1082
         *    @access public
1083
         */
1084
        function setFieldByName($name, $value) {
1085
            return $this->_browser->setFieldByName($name, $value);
1086
        }
1087
 
1088
        /**
1089
         *    Sets all form fields with that name.
1090
         *    @param string/integer $id   Id of field in forms.
1091
         *    @param string $value        New value of field.
1092
         *    @return boolean             True if field exists, otherwise false.
1093
         *    @access public
1094
         */
1095
        function setFieldById($id, $value) {
1096
            return $this->_browser->setFieldById($id, $value);
1097
        }
1098
 
1099
        /**
1100
         *    Confirms that the form element is currently set
1101
         *    to the expected value. A missing form will always
1102
         *    fail. If no value is given then only the existence
1103
         *    of the field is checked.
1104
         *    @param string $name       Name of field in forms.
1105
         *    @param mixed $expected    Expected string/array value or
1106
         *                              false for unset fields.
1107
         *    @param string $message    Message to display. Default
1108
         *                              can be embedded with %s.
1109
         *    @return boolean           True if pass.
1110
         *    @access public
1111
         */
1112
        function assertField($label, $expected = true, $message = '%s') {
1113
            $value = $this->_browser->getField($label);
1114
            return $this->_assertFieldValue($label, $value, $expected, $message);
1115
        }
1116
 
1117
        /**
1118
         *    Confirms that the form element is currently set
1119
         *    to the expected value. A missing form element will always
1120
         *    fail. If no value is given then only the existence
1121
         *    of the field is checked.
1122
         *    @param string $name       Name of field in forms.
1123
         *    @param mixed $expected    Expected string/array value or
1124
         *                              false for unset fields.
1125
         *    @param string $message    Message to display. Default
1126
         *                              can be embedded with %s.
1127
         *    @return boolean           True if pass.
1128
         *    @access public
1129
         */
1130
        function assertFieldByName($name, $expected = true, $message = '%s') {
1131
            $value = $this->_browser->getFieldByName($name);
1132
            return $this->_assertFieldValue($name, $value, $expected, $message);
1133
        }
1134
 
1135
        /**
1136
         *    Confirms that the form element is currently set
1137
         *    to the expected value. A missing form will always
1138
         *    fail. If no ID is given then only the existence
1139
         *    of the field is checked.
1140
         *    @param string/integer $id  Name of field in forms.
1141
         *    @param mixed $expected     Expected string/array value or
1142
         *                               false for unset fields.
1143
         *    @param string $message     Message to display. Default
1144
         *                               can be embedded with %s.
1145
         *    @return boolean            True if pass.
1146
         *    @access public
1147
         */
1148
        function assertFieldById($id, $expected = true, $message = '%s') {
1149
            $value = $this->_browser->getFieldById($id);
1150
            return $this->_assertFieldValue($id, $value, $expected, $message);
1151
        }
1152
 
1153
        /**
1154
         *    Tests the field value against the expectation.
1155
         *    @param string $identifier      Name, ID or label.
1156
         *    @param mixed $value            Current field value.
1157
         *    @param mixed $expected         Expected value to match.
1158
         *    @param string $message         Failure message.
1159
         *    @return boolean                True if pass
1160
         *    @access protected
1161
         */
1162
        function _assertFieldValue($identifier, $value, $expected, $message) {
1163
            if ($expected === true) {
1164
                return $this->assertTrue(
1165
                        isset($value),
1166
                        sprintf($message, "Field [$identifier] should exist"));
1167
            }
1168
            if (! SimpleExpectation::isExpectation($expected)) {
1169
                $identifier = str_replace('%', '%%', $identifier);
1170
                $expected = new FieldExpectation(
1171
                        $expected,
1172
                        "Field [$identifier] should match with [%s]");
1173
            }
1174
            return $this->assert($expected, $value, $message);
1175
        }
1176
 
1177
        /**
1178
         *    Checks the response code against a list
1179
         *    of possible values.
1180
         *    @param array $responses    Possible responses for a pass.
1181
         *    @param string $message     Message to display. Default
1182
         *                               can be embedded with %s.
1183
         *    @return boolean            True if pass.
1184
         *    @access public
1185
         */
1186
        function assertResponse($responses, $message = '%s') {
1187
            $responses = (is_array($responses) ? $responses : array($responses));
1188
            $code = $this->_browser->getResponseCode();
1189
            $message = sprintf($message, "Expecting response in [" .
1190
                    implode(", ", $responses) . "] got [$code]");
1191
            return $this->assertTrue(in_array($code, $responses), $message);
1192
        }
1193
 
1194
        /**
1195
         *    Checks the mime type against a list
1196
         *    of possible values.
1197
         *    @param array $types      Possible mime types for a pass.
1198
         *    @param string $message   Message to display.
1199
         *    @return boolean          True if pass.
1200
         *    @access public
1201
         */
1202
        function assertMime($types, $message = '%s') {
1203
            $types = (is_array($types) ? $types : array($types));
1204
            $type = $this->_browser->getMimeType();
1205
            $message = sprintf($message, "Expecting mime type in [" .
1206
                    implode(", ", $types) . "] got [$type]");
1207
            return $this->assertTrue(in_array($type, $types), $message);
1208
        }
1209
 
1210
        /**
1211
         *    Attempt to match the authentication type within
1212
         *    the security realm we are currently matching.
1213
         *    @param string $authentication   Usually basic.
1214
         *    @param string $message          Message to display.
1215
         *    @return boolean                 True if pass.
1216
         *    @access public
1217
         */
1218
        function assertAuthentication($authentication = false, $message = '%s') {
1219
            if (! $authentication) {
1220
                $message = sprintf($message, "Expected any authentication type, got [" .
1221
                        $this->_browser->getAuthentication() . "]");
1222
                return $this->assertTrue(
1223
                        $this->_browser->getAuthentication(),
1224
                        $message);
1225
            } else {
1226
                $message = sprintf($message, "Expected authentication [$authentication] got [" .
1227
                        $this->_browser->getAuthentication() . "]");
1228
                return $this->assertTrue(
1229
                        strtolower($this->_browser->getAuthentication()) == strtolower($authentication),
1230
                        $message);
1231
            }
1232
        }
1233
 
1234
        /**
1235
         *    Checks that no authentication is necessary to view
1236
         *    the desired page.
1237
         *    @param string $message     Message to display.
1238
         *    @return boolean            True if pass.
1239
         *    @access public
1240
         */
1241
        function assertNoAuthentication($message = '%s') {
1242
            $message = sprintf($message, "Expected no authentication type, got [" .
1243
                    $this->_browser->getAuthentication() . "]");
1244
            return $this->assertFalse($this->_browser->getAuthentication(), $message);
1245
        }
1246
 
1247
        /**
1248
         *    Attempts to match the current security realm.
1249
         *    @param string $realm     Name of security realm.
1250
         *    @param string $message   Message to display.
1251
         *    @return boolean          True if pass.
1252
         *    @access public
1253
         */
1254
        function assertRealm($realm, $message = '%s') {
1255
            if (! SimpleExpectation::isExpectation($realm)) {
1256
                $realm = new EqualExpectation($realm);
1257
            }
1258
            return $this->assert(
1259
                    $realm,
1260
                    $this->_browser->getRealm(),
1261
                    "Expected realm -> $message");
1262
        }
1263
 
1264
        /**
1265
         *    Checks each header line for the required value. If no
1266
         *    value is given then only an existence check is made.
1267
         *    @param string $header    Case insensitive header name.
1268
         *    @param mixed $value      Case sensitive trimmed string to
1269
         *                             match against. An expectation object
1270
         *                             can be used for pattern matching.
1271
         *    @return boolean          True if pass.
1272
         *    @access public
1273
         */
1274
        function assertHeader($header, $value = false, $message = '%s') {
1275
            return $this->assert(
1276
                    new HttpHeaderExpectation($header, $value),
1277
                    $this->_browser->getHeaders(),
1278
                    $message);
1279
        }
1280
 
1281
        /**
1282
         *    @deprecated
1283
         */
1284
        function assertHeaderPattern($header, $pattern, $message = '%s') {
1285
            return $this->assert(
1286
                    new HttpHeaderExpectation($header, new PatternExpectation($pattern)),
1287
                    $this->_browser->getHeaders(),
1288
                    $message);
1289
        }
1290
 
1291
        /**
1292
         *    Confirms that the header type has not been received.
1293
         *    Only the landing page is checked. If you want to check
1294
         *    redirect pages, then you should limit redirects so
1295
         *    as to capture the page you want.
1296
         *    @param string $header    Case insensitive header name.
1297
         *    @return boolean          True if pass.
1298
         *    @access public
1299
         */
1300
        function assertNoHeader($header, $message = '%s') {
1301
            return $this->assert(
1302
                    new NoHttpHeaderExpectation($header),
1303
                    $this->_browser->getHeaders(),
1304
                    $message);
1305
        }
1306
 
1307
        /**
1308
         *    @deprecated
1309
         */
1310
        function assertNoUnwantedHeader($header, $message = '%s') {
1311
            return $this->assertNoHeader($header, $message);
1312
        }
1313
 
1314
        /**
1315
         *    Tests the text between the title tags.
1316
         *    @param string $title      Expected title.
1317
         *    @param string $message    Message to display.
1318
         *    @return boolean           True if pass.
1319
         *    @access public
1320
         */
1321
        function assertTitle($title = false, $message = '%s') {
1322
            if (! SimpleExpectation::isExpectation($title)) {
1323
                $title = new EqualExpectation($title);
1324
            }
1325
            return $this->assert($title, $this->_browser->getTitle(), $message);
1326
        }
1327
 
1328
        /**
1329
         *    Will trigger a pass if the text is found in the plain
1330
         *    text form of the page.
1331
         *    @param string $text       Text to look for.
1332
         *    @param string $message    Message to display.
1333
         *    @return boolean           True if pass.
1334
         *    @access public
1335
         */
1336
        function assertText($text, $message = '%s') {
1337
            return $this->assert(
1338
                    new TextExpectation($text),
1339
                    $this->_browser->getContentAsText(),
1340
                    $message);
1341
        }
1342
 
1343
        /**
1344
         *	  @deprecated
1345
         */
1346
        function assertWantedText($text, $message = '%s') {
1347
        	return $this->assertText($text, $message);
1348
        }
1349
 
1350
        /**
1351
         *    Will trigger a pass if the text is not found in the plain
1352
         *    text form of the page.
1353
         *    @param string $text       Text to look for.
1354
         *    @param string $message    Message to display.
1355
         *    @return boolean           True if pass.
1356
         *    @access public
1357
         */
1358
        function assertNoText($text, $message = '%s') {
1359
            return $this->assert(
1360
                    new NoTextExpectation($text),
1361
                    $this->_browser->getContentAsText(),
1362
                    $message);
1363
        }
1364
 
1365
        /**
1366
         *	  @deprecated
1367
         */
1368
        function assertNoUnwantedText($text, $message = '%s') {
1369
        	return $this->assertNoText($text, $message);
1370
        }
1371
 
1372
        /**
1373
         *    Will trigger a pass if the Perl regex pattern
1374
         *    is found in the raw content.
1375
         *    @param string $pattern    Perl regex to look for including
1376
         *                              the regex delimiters.
1377
         *    @param string $message    Message to display.
1378
         *    @return boolean           True if pass.
1379
         *    @access public
1380
         */
1381
        function assertPattern($pattern, $message = '%s') {
1382
            return $this->assert(
1383
                    new PatternExpectation($pattern),
1384
                    $this->_browser->getContent(),
1385
                    $message);
1386
        }
1387
 
1388
        /**
1389
         *	  @deprecated
1390
         */
1391
        function assertWantedPattern($pattern, $message = '%s') {
1392
        	return $this->assertPattern($pattern, $message);
1393
        }
1394
 
1395
        /**
1396
         *    Will trigger a pass if the perl regex pattern
1397
         *    is not present in raw content.
1398
         *    @param string $pattern    Perl regex to look for including
1399
         *                              the regex delimiters.
1400
         *    @param string $message    Message to display.
1401
         *    @return boolean           True if pass.
1402
         *    @access public
1403
         */
1404
        function assertNoPattern($pattern, $message = '%s') {
1405
            return $this->assert(
1406
                    new NoPatternExpectation($pattern),
1407
                    $this->_browser->getContent(),
1408
                    $message);
1409
        }
1410
 
1411
        /**
1412
         *	  @deprecated
1413
         */
1414
        function assertNoUnwantedPattern($pattern, $message = '%s') {
1415
        	return $this->assertNoPattern($pattern, $message);
1416
        }
1417
 
1418
        /**
1419
         *    Checks that a cookie is set for the current page
1420
         *    and optionally checks the value.
1421
         *    @param string $name        Name of cookie to test.
1422
         *    @param string $expected    Expected value as a string or
1423
         *                               false if any value will do.
1424
         *    @param string $message     Message to display.
1425
         *    @return boolean            True if pass.
1426
         *    @access public
1427
         */
1428
        function assertCookie($name, $expected = false, $message = '%s') {
1429
            $value = $this->getCookie($name);
1430
            if (! $expected) {
1431
                return $this->assertTrue(
1432
                        $value,
1433
                        sprintf($message, "Expecting cookie [$name]"));
1434
            }
1435
            if (! SimpleExpectation::isExpectation($expected)) {
1436
                $expected = new EqualExpectation($expected);
1437
            }
1438
            return $this->assert($expected, $value, "Expecting cookie [$name] -> $message");
1439
        }
1440
 
1441
        /**
1442
         *    Checks that no cookie is present or that it has
1443
         *    been successfully cleared.
1444
         *    @param string $name        Name of cookie to test.
1445
         *    @param string $message     Message to display.
1446
         *    @return boolean            True if pass.
1447
         *    @access public
1448
         */
1449
        function assertNoCookie($name, $message = '%s') {
1450
            return $this->assertTrue(
1451
                    $this->getCookie($name) === false,
1452
                    sprintf($message, "Not expecting cookie [$name]"));
1453
        }
1454
    }
1455
?>