Source for file web_tester.php
Documentation is available at
web_tester.php
<?php
/**
* Base include file for SimpleTest.
*
@package
SimpleTest
*
@subpackage
WebTester
*
@version
$Id: web_tester.php 1723 2008-04-08 00:34:10Z lastcraft $
*/
/**#@+
* include other SimpleTest class files
*/
require_once
(
dirname
(
__FILE__
)
.
'/test_case.php'
)
;
require_once
(
dirname
(
__FILE__
)
.
'/browser.php'
)
;
require_once
(
dirname
(
__FILE__
)
.
'/page.php'
)
;
require_once
(
dirname
(
__FILE__
)
.
'/expectation.php'
)
;
/**#@-*/
* Test for an HTML widget value match.
*
@package
SimpleTest
*
@subpackage
WebTester
*/
class
FieldExpectation
extends
SimpleExpectation
{
var
$_value
;
/**
* Sets the field value to compare against.
*
@param
mixed
$value
Test value to match. Can be an
* expectation for say pattern matching.
*
@param
string
$message
Optiona message override. Can use %s as
* a placeholder for the original message.
*
@access
public
*/
function
FieldExpectation
(
$value
,
$message
=
'%s'
)
{
$this
->
SimpleExpectation
(
$message
)
;
if
(
is_array
(
$value
))
{
sort
(
$value
)
;
}
$this
->
_value
=
$value
;
}
/**
* Tests the expectation. True if it matches
* a string value or an array value in any order.
*
@param
mixed
$compare
Comparison value. False for
* an unset field.
*
@return
boolean
True if correct.
*
@access
public
*/
function
test
(
$compare
)
{
if
(
$this
->
_value
===
false
)
{
return
(
$compare
===
false
)
;
}
if
(
$this
->
_isSingle
(
$this
->
_value
))
{
return
$this
->
_testSingle
(
$compare
)
;
}
if
(
is_array
(
$this
->
_value
))
{
return
$this
->
_testMultiple
(
$compare
)
;
}
return
false
;
}
/**
* Tests for valid field comparisons with a single option.
*
@param
mixed
$value
Value to type check.
*
@return
boolean
True if integer, string or float.
*
@access
private
*/
function
_isSingle
(
$value
)
{
return
is_string
(
$value
)
||
is_integer
(
$value
)
||
is_float
(
$value
)
;
}
/**
* String comparison for simple field with a single option.
*
@param
mixed
$compare
String to test against.
*
@returns
boolean True if matching.
*
@access
private
*/
function
_testSingle
(
$compare
)
{
if
(
is_array
(
$compare
)
&&
count
(
$compare
)
==
1
)
{
$compare
=
$compare
[
0
]
;
}
if
(
!
$this
->
_isSingle
(
$compare
))
{
return
false
;
}
return
(
$this
->
_value
==
$compare
)
;
}
/**
* List comparison for multivalue field.
*
@param
mixed
$compare
List in any order to test against.
*
@returns
boolean True if matching.
*
@access
private
*/
function
_testMultiple
(
$compare
)
{
if
(
is_string
(
$compare
))
{
$compare
=
array
(
$compare
)
;
}
if
(
!
is_array
(
$compare
))
{
return
false
;
}
sort
(
$compare
)
;
return
(
$this
->
_value
===
$compare
)
;
}
/**
* Returns a human readable test message.
*
@param
mixed
$compare
Comparison value.
*
@return
string
Description of success
* or failure.
*
@access
public
*/
function
testMessage
(
$compare
)
{
$dumper
=
&
$this
->
_getDumper
(
)
;
if
(
is_array
(
$compare
))
{
sort
(
$compare
)
;
}
if
(
$this
->
test
(
$compare
))
{
return
"Field expectation ["
.
$dumper
->
describeValue
(
$this
->
_value
)
.
"]"
;
}
else
{
return
"Field expectation ["
.
$dumper
->
describeValue
(
$this
->
_value
)
.
"] fails with ["
.
$dumper
->
describeValue
(
$compare
)
.
"] "
.
$dumper
->
describeDifference
(
$this
->
_value
,
$compare
)
;
}
}
}
/**
* Test for a specific HTTP header within a header block.
*
@package
SimpleTest
*
@subpackage
WebTester
*/
class
HttpHeaderExpectation
extends
SimpleExpectation
{
var
$_expected_header
;
var
$_expected_value
;
/**
* Sets the field and value to compare against.
*
@param
string
$header
Case insenstive trimmed header name.
*
@param
mixed
$value
Optional value to compare. If not
* given then any value will match. If
* an expectation object then that will
* be used instead.
*
@param
string
$message
Optiona message override. Can use %s as
* a placeholder for the original message.
*/
function
HttpHeaderExpectation
(
$header
,
$value
=
false
,
$message
=
'%s'
)
{
$this
->
SimpleExpectation
(
$message
)
;
$this
->
_expected_header
=
$this
->
_normaliseHeader
(
$header
)
;
$this
->
_expected_value
=
$value
;
}
/**
* Accessor for aggregated object.
*
@return
mixed
Expectation set in constructor.
*
@access
protected
*/
function
_getExpectation
(
)
{
return
$this
->
_expected_value
;
}
/**
* Removes whitespace at ends and case variations.
*
@param
string
$header
Name of header.
*
@param
string
Trimmed and lowecased header
* name.
*
@access
private
*/
function
_normaliseHeader
(
$header
)
{
return
strtolower
(
trim
(
$header
))
;
}
/**
* Tests the expectation. True if it matches
* a string value or an array value in any order.
*
@param
mixed
$compare
Raw header block to search.
*
@return
boolean
True if header present.
*
@access
public
*/
function
test
(
$compare
)
{
return
is_string
(
$this
->
_findHeader
(
$compare
))
;
}
/**
* Searches the incoming result. Will extract the matching
* line as text.
*
@param
mixed
$compare
Raw header block to search.
*
@return
string
Matching header line.
*
@access
protected
*/
function
_findHeader
(
$compare
)
{
$lines
=
split
(
"\r\n"
,
$compare
)
;
foreach
(
$lines
as
$line
)
{
if
(
$this
->
_testHeaderLine
(
$line
))
{
return
$line
;
}
}
return
false
;
}
/**
* Compares a single header line against the expectation.
*
@param
string
$line
A single line to compare.
*
@return
boolean
True if matched.
*
@access
private
*/
function
_testHeaderLine
(
$line
)
{
if
(
count
(
$parsed
=
split
(
':'
,
$line
,
2
))
<
2
)
{
return
false
;
}
list
(
$header
,
$value
)
=
$parsed
;
if
(
$this
->
_normaliseHeader
(
$header
)
!=
$this
->
_expected_header
)
{
return
false
;
}
return
$this
->
_testHeaderValue
(
$value
,
$this
->
_expected_value
)
;
}
/**
* Tests the value part of the header.
*
@param
string
$value
Value to test.
*
@param
mixed
$expected
Value to test against.
*
@return
boolean
True if matched.
*
@access
protected
*/
function
_testHeaderValue
(
$value
,
$expected
)
{
if
(
$expected
===
false
)
{
return
true
;
}
if
(
SimpleExpectation
::
isExpectation
(
$expected
))
{
return
$expected
->
test
(
trim
(
$value
))
;
}
return
(
trim
(
$value
)
==
trim
(
$expected
))
;
}
/**
* Returns a human readable test message.
*
@param
mixed
$compare
Raw header block to search.
*
@return
string
Description of success
* or failure.
*
@access
public
*/
function
testMessage
(
$compare
)
{
if
(
SimpleExpectation
::
isExpectation
(
$this
->
_expected_value
))
{
$message
=
$this
->
_expected_value
->
overlayMessage
(
$compare
,
$this
->
_getDumper
(
))
;
}
else
{
$message
=
$this
->
_expected_header
.
(
$this
->
_expected_value
?
': '
.
$this
->
_expected_value
:
''
)
;
}
if
(
is_string
(
$line
=
$this
->
_findHeader
(
$compare
)))
{
return
"
Searching for header [
$message
] found [
$line
]
"
;
}
else
{
return
"
Failed to find header [
$message
]
"
;
}
}
}
/**
* Test for a specific HTTP header within a header block that
* should not be found.
*
@package
SimpleTest
*
@subpackage
WebTester
*/
class
NoHttpHeaderExpectation
extends
HttpHeaderExpectation
{
var
$_expected_header
;
var
$_expected_value
;
/**
* Sets the field and value to compare against.
*
@param
string
$unwanted
Case insenstive trimmed header name.
*
@param
string
$message
Optiona message override. Can use %s as
* a placeholder for the original message.
*/
function
NoHttpHeaderExpectation
(
$unwanted
,
$message
=
'%s'
)
{
$this
->
HttpHeaderExpectation
(
$unwanted
,
false
,
$message
)
;
}
/**
* Tests that the unwanted header is not found.
*
@param
mixed
$compare
Raw header block to search.
*
@return
boolean
True if header present.
*
@access
public
*/
function
test
(
$compare
)
{
return
(
$this
->
_findHeader
(
$compare
)
===
false
)
;
}
/**
* Returns a human readable test message.
*
@param
mixed
$compare
Raw header block to search.
*
@return
string
Description of success
* or failure.
*
@access
public
*/
function
testMessage
(
$compare
)
{
$expectation
=
$this
->
_getExpectation
(
)
;
if
(
is_string
(
$line
=
$this
->
_findHeader
(
$compare
)))
{
return
"
Found unwanted header [
$expectation
] with [
$line
]
"
;
}
else
{
return
"
Did not find unwanted header [
$expectation
]
"
;
}
}
}
/**
* Test for a text substring.
*
@package
SimpleTest
*
@subpackage
UnitTester
*/
class
TextExpectation
extends
SimpleExpectation
{
var
$_substring
;
/**
* Sets the value to compare against.
*
@param
string
$substring
Text to search for.
*
@param
string
$message
Customised message on failure.
*
@access
public
*/
function
TextExpectation
(
$substring
,
$message
=
'%s'
)
{
$this
->
SimpleExpectation
(
$message
)
;
$this
->
_substring
=
$substring
;
}
/**
* Accessor for the substring.
*
@return
string
Text to match.
*
@access
protected
*/
function
_getSubstring
(
)
{
return
$this
->
_substring
;
}
/**
* Tests the expectation. True if the text contains the
* substring.
*
@param
string
$compare
Comparison value.
*
@return
boolean
True if correct.
*
@access
public
*/
function
test
(
$compare
)
{
return
(
strpos
(
$compare
,
$this
->
_substring
)
!==
false
)
;
}
/**
* Returns a human readable test message.
*
@param
mixed
$compare
Comparison value.
*
@return
string
Description of success
* or failure.
*
@access
public
*/
function
testMessage
(
$compare
)
{
if
(
$this
->
test
(
$compare
))
{
return
$this
->
_describeTextMatch
(
$this
->
_getSubstring
(
)
,
$compare
)
;
}
else
{
$dumper
=
&
$this
->
_getDumper
(
)
;
return
"Text ["
.
$this
->
_getSubstring
(
)
.
"] not detected in ["
.
$dumper
->
describeValue
(
$compare
)
.
"]"
;
}
}
/**
* Describes a pattern match including the string
* found and it's position.
*
@param
string
$substring
Text to search for.
*
@param
string
$subject
Subject to search.
*
@access
protected
*/
function
_describeTextMatch
(
$substring
,
$subject
)
{
$position
=
strpos
(
$subject
,
$substring
)
;
$dumper
=
&
$this
->
_getDumper
(
)
;
return
"
Text [
$substring
] detected at character [
$position
] in [
"
.
$dumper
->
describeValue
(
$subject
)
.
"] in region ["
.
$dumper
->
clipString
(
$subject
,
100
,
$position
)
.
"]"
;
}
}
/**
* Fail if a substring is detected within the
* comparison text.
*
@package
SimpleTest
*
@subpackage
UnitTester
*/
class
NoTextExpectation
extends
TextExpectation
{
/**
* Sets the reject pattern
*
@param
string
$substring
Text to search for.
*
@param
string
$message
Customised message on failure.
*
@access
public
*/
function
NoTextExpectation
(
$substring
,
$message
=
'%s'
)
{
$this
->
TextExpectation
(
$substring
,
$message
)
;
}
/**
* Tests the expectation. False if the substring appears
* in the text.
*
@param
string
$compare
Comparison value.
*
@return
boolean
True if correct.
*
@access
public
*/
function
test
(
$compare
)
{
return
!
parent
::
test
(
$compare
)
;
}
/**
* Returns a human readable test message.
*
@param
string
$compare
Comparison value.
*
@return
string
Description of success
* or failure.
*
@access
public
*/
function
testMessage
(
$compare
)
{
if
(
$this
->
test
(
$compare
))
{
$dumper
=
&
$this
->
_getDumper
(
)
;
return
"Text ["
.
$this
->
_getSubstring
(
)
.
"] not detected in ["
.
$dumper
->
describeValue
(
$compare
)
.
"]"
;
}
else
{
return
$this
->
_describeTextMatch
(
$this
->
_getSubstring
(
)
,
$compare
)
;
}
}
}
/**
* Test case for testing of web pages. Allows
* fetching of pages, parsing of HTML and
* submitting forms.
*
@package
SimpleTest
*
@subpackage
WebTester
*/
class
WebTestCase
extends
SimpleTestCase
{
var
$_browser
;
var
$_ignore_errors
=
false
;
/**
* Creates an empty test case. Should be subclassed
* with test methods for a functional test case.
*
@param
string
$label
Name of test case. Will use
* the class name if none specified.
*
@access
public
*/
function
WebTestCase
(
$label
=
false
)
{
$this
->
SimpleTestCase
(
$label
)
;
}
/**
* Announces the start of the test.
*
@param
string
$method
Test method just started.
*
@access
public
*/
function
before
(
$method
)
{
parent
::
before
(
$method
)
;
$this
->
setBrowser
(
$this
->
createBrowser
(
))
;
}
/**
* Announces the end of the test. Includes private clean up.
*
@param
string
$method
Test method just finished.
*
@access
public
*/
function
after
(
$method
)
{
$this
->
unsetBrowser
(
)
;
parent
::
after
(
$method
)
;
}
/**
* Gets a current browser reference for setting
* special expectations or for detailed
* examination of page fetches.
*
@return
SimpleBrowser
Current test browser object.
*
@access
public
*/
function
&
getBrowser
(
)
{
return
$this
->
_browser
;
}
/**
* Gets a current browser reference for setting
* special expectations or for detailed
* examination of page fetches.
*
@param
SimpleBrowser
$browser
New test browser object.
*
@access
public
*/
function
setBrowser
(
&
$browser
)
{
return
$this
->
_browser
=
&
$browser
;
}
/**
* Clears the current browser reference to help the
* PHP garbage collector.
*
@access
public
*/
function
unsetBrowser
(
)
{
unset
(
$this
->
_browser
)
;
}
/**
* Creates a new default web browser object.
* Will be cleared at the end of the test method.
*
@return
TestBrowser
New browser.
*
@access
public
*/
function
&
createBrowser
(
)
{
$browser
=
&
new
SimpleBrowser
(
)
;
return
$browser
;
}
/**
* Gets the last response error.
*
@return
string
Last low level HTTP error.
*
@access
public
*/
function
getTransportError
(
)
{
return
$this
->
_browser
->
getTransportError
(
)
;
}
/**
* Accessor for the currently selected URL.
* &n