3 * Base include file for SimpleTest.
5 * @subpackage WebTester
6 * @version $Id: tag.php,v 1.95 2006/02/05 00:34:29 lastcraft Exp $
10 * include SimpleTest files
12 require_once(dirname(__FILE__
) . '/parser.php');
13 require_once(dirname(__FILE__
) . '/encoding.php');
19 * @subpackage WebTester
27 * Starts with a named tag with attributes only.
28 * @param string $name Tag name.
29 * @param hash $attributes Attribute names and
30 * string values. Note that
31 * the keys must have been
32 * converted to lower case.
34 function SimpleTag($name, $attributes) {
35 $this->_name
= strtolower(trim($name));
36 $this->_attributes
= $attributes;
41 * Check to see if the tag can have both start and
42 * end tags with content in between.
43 * @return boolean True if content allowed.
46 function expectEndTag() {
51 * The current tag should not swallow all content for
52 * itself as it's searchable page content. Private
53 * content tags are usually widgets that contain default
55 * @return boolean False as content is available
56 * to other tags by default.
59 function isPrivateContent() {
64 * Appends string content to the current content.
65 * @param string $content Additional text.
68 function addContent($content) {
69 $this->_content
.= (string)$content;
73 * Adds an enclosed tag to the content.
74 * @param SimpleTag $tag New tag.
77 function addTag(&$tag) {
81 * Accessor for tag name.
82 * @return string Name of tag.
85 function getTagName() {
90 * List of legal child elements.
91 * @return array List of element names.
94 function getChildElements() {
99 * Accessor for an attribute.
100 * @param string $label Attribute name.
101 * @return string Attribute value.
104 function getAttribute($label) {
105 $label = strtolower($label);
106 if (! isset($this->_attributes
[$label])) {
109 return (string)$this->_attributes
[$label];
114 * @param string $label Attribute name.
115 * @return string $value New attribute value.
118 function _setAttribute($label, $value) {
119 $this->_attributes
[strtolower($label)] = $value;
123 * Accessor for the whole content so far.
124 * @return string Content as big raw string.
127 function getContent() {
128 return $this->_content
;
132 * Accessor for content reduced to visible text. Acts
133 * like a text mode browser, normalising space and
134 * reducing images to their alt text.
135 * @return string Content as plain text.
139 return SimpleHtmlSaxParser
::normalise($this->_content
);
143 * Test to see if id attribute matches.
144 * @param string $id ID to test against.
145 * @return boolean True on match.
149 return ($this->getAttribute('id') == $id);
155 * @package SimpleTest
156 * @subpackage WebTester
158 class SimpleTitleTag
extends SimpleTag
{
161 * Starts with a named tag with attributes only.
162 * @param hash $attributes Attribute names and
165 function SimpleTitleTag($attributes) {
166 $this->SimpleTag('title', $attributes);
172 * @package SimpleTest
173 * @subpackage WebTester
175 class SimpleAnchorTag
extends SimpleTag
{
178 * Starts with a named tag with attributes only.
179 * @param hash $attributes Attribute names and
182 function SimpleAnchorTag($attributes) {
183 $this->SimpleTag('a', $attributes);
187 * Accessor for URL as string.
188 * @return string Coerced as string.
192 $url = $this->getAttribute('href');
202 * @package SimpleTest
203 * @subpackage WebTester
205 class SimpleWidget
extends SimpleTag
{
211 * Starts with a named tag with attributes only.
212 * @param string $name Tag name.
213 * @param hash $attributes Attribute names and
216 function SimpleWidget($name, $attributes) {
217 $this->SimpleTag($name, $attributes);
218 $this->_value
= false;
219 $this->_label
= false;
220 $this->_is_set
= false;
224 * Accessor for name submitted as the key in
225 * GET/POST variables hash.
226 * @return string Parsed value.
230 return $this->getAttribute('name');
234 * Accessor for default value parsed with the tag.
235 * @return string Parsed value.
238 function getDefault() {
239 return $this->getAttribute('value');
243 * Accessor for currently set value or default if
245 * @return string Value set by form or default
249 function getValue() {
250 if (! $this->_is_set
) {
251 return $this->getDefault();
253 return $this->_value
;
257 * Sets the current form element value.
258 * @param string $value New value.
259 * @return boolean True if allowed.
262 function setValue($value) {
263 $this->_value
= $value;
264 $this->_is_set
= true;
269 * Resets the form element value back to the
273 function resetValue() {
274 $this->_is_set
= false;
278 * Allows setting of a label externally, say by a
280 * @param string $label Label to attach.
283 function setLabel($label) {
284 $this->_label
= trim($label);
288 * Reads external or internal label.
289 * @param string $label Label to test.
290 * @return boolean True is match.
293 function isLabel($label) {
294 return $this->_label
== trim($label);
298 * Dispatches the value into the form encoded packet.
299 * @param SimpleEncoding $encoding Form packet.
302 function write(&$encoding) {
303 if ($this->getName()) {
304 $encoding->add($this->getName(), $this->getValue());
310 * Text, password and hidden field.
311 * @package SimpleTest
312 * @subpackage WebTester
314 class SimpleTextTag
extends SimpleWidget
{
317 * Starts with a named tag with attributes only.
318 * @param hash $attributes Attribute names and
321 function SimpleTextTag($attributes) {
322 $this->SimpleWidget('input', $attributes);
323 if ($this->getAttribute('value') === false) {
324 $this->_setAttribute('value', '');
329 * Tag contains no content.
330 * @return boolean False.
333 function expectEndTag() {
338 * Sets the current form element value. Cannot
339 * change the value of a hidden field.
340 * @param string $value New value.
341 * @return boolean True if allowed.
344 function setValue($value) {
345 if ($this->getAttribute('type') == 'hidden') {
348 return parent
::setValue($value);
353 * Submit button as input tag.
354 * @package SimpleTest
355 * @subpackage WebTester
357 class SimpleSubmitTag
extends SimpleWidget
{
360 * Starts with a named tag with attributes only.
361 * @param hash $attributes Attribute names and
364 function SimpleSubmitTag($attributes) {
365 $this->SimpleWidget('input', $attributes);
366 if ($this->getAttribute('value') === false) {
367 $this->_setAttribute('value', 'Submit');
372 * Tag contains no end element.
373 * @return boolean False.
376 function expectEndTag() {
381 * Disables the setting of the button value.
382 * @param string $value Ignored.
383 * @return boolean True if allowed.
386 function setValue($value) {
391 * Value of browser visible text.
392 * @return string Visible label.
395 function getLabel() {
396 return $this->getValue();
400 * Test for a label match when searching.
401 * @param string $label Label to test.
402 * @return boolean True on match.
405 function isLabel($label) {
406 return trim($label) == trim($this->getLabel());
411 * Image button as input tag.
412 * @package SimpleTest
413 * @subpackage WebTester
415 class SimpleImageSubmitTag
extends SimpleWidget
{
418 * Starts with a named tag with attributes only.
419 * @param hash $attributes Attribute names and
422 function SimpleImageSubmitTag($attributes) {
423 $this->SimpleWidget('input', $attributes);
427 * Tag contains no end element.
428 * @return boolean False.
431 function expectEndTag() {
436 * Disables the setting of the button value.
437 * @param string $value Ignored.
438 * @return boolean True if allowed.
441 function setValue($value) {
446 * Value of browser visible text.
447 * @return string Visible label.
450 function getLabel() {
451 if ($this->getAttribute('title')) {
452 return $this->getAttribute('title');
454 return $this->getAttribute('alt');
458 * Test for a label match when searching.
459 * @param string $label Label to test.
460 * @return boolean True on match.
463 function isLabel($label) {
464 return trim($label) == trim($this->getLabel());
468 * Dispatches the value into the form encoded packet.
469 * @param SimpleEncoding $encoding Form packet.
470 * @param integer $x X coordinate of click.
471 * @param integer $y Y coordinate of click.
474 function write(&$encoding, $x, $y) {
475 if ($this->getName()) {
476 $encoding->add($this->getName() . '.x', $x);
477 $encoding->add($this->getName() . '.y', $y);
479 $encoding->add('x', $x);
480 $encoding->add('y', $y);
486 * Submit button as button tag.
487 * @package SimpleTest
488 * @subpackage WebTester
490 class SimpleButtonTag
extends SimpleWidget
{
493 * Starts with a named tag with attributes only.
494 * Defaults are very browser dependent.
495 * @param hash $attributes Attribute names and
498 function SimpleButtonTag($attributes) {
499 $this->SimpleWidget('button', $attributes);
503 * Check to see if the tag can have both start and
504 * end tags with content in between.
505 * @return boolean True if content allowed.
508 function expectEndTag() {
513 * Disables the setting of the button value.
514 * @param string $value Ignored.
515 * @return boolean True if allowed.
518 function setValue($value) {
523 * Value of browser visible text.
524 * @return string Visible label.
527 function getLabel() {
528 return $this->getContent();
532 * Test for a label match when searching.
533 * @param string $label Label to test.
534 * @return boolean True on match.
537 function isLabel($label) {
538 return trim($label) == trim($this->getLabel());
543 * Content tag for text area.
544 * @package SimpleTest
545 * @subpackage WebTester
547 class SimpleTextAreaTag
extends SimpleWidget
{
550 * Starts with a named tag with attributes only.
551 * @param hash $attributes Attribute names and
554 function SimpleTextAreaTag($attributes) {
555 $this->SimpleWidget('textarea', $attributes);
559 * Accessor for starting value.
560 * @return string Parsed value.
563 function getDefault() {
564 return $this->_wrap(SimpleHtmlSaxParser
::decodeHtml($this->getContent()));
568 * Applies word wrapping if needed.
569 * @param string $value New value.
570 * @return boolean True if allowed.
573 function setValue($value) {
574 return parent
::setValue($this->_wrap($value));
578 * Test to see if text should be wrapped.
579 * @return boolean True if wrapping on.
582 function _wrapIsEnabled() {
583 if ($this->getAttribute('cols')) {
584 $wrap = $this->getAttribute('wrap');
585 if (($wrap == 'physical') ||
($wrap == 'hard')) {
593 * Performs the formatting that is peculiar to
594 * this tag. There is strange behaviour in this
595 * one, including stripping a leading new line.
596 * Go figure. I am using Firefox as a guide.
597 * @param string $text Text to wrap.
598 * @return string Text wrapped with carriage
599 * returns and line feeds
602 function _wrap($text) {
603 $text = str_replace("\r\r\n", "\r\n", str_replace("\n", "\r\n", $text));
604 $text = str_replace("\r\n\n", "\r\n", str_replace("\r", "\r\n", $text));
605 if (strncmp($text, "\r\n", strlen("\r\n")) == 0) {
606 $text = substr($text, strlen("\r\n"));
608 if ($this->_wrapIsEnabled()) {
611 (integer)$this->getAttribute('cols'),
618 * The content of textarea is not part of the page.
619 * @return boolean True.
622 function isPrivateContent() {
628 * File upload widget.
629 * @package SimpleTest
630 * @subpackage WebTester
632 class SimpleUploadTag
extends SimpleWidget
{
635 * Starts with attributes only.
636 * @param hash $attributes Attribute names and
639 function SimpleUploadTag($attributes) {
640 $this->SimpleWidget('input', $attributes);
644 * Tag contains no content.
645 * @return boolean False.
648 function expectEndTag() {
653 * Dispatches the value into the form encoded packet.
654 * @param SimpleEncoding $encoding Form packet.
657 function write(&$encoding) {
658 if (! file_exists($this->getValue())) {
663 implode('', file($this->getValue())),
664 basename($this->getValue()));
670 * @package SimpleTest
671 * @subpackage WebTester
673 class SimpleSelectionTag
extends SimpleWidget
{
678 * Starts with attributes only.
679 * @param hash $attributes Attribute names and
682 function SimpleSelectionTag($attributes) {
683 $this->SimpleWidget('select', $attributes);
684 $this->_options
= array();
685 $this->_choice
= false;
689 * Adds an option tag to a selection field.
690 * @param SimpleOptionTag $tag New option.
693 function addTag(&$tag) {
694 if ($tag->getTagName() == 'option') {
695 $this->_options
[] = &$tag;
700 * Text within the selection element is ignored.
701 * @param string $content Ignored.
704 function addContent($content) {
708 * Scans options for defaults. If none, then
709 * the first option is selected.
710 * @return string Selected field.
713 function getDefault() {
714 for ($i = 0, $count = count($this->_options
); $i < $count; $i++
) {
715 if ($this->_options
[$i]->getAttribute('selected') !== false) {
716 return $this->_options
[$i]->getDefault();
720 return $this->_options
[0]->getDefault();
726 * Can only set allowed values.
727 * @param string $value New choice.
728 * @return boolean True if allowed.
731 function setValue($value) {
732 for ($i = 0, $count = count($this->_options
); $i < $count; $i++
) {
733 if ($this->_options
[$i]->isValue($value)) {
742 * Accessor for current selection value.
743 * @return string Value attribute or
747 function getValue() {
748 if ($this->_choice
=== false) {
749 return $this->getDefault();
751 return $this->_options
[$this->_choice
]->getValue();
757 * @package SimpleTest
758 * @subpackage WebTester
760 class MultipleSelectionTag
extends SimpleWidget
{
765 * Starts with attributes only.
766 * @param hash $attributes Attribute names and
769 function MultipleSelectionTag($attributes) {
770 $this->SimpleWidget('select', $attributes);
771 $this->_options
= array();
772 $this->_values
= false;
776 * Adds an option tag to a selection field.
777 * @param SimpleOptionTag $tag New option.
780 function addTag(&$tag) {
781 if ($tag->getTagName() == 'option') {
782 $this->_options
[] = &$tag;
787 * Text within the selection element is ignored.
788 * @param string $content Ignored.
791 function addContent($content) {
795 * Scans options for defaults to populate the
797 * @return array Selected fields.
800 function getDefault() {
802 for ($i = 0, $count = count($this->_options
); $i < $count; $i++
) {
803 if ($this->_options
[$i]->getAttribute('selected') !== false) {
804 $default[] = $this->_options
[$i]->getDefault();
811 * Can only set allowed values. Any illegal value
812 * will result in a failure, but all correct values
814 * @param array $desired New choices.
815 * @return boolean True if all allowed.
818 function setValue($desired) {
820 foreach ($desired as $value) {
822 for ($i = 0, $count = count($this->_options
); $i < $count; $i++
) {
823 if ($this->_options
[$i]->isValue($value)) {
824 $achieved[] = $this->_options
[$i]->getValue();
833 $this->_values
= $achieved;
838 * Accessor for current selection value.
839 * @return array List of currently set options.
842 function getValue() {
843 if ($this->_values
=== false) {
844 return $this->getDefault();
846 return $this->_values
;
851 * Option for selection field.
852 * @package SimpleTest
853 * @subpackage WebTester
855 class SimpleOptionTag
extends SimpleWidget
{
858 * Stashes the attributes.
860 function SimpleOptionTag($attributes) {
861 $this->SimpleWidget('option', $attributes);
866 * @param string $value Ignored.
867 * @return boolean Not allowed.
870 function setValue($value) {
875 * Test to see if a value matches the option.
876 * @param string $compare Value to compare with.
877 * @return boolean True if possible match.
880 function isValue($compare) {
881 $compare = trim($compare);
882 if (trim($this->getValue()) == $compare) {
885 return trim($this->getContent()) == $compare;
889 * Accessor for starting value. Will be set to
890 * the option label if no value exists.
891 * @return string Parsed value.
894 function getDefault() {
895 if ($this->getAttribute('value') === false) {
896 return $this->getContent();
898 return $this->getAttribute('value');
902 * The content of options is not part of the page.
903 * @return boolean True.
906 function isPrivateContent() {
913 * @package SimpleTest
914 * @subpackage WebTester
916 class SimpleRadioButtonTag
extends SimpleWidget
{
919 * Stashes the attributes.
920 * @param array $attributes Hash of attributes.
922 function SimpleRadioButtonTag($attributes) {
923 $this->SimpleWidget('input', $attributes);
924 if ($this->getAttribute('value') === false) {
925 $this->_setAttribute('value', 'on');
930 * Tag contains no content.
931 * @return boolean False.
934 function expectEndTag() {
939 * The only allowed value sn the one in the
941 * @param string $value New value.
942 * @return boolean True if allowed.
945 function setValue($value) {
946 if ($value === false) {
947 return parent
::setValue($value);
949 if ($value !== $this->getAttribute('value')) {
952 return parent
::setValue($value);
956 * Accessor for starting value.
957 * @return string Parsed value.
960 function getDefault() {
961 if ($this->getAttribute('checked') !== false) {
962 return $this->getAttribute('value');
970 * @package SimpleTest
971 * @subpackage WebTester
973 class SimpleCheckboxTag
extends SimpleWidget
{
976 * Starts with attributes only.
977 * @param hash $attributes Attribute names and
980 function SimpleCheckboxTag($attributes) {
981 $this->SimpleWidget('input', $attributes);
982 if ($this->getAttribute('value') === false) {
983 $this->_setAttribute('value', 'on');
988 * Tag contains no content.
989 * @return boolean False.
992 function expectEndTag() {
997 * The only allowed value in the one in the
998 * "value" attribute. The default for this
999 * attribute is "on". If this widget is set to
1000 * true, then the usual value will be taken.
1001 * @param string $value New value.
1002 * @return boolean True if allowed.
1005 function setValue($value) {
1006 if ($value === false) {
1007 return parent
::setValue($value);
1009 if ($value === true) {
1010 return parent
::setValue($this->getAttribute('value'));
1012 if ($value != $this->getAttribute('value')) {
1015 return parent
::setValue($value);
1019 * Accessor for starting value. The default
1021 * @return string Parsed value.
1024 function getDefault() {
1025 if ($this->getAttribute('checked') !== false) {
1026 return $this->getAttribute('value');
1033 * A group of multiple widgets with some shared behaviour.
1034 * @package SimpleTest
1035 * @subpackage WebTester
1037 class SimpleTagGroup
{
1038 var $_widgets = array();
1041 * Adds a tag to the group.
1042 * @param SimpleWidget $widget
1045 function addWidget(&$widget) {
1046 $this->_widgets
[] = &$widget;
1050 * Accessor to widget set.
1051 * @return array All widgets.
1054 function &_getWidgets() {
1055 return $this->_widgets
;
1059 * Accessor for an attribute.
1060 * @param string $label Attribute name.
1061 * @return boolean Always false.
1064 function getAttribute($label) {
1069 * Fetches the name for the widget from the first
1071 * @return string Name of widget.
1074 function getName() {
1075 if (count($this->_widgets
) > 0) {
1076 return $this->_widgets
[0]->getName();
1081 * Scans the widgets for one with the appropriate
1083 * @param string $id ID value to try.
1084 * @return boolean True if matched.
1087 function isId($id) {
1088 for ($i = 0, $count = count($this->_widgets
); $i < $count; $i++
) {
1089 if ($this->_widgets
[$i]->isId($id)) {
1097 * Scans the widgets for one with the appropriate
1099 * @param string $label Attached label to try.
1100 * @return boolean True if matched.
1103 function isLabel($label) {
1104 for ($i = 0, $count = count($this->_widgets
); $i < $count; $i++
) {
1105 if ($this->_widgets
[$i]->isLabel($label)) {
1113 * Dispatches the value into the form encoded packet.
1114 * @param SimpleEncoding $encoding Form packet.
1117 function write(&$encoding) {
1118 $encoding->add($this->getName(), $this->getValue());
1123 * A group of tags with the same name within a form.
1124 * @package SimpleTest
1125 * @subpackage WebTester
1127 class SimpleCheckboxGroup
extends SimpleTagGroup
{
1130 * Accessor for current selected widget or false
1132 * @return string/array Widget values or false if none.
1135 function getValue() {
1137 $widgets = &$this->_getWidgets();
1138 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1139 if ($widgets[$i]->getValue() !== false) {
1140 $values[] = $widgets[$i]->getValue();
1143 return $this->_coerceValues($values);
1147 * Accessor for starting value that is active.
1148 * @return string/array Widget values or false if none.
1151 function getDefault() {
1153 $widgets = &$this->_getWidgets();
1154 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1155 if ($widgets[$i]->getDefault() !== false) {
1156 $values[] = $widgets[$i]->getDefault();
1159 return $this->_coerceValues($values);
1163 * Accessor for current set values.
1164 * @param string/array/boolean $values Either a single string, a
1165 * hash or false for nothing set.
1166 * @return boolean True if all values can be set.
1169 function setValue($values) {
1170 $values = $this->_makeArray($values);
1171 if (! $this->_valuesArePossible($values)) {
1174 $widgets = &$this->_getWidgets();
1175 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1176 $possible = $widgets[$i]->getAttribute('value');
1177 if (in_array($widgets[$i]->getAttribute('value'), $values)) {
1178 $widgets[$i]->setValue($possible);
1180 $widgets[$i]->setValue(false);
1187 * Tests to see if a possible value set is legal.
1188 * @param string/array/boolean $values Either a single string, a
1189 * hash or false for nothing set.
1190 * @return boolean False if trying to set a
1194 function _valuesArePossible($values) {
1196 $widgets = &$this->_getWidgets();
1197 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1198 $possible = $widgets[$i]->getAttribute('value');
1199 if (in_array($possible, $values)) {
1200 $matches[] = $possible;
1203 return ($values == $matches);
1207 * Converts the output to an appropriate format. This means
1208 * that no values is false, a single value is just that
1209 * value and only two or more are contained in an array.
1210 * @param array $values List of values of widgets.
1211 * @return string/array/boolean Expected format for a tag.
1214 function _coerceValues($values) {
1215 if (count($values) == 0) {
1217 } elseif (count($values) == 1) {
1225 * Converts false or string into array. The opposite of
1226 * the coercian method.
1227 * @param string/array/boolean $value A single item is converted
1228 * to a one item list. False
1229 * gives an empty list.
1230 * @return array List of values, possibly empty.
1233 function _makeArray($value) {
1234 if ($value === false) {
1237 if (is_string($value)) {
1238 return array($value);
1245 * A group of tags with the same name within a form.
1246 * Used for radio buttons.
1247 * @package SimpleTest
1248 * @subpackage WebTester
1250 class SimpleRadioGroup
extends SimpleTagGroup
{
1253 * Each tag is tried in turn until one is
1254 * successfully set. The others will be
1255 * unchecked if successful.
1256 * @param string $value New value.
1257 * @return boolean True if any allowed.
1260 function setValue($value) {
1261 if (! $this->_valueIsPossible($value)) {
1265 $widgets = &$this->_getWidgets();
1266 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1267 if (! $widgets[$i]->setValue($value)) {
1268 $widgets[$i]->setValue(false);
1275 * Tests to see if a value is allowed.
1276 * @param string Attempted value.
1277 * @return boolean True if a valid value.
1280 function _valueIsPossible($value) {
1281 $widgets = &$this->_getWidgets();
1282 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1283 if ($widgets[$i]->getAttribute('value') == $value) {
1291 * Accessor for current selected widget or false
1293 * @return string/boolean Value attribute or
1297 function getValue() {
1298 $widgets = &$this->_getWidgets();
1299 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1300 if ($widgets[$i]->getValue() !== false) {
1301 return $widgets[$i]->getValue();
1308 * Accessor for starting value that is active.
1309 * @return string/boolean Value of first checked
1310 * widget or false if none.
1313 function getDefault() {
1314 $widgets = &$this->_getWidgets();
1315 for ($i = 0, $count = count($widgets); $i < $count; $i++
) {
1316 if ($widgets[$i]->getDefault() !== false) {
1317 return $widgets[$i]->getDefault();
1325 * Tag to keep track of labels.
1326 * @package SimpleTest
1327 * @subpackage WebTester
1329 class SimpleLabelTag
extends SimpleTag
{
1332 * Starts with a named tag with attributes only.
1333 * @param hash $attributes Attribute names and
1336 function SimpleLabelTag($attributes) {
1337 $this->SimpleTag('label', $attributes);
1341 * Access for the ID to attach the label to.
1342 * @return string For attribute.
1346 return $this->getAttribute('for');
1351 * Tag to aid parsing the form.
1352 * @package SimpleTest
1353 * @subpackage WebTester
1355 class SimpleFormTag
extends SimpleTag
{
1358 * Starts with a named tag with attributes only.
1359 * @param hash $attributes Attribute names and
1362 function SimpleFormTag($attributes) {
1363 $this->SimpleTag('form', $attributes);
1368 * Tag to aid parsing the frames in a page.
1369 * @package SimpleTest
1370 * @subpackage WebTester
1372 class SimpleFrameTag
extends SimpleTag
{
1375 * Starts with a named tag with attributes only.
1376 * @param hash $attributes Attribute names and
1379 function SimpleFrameTag($attributes) {
1380 $this->SimpleTag('frame', $attributes);
1384 * Tag contains no content.
1385 * @return boolean False.
1388 function expectEndTag() {