3 * Base include file for SimpleTest
5 * @subpackage WebTester
6 * @version $Id: frames.php,v 1.39 2005/09/09 01:42:29 lastcraft Exp $
10 * include other SimpleTest class files
12 require_once(dirname(__FILE__
) . '/page.php');
13 require_once(dirname(__FILE__
) . '/user_agent.php');
17 * A composite page. Wraps a frameset page and
18 * adds subframes. The original page will be
19 * mostly ignored. Implements the SimplePage
20 * interface so as to be interchangeable.
22 * @subpackage WebTester
24 class SimpleFrameset
{
31 * Stashes the frameset page. Will make use of the
32 * browser to fetch the sub frames recursively.
33 * @param SimplePage $page Frameset page.
35 function SimpleFrameset(&$page) {
36 $this->_frameset
= &$page;
37 $this->_frames
= array();
38 $this->_focus
= false;
39 $this->_names
= array();
43 * Adds a parsed page to the frameset.
44 * @param SimplePage $page Frame page.
45 * @param string $name Name of frame in frameset.
48 function addFrame(&$page, $name = false) {
49 $this->_frames
[] = &$page;
51 $this->_names
[$name] = count($this->_frames
) - 1;
56 * Replaces existing frame with another. If the
57 * frame is nested, then the call is passed down
59 * @param array $path Path of frame in frameset.
60 * @param SimplePage $page Frame source.
63 function setFrame($path, &$page) {
64 $name = array_shift($path);
65 if (isset($this->_names
[$name])) {
66 $index = $this->_names
[$name];
70 if (count($path) == 0) {
71 $this->_frames
[$index] = &$page;
74 $this->_frames
[$index]->setFrame($path, $page);
78 * Accessor for current frame focus. Will be
79 * false if no frame has focus. Will have the nested
81 * @return array Labels or indexes of nested frames.
84 function getFrameFocus() {
85 if ($this->_focus
=== false) {
89 array($this->_getPublicNameFromIndex($this->_focus
)),
90 $this->_frames
[$this->_focus
]->getFrameFocus());
94 * Turns an internal array index into the frames list
95 * into a public name, or if none, then a one offset
97 * @param integer $subject Internal index.
98 * @return integer/string Public name.
101 function _getPublicNameFromIndex($subject) {
102 foreach ($this->_names
as $name => $index) {
103 if ($subject == $index) {
111 * Sets the focus by index. The integer index starts from 1.
112 * If already focused and the target frame also has frames,
113 * then the nested frame will be focused.
114 * @param integer $choice Chosen frame.
115 * @return boolean True if frame exists.
118 function setFrameFocusByIndex($choice) {
119 if (is_integer($this->_focus
)) {
120 if ($this->_frames
[$this->_focus
]->hasFrames()) {
121 return $this->_frames
[$this->_focus
]->setFrameFocusByIndex($choice);
124 if (($choice < 1) ||
($choice > count($this->_frames
))) {
127 $this->_focus
= $choice - 1;
132 * Sets the focus by name. If already focused and the
133 * target frame also has frames, then the nested frame
135 * @param string $name Chosen frame.
136 * @return boolean True if frame exists.
139 function setFrameFocus($name) {
140 if (is_integer($this->_focus
)) {
141 if ($this->_frames
[$this->_focus
]->hasFrames()) {
142 return $this->_frames
[$this->_focus
]->setFrameFocus($name);
145 if (in_array($name, array_keys($this->_names
))) {
146 $this->_focus
= $this->_names
[$name];
153 * Clears the frame focus.
156 function clearFrameFocus() {
157 $this->_focus
= false;
158 $this->_clearNestedFramesFocus();
162 * Clears the frame focus for any nested frames.
165 function _clearNestedFramesFocus() {
166 for ($i = 0; $i < count($this->_frames
); $i++
) {
167 $this->_frames
[$i]->clearFrameFocus();
172 * Test for the presence of a frameset.
173 * @return boolean Always true.
176 function hasFrames() {
181 * Accessor for frames information.
182 * @return array/string Recursive hash of frame URL strings.
183 * The key is either a numerical
184 * index or the name attribute.
187 function getFrames() {
189 for ($i = 0; $i < count($this->_frames
); $i++
) {
190 $report[$this->_getPublicNameFromIndex($i)] =
191 $this->_frames
[$i]->getFrames();
197 * Accessor for raw text of either all the pages or
198 * the frame in focus.
199 * @return string Raw unparsed content.
203 if (is_integer($this->_focus
)) {
204 return $this->_frames
[$this->_focus
]->getRaw();
207 for ($i = 0; $i < count($this->_frames
); $i++
) {
208 $raw .= $this->_frames
[$i]->getRaw();
214 * Accessor for plain text of either all the pages or
215 * the frame in focus.
216 * @return string Plain text content.
220 if (is_integer($this->_focus
)) {
221 return $this->_frames
[$this->_focus
]->getText();
224 for ($i = 0; $i < count($this->_frames
); $i++
) {
225 $raw .= ' ' . $this->_frames
[$i]->getText();
231 * Accessor for last error.
232 * @return string Error from last response.
235 function getTransportError() {
236 if (is_integer($this->_focus
)) {
237 return $this->_frames
[$this->_focus
]->getTransportError();
239 return $this->_frameset
->getTransportError();
243 * Request method used to fetch this frame.
244 * @return string GET, POST or HEAD.
247 function getMethod() {
248 if (is_integer($this->_focus
)) {
249 return $this->_frames
[$this->_focus
]->getMethod();
251 return $this->_frameset
->getMethod();
255 * Original resource name.
256 * @return SimpleUrl Current url.
260 if (is_integer($this->_focus
)) {
261 $url = $this->_frames
[$this->_focus
]->getUrl();
262 $url->setTarget($this->_getPublicNameFromIndex($this->_focus
));
264 $url = $this->_frameset
->getUrl();
270 * Original request data.
271 * @return mixed Sent content.
274 function getRequestData() {
275 if (is_integer($this->_focus
)) {
276 return $this->_frames
[$this->_focus
]->getRequestData();
278 return $this->_frameset
->getRequestData();
282 * Accessor for current MIME type.
283 * @return string MIME type as string; e.g. 'text/html'
286 function getMimeType() {
287 if (is_integer($this->_focus
)) {
288 return $this->_frames
[$this->_focus
]->getMimeType();
290 return $this->_frameset
->getMimeType();
294 * Accessor for last response code.
295 * @return integer Last HTTP response code received.
298 function getResponseCode() {
299 if (is_integer($this->_focus
)) {
300 return $this->_frames
[$this->_focus
]->getResponseCode();
302 return $this->_frameset
->getResponseCode();
306 * Accessor for last Authentication type. Only valid
307 * straight after a challenge (401).
308 * @return string Description of challenge type.
311 function getAuthentication() {
312 if (is_integer($this->_focus
)) {
313 return $this->_frames
[$this->_focus
]->getAuthentication();
315 return $this->_frameset
->getAuthentication();
319 * Accessor for last Authentication realm. Only valid
320 * straight after a challenge (401).
321 * @return string Name of security realm.
324 function getRealm() {
325 if (is_integer($this->_focus
)) {
326 return $this->_frames
[$this->_focus
]->getRealm();
328 return $this->_frameset
->getRealm();
332 * Accessor for outgoing header information.
333 * @return string Header block.
336 function getRequest() {
337 if (is_integer($this->_focus
)) {
338 return $this->_frames
[$this->_focus
]->getRequest();
340 return $this->_frameset
->getRequest();
344 * Accessor for raw header information.
345 * @return string Header block.
348 function getHeaders() {
349 if (is_integer($this->_focus
)) {
350 return $this->_frames
[$this->_focus
]->getHeaders();
352 return $this->_frameset
->getHeaders();
356 * Accessor for parsed title.
357 * @return string Title or false if no title is present.
360 function getTitle() {
361 return $this->_frameset
->getTitle();
365 * Accessor for a list of all fixed links.
366 * @return array List of urls with scheme of
367 * http or https and hostname.
370 function getAbsoluteUrls() {
371 if (is_integer($this->_focus
)) {
372 return $this->_frames
[$this->_focus
]->getAbsoluteUrls();
375 foreach ($this->_frames
as $frame) {
376 $urls = array_merge($urls, $frame->getAbsoluteUrls());
378 return array_values(array_unique($urls));
382 * Accessor for a list of all relative links.
383 * @return array List of urls without hostname.
386 function getRelativeUrls() {
387 if (is_integer($this->_focus
)) {
388 return $this->_frames
[$this->_focus
]->getRelativeUrls();
391 foreach ($this->_frames
as $frame) {
392 $urls = array_merge($urls, $frame->getRelativeUrls());
394 return array_values(array_unique($urls));
398 * Accessor for URLs by the link label. Label will match
399 * regardess of whitespace issues and case.
400 * @param string $label Text of link.
401 * @return array List of links with that label.
404 function getUrlsByLabel($label) {
405 if (is_integer($this->_focus
)) {
406 return $this->_tagUrlsWithFrame(
407 $this->_frames
[$this->_focus
]->getUrlsByLabel($label),
411 foreach ($this->_frames
as $index => $frame) {
414 $this->_tagUrlsWithFrame(
415 $frame->getUrlsByLabel($label),
422 * Accessor for a URL by the id attribute. If in a frameset
423 * then the first link found with that ID attribute is
424 * returned only. Focus on a frame if you want one from
425 * a specific part of the frameset.
426 * @param string $id Id attribute of link.
427 * @return string URL with that id.
430 function getUrlById($id) {
431 foreach ($this->_frames
as $index => $frame) {
432 if ($url = $frame->getUrlById($id)) {
433 if (! $url->gettarget()) {
434 $url->setTarget($this->_getPublicNameFromIndex($index));
443 * Attaches the intended frame index to a list of URLs.
444 * @param array $urls List of SimpleUrls.
445 * @param string $frame Name of frame or index.
446 * @return array List of tagged URLs.
449 function _tagUrlsWithFrame($urls, $frame) {
451 foreach ($urls as $url) {
452 if (! $url->getTarget()) {
453 $url->setTarget($this->_getPublicNameFromIndex($frame));
461 * Finds a held form by button label. Will only
462 * search correctly built forms.
463 * @param SimpleSelector $selector Button finder.
464 * @return SimpleForm Form object containing
468 function &getFormBySubmit($selector) {
469 $form = &$this->_findForm('getFormBySubmit', $selector);
474 * Finds a held form by image using a selector.
475 * Will only search correctly built forms. The first
476 * form found either within the focused frame, or
477 * across frames, will be the one returned.
478 * @param SimpleSelector $selector Image finder.
479 * @return SimpleForm Form object containing
483 function &getFormByImage($selector) {
484 $form = &$this->_findForm('getFormByImage', $selector);
489 * Finds a held form by the form ID. A way of
490 * identifying a specific form when we have control
491 * of the HTML code. The first form found
492 * either within the focused frame, or across frames,
493 * will be the one returned.
494 * @param string $id Form label.
495 * @return SimpleForm Form object containing the matching ID.
498 function &getFormById($id) {
499 $form = &$this->_findForm('getFormById', $id);
504 * General form finder. Will search all the frames or
505 * just the one in focus.
506 * @param string $method Method to use to find in a page.
507 * @param string $attribute Label, name or ID.
508 * @return SimpleForm Form object containing the matching ID.
511 function &_findForm($method, $attribute) {
512 if (is_integer($this->_focus
)) {
513 $form = &$this->_findFormInFrame(
514 $this->_frames
[$this->_focus
],
520 for ($i = 0; $i < count($this->_frames
); $i++
) {
521 $form = &$this->_findFormInFrame(
535 * Finds a form in a page using a form finding method. Will
536 * also tag the form with the frame name it belongs in.
537 * @param SimplePage $page Page content of frame.
538 * @param integer $index Internal frame representation.
539 * @param string $method Method to use to find in a page.
540 * @param string $attribute Label, name or ID.
541 * @return SimpleForm Form object containing the matching ID.
544 function &_findFormInFrame(&$page, $index, $method, $attribute) {
545 $form = &$this->_frames
[$index]->$method($attribute);
547 $form->setDefaultTarget($this->_getPublicNameFromIndex($index));
553 * Sets a field on each form in which the field is
555 * @param SimpleSelector $selector Field finder.
556 * @param string $value Value to set field to.
557 * @return boolean True if value is valid.
560 function setField($selector, $value) {
561 if (is_integer($this->_focus
)) {
562 $this->_frames
[$this->_focus
]->setField($selector, $value);
564 for ($i = 0; $i < count($this->_frames
); $i++
) {
565 $this->_frames
[$i]->setField($selector, $value);
571 * Accessor for a form element value within a page.
572 * @param SimpleSelector $selector Field finder.
573 * @return string/boolean A string if the field is
574 * present, false if unchecked
575 * and null if missing.
578 function getField($selector) {
579 for ($i = 0; $i < count($this->_frames
); $i++
) {
580 $value = $this->_frames
[$i]->getField($selector);