PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/sites/all/modules/simpletest/drupal_test_case.php

https://github.com/sdboyer/sdboyer-test
PHP | 818 lines | 433 code | 84 blank | 301 comment | 45 complexity | 51a11d56833b32ccdd18225d64a6eb06 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /* $Id: drupal_test_case.php,v 1.53 2008/02/19 13:52:05 rokZlender Exp $ */
  3. /**
  4. * Test case for typical Drupal tests.
  5. * Extends WebTestCase for comfortable browser usage
  6. * but also implements all UnitTestCase methods, I wish
  7. * WebTestCase would do this.
  8. */
  9. class DrupalTestCase extends WebTestCase {
  10. var $_content;
  11. var $_originalModules = array();
  12. var $_modules = array();
  13. var $_cleanupVariables = array();
  14. var $_cleanupUsers = array();
  15. var $_cleanupRoles = array();
  16. var $_cleanupNodes = array();
  17. var $_cleanupContentTypes = array();
  18. function DrupalTestCase($label = NULL) {
  19. if (! $label) {
  20. if (method_exists($this, 'get_info')) {
  21. $info = $this->get_info();
  22. $label = $info['name'];
  23. }
  24. }
  25. $this->WebTestCase($label);
  26. }
  27. /**
  28. * Creates a node based on default settings.
  29. *
  30. * @param settings An array of settings to change from the defaults, in the form of 'body' => 'Hello, world!'
  31. */
  32. function drupalCreateNode($settings = array()) {
  33. // Populate defaults array
  34. $defaults = array(
  35. 'body' => $this->randomName(32),
  36. 'title' => $this->randomName(8),
  37. 'comment' => 2,
  38. 'changed' => time(),
  39. 'format' => 1,
  40. 'moderate' => 0,
  41. 'promote' => 0,
  42. 'revision' => 1,
  43. 'log' => '',
  44. 'status' => 1,
  45. 'sticky' => 0,
  46. 'type' => 'page',
  47. 'revisions' => NULL,
  48. 'taxonomy' => NULL,
  49. );
  50. $defaults['teaser'] = $defaults['body'];
  51. // If we already have a node, we use the original node's created time, and this
  52. $defaults['date'] = format_date($defaults['created'], 'custom', 'Y-m-d H:i:s O');
  53. if (empty($settings['uid'])) {
  54. global $user;
  55. $defaults['uid'] = $user->uid;
  56. }
  57. $node = ($settings + $defaults);
  58. $node = (object)$node;
  59. node_save($node);
  60. // small hack to link revisions to our test user
  61. db_query('UPDATE {node_revisions} SET uid = %d WHERE vid = %d', $node->uid, $node->vid);
  62. $this->_cleanupNodes[] = $node->nid;
  63. return $node;
  64. }
  65. /**
  66. * Creates a custom content type based on default settings.
  67. *
  68. * @param settings An array of settings to change from the defaults, in the form of 'type' => 'foo'
  69. */
  70. function drupalCreateContentType($settings = array()) {
  71. // find a non-existent random type name.
  72. do {
  73. $name = strtolower($this->randomName(3, 'type_'));
  74. } while (node_get_types('type', $name));
  75. // Populate defaults array
  76. $defaults = array(
  77. 'type' => $name,
  78. 'name' => $name,
  79. 'description' => '',
  80. 'help' => '',
  81. 'min_word_count' => 0,
  82. 'title_label' => 'Title',
  83. 'body_label' => 'Body',
  84. 'has_title' => 1,
  85. 'has_body' => 1,
  86. );
  87. // imposed values for a custom type
  88. $forced = array(
  89. 'orig_type' => '',
  90. 'old_type' => '',
  91. 'module' => 'node',
  92. 'custom' => 1,
  93. 'modified' => 1,
  94. 'locked' => 0,
  95. );
  96. $type = $forced + $settings + $defaults;
  97. $type = (object)$type;
  98. node_type_save($type);
  99. node_types_rebuild();
  100. $this->_cleanupContentTypes[] = $type->type;
  101. return $type;
  102. }
  103. /**
  104. * @abstract Checks to see if we need to send
  105. * a http-auth header to authenticate
  106. * when browsing a site.
  107. *
  108. * @param status Boolean pass true if you want to know if we are using
  109. * HTTP-AUTH
  110. * @return void
  111. */
  112. function drupalCheckAuth($status = false) {
  113. $check = variable_get('simpletest_httpauth', false);
  114. if( $status ) {
  115. return $check;
  116. }
  117. if( variable_get('simpletest_httpauth', false) ) {
  118. $html = $this->authenticate(variable_get('simpletest_httpauth_username', ''), variable_get('simpletest_httpauth_pass', ''));
  119. }
  120. return $html;
  121. }
  122. /**
  123. * @abstract Broker for the get function
  124. * adds the authentication headers if necessary
  125. * @author Earnest Berry III <earnest.berry@gmail.com>
  126. *
  127. * @param $path string Drupal path or url to load into internal browser
  128. * @param array $options Options to be forwarded to url().
  129. * @return void
  130. */
  131. function drupalGet($path, $options = array()) {
  132. $url = url($path, array_merge($options, array('absolute' => TRUE)));
  133. $html = $this->_browser->get($url);
  134. if ($this->drupalCheckAuth(true)) {
  135. $html .= $this->drupalCheckAuth();
  136. }
  137. $this->_content = $this->_browser->getContent();
  138. return $html;
  139. }
  140. /**
  141. * @abstract Broker for the post function
  142. * adds the authentication headers if
  143. * necessary
  144. * @author Earnest Berry III <earnest.berry@gmail.com>
  145. *
  146. * @param url string Url to retch
  147. * @return void
  148. */
  149. function drupalRawPost($action, $edit = array()) {
  150. $html = $this->_browser->post($action, $edit);
  151. if( $this->drupalCheckAuth(true) ) {
  152. $html .= $this->drupalCheckAuth();
  153. }
  154. $this->_content = $this->_browser->getContent();
  155. return $html;
  156. }
  157. /**
  158. * Do a post request on a drupal page.
  159. * It will be done as usual post request with SimpleBrowser
  160. * By $reporting you specify if this request does assertions or not
  161. * Warning: empty ("") returns will cause fails with $reporting
  162. *
  163. * @param string $path
  164. * Location of the post form. Either a Drupal path or an absolute path or
  165. * NULL to post to the current page.
  166. * @param array $edit
  167. * Field data in an assocative array. Changes the current input fields
  168. * (where possible) to the values indicated. A checkbox can be set to
  169. * TRUE to be checked and FALSE to be unchecked.
  170. * @param string $submit
  171. * Untranslated value, id or name of the submit button.
  172. */
  173. function drupalPost($path, $edit = array(), $submit) {
  174. if (isset($path)) {
  175. $ret = $this->drupalGet($path);
  176. $this->assertTrue($ret, t(' [browser] GET path "@path"', array('@path' => $path)));
  177. }
  178. foreach ($edit as $field_name => $field_value) {
  179. $ret = $this->_browser->setFieldByName($field_name, $field_value)
  180. || $this->_browser->setFieldById("edit-$field_name", $field_value);
  181. $this->assertTrue($ret, " [browser] Setting $field_name=\"$field_value\"");
  182. }
  183. $ret = $this->_browser->clickSubmit(t($submit)) || $this->_browser->clickSubmitById($submit) || $this->_browser->clickSubmitByName($submit) || $this->_browser->clickImageByName($submit);
  184. $this->assertTrue($ret, ' [browser] POST by click on ' . t($submit));
  185. $this->_content = $this->_browser->getContent();
  186. }
  187. /**
  188. * Follows a link by name.
  189. *
  190. * Will click the first link found with this link text by default, or a
  191. * later one if an index is given. Match is case insensitive with
  192. * normalized space. The label is translated label. There is an assert
  193. * for successful click.
  194. * WARNING: Assertion fails on empty ("") output from the clicked link
  195. *
  196. * @param string $label Text between the anchor tags.
  197. * @param integer $index Link position counting from zero.
  198. * @param boolean $reporting Assertions or not
  199. * @return boolean/string Page on success.
  200. *
  201. * @access public
  202. */
  203. function clickLink($label, $index = 0) {
  204. $url_before = $this->getUrl();
  205. $urls = $this->_browser->_page->getUrlsByLabel($label);
  206. if (count($urls) < $index + 1) {
  207. $url_target = 'URL NOT FOUND!';
  208. } else {
  209. $url_target = $urls[$index]->asString();
  210. }
  211. $ret = parent::clickLink(t($label), $index);
  212. $this->assertTrue($ret, ' [browser] clicked link '. t($label) . " ($url_target) from $url_before");
  213. return $ret;
  214. }
  215. /**
  216. * @TODO: needs documentation
  217. */
  218. function drupalGetContent() {
  219. return $this->_content;
  220. }
  221. /**
  222. * Generates a random string, to be used as name or whatever
  223. * @param integer $number number of characters
  224. * @return random string
  225. */
  226. function randomName($number = 4, $prefix = 'simpletest_') {
  227. $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_';
  228. for ($x = 0; $x < $number; $x++) {
  229. $prefix .= $chars{mt_rand(0, strlen($chars)-1)};
  230. if ($x == 0) {
  231. $chars .= '0123456789';
  232. }
  233. }
  234. return $prefix;
  235. }
  236. /**
  237. * Enables a drupal module
  238. * @param string $name name of the module
  239. * @return boolean success
  240. */
  241. function drupalModuleEnable($name) {
  242. if (module_exists($name)) {
  243. $this->pass(" [module] $name already enabled");
  244. return TRUE;
  245. }
  246. $this->checkOriginalModules();
  247. if (array_search($name, $this->_modules) === FALSE) {
  248. $this->_modules[$name] = $name;
  249. $form_state['values'] = array('status' => $this->_modules, 'op' => t('Save configuration'));
  250. drupal_execute('system_modules', $form_state);
  251. //rebuilding all caches
  252. drupal_rebuild_theme_registry();
  253. node_types_rebuild();
  254. menu_rebuild();
  255. cache_clear_all('schema', 'cache');
  256. module_rebuild_cache();
  257. }
  258. }
  259. /**
  260. * Disables a drupal module
  261. * @param string $name name of the module
  262. * @return boolean success
  263. */
  264. function drupalModuleDisable($name) {
  265. if (!module_exists($name)) {
  266. $this->pass(" [module] $name already disabled");
  267. return TRUE;
  268. }
  269. $this->checkOriginalModules();
  270. if (($key = array_search($name, $this->_modules)) !== FALSE) {
  271. unset($this->_modules[$key]);
  272. $form_state['values'] = array('status' => $this->_modules, 'op' => t('Save configuration'));
  273. drupal_execute('system_modules', $form_state);
  274. //rebuilding all caches
  275. drupal_rebuild_theme_registry();
  276. node_types_rebuild();
  277. menu_rebuild();
  278. cache_clear_all('schema', 'cache');
  279. module_rebuild_cache();
  280. }
  281. }
  282. /**
  283. * Retrieves and saves current modules list into $_originalModules and $_modules.
  284. */
  285. function checkOriginalModules() {
  286. if (empty($this->_originalModules)) {
  287. require_once ('./modules/system/system.admin.inc');
  288. $form_state = array();
  289. $form = drupal_retrieve_form('system_modules', $form_state);
  290. $this->_originalModules = drupal_map_assoc($form['status']['#default_value']);
  291. $this->_modules = $this->_originalModules;
  292. }
  293. }
  294. /**
  295. * Set a drupal variable and keep track of the changes for tearDown()
  296. * @param string $name name of the value
  297. * @param mixed $value value
  298. */
  299. function drupalVariableSet($name, $value) {
  300. /* NULL variables would anyways result in default because of isset */
  301. $old_value = variable_get($name, NULL);
  302. if ($value !== $old_value) {
  303. variable_set($name, $value);
  304. /* Use array_key_exists instead of isset so NULL values do not get overwritten */
  305. if (!array_key_exists($name, $this->_cleanupVariables)) {
  306. $this->_cleanupVariables[$name] = $old_value;
  307. }
  308. }
  309. }
  310. /**
  311. * Create a role / perm combination specified by permissions
  312. *
  313. * @param array $permissions Array of the permission strings
  314. * @return integer role-id
  315. */
  316. function drupalCreateRolePerm($permissions = NULL) {
  317. if ($permissions === NULL) {
  318. $permstring = 'access comments, access content, post comments, post comments without approval';
  319. } else {
  320. $permstring = implode(', ', $permissions);
  321. }
  322. /* Create role */
  323. $role_name = $this->randomName();
  324. db_query("INSERT INTO {role} (name) VALUES ('%s')", $role_name);
  325. $role = db_fetch_object(db_query("SELECT * FROM {role} WHERE name = '%s'", $role_name));
  326. $this->assertTrue($role, " [role] created name: $role_name, id: " . (isset($role->rid) ? $role->rid : '-n/a-'));
  327. if ($role && !empty($role->rid)) {
  328. /* Create permissions */
  329. db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, $permstring);
  330. $this->assertTrue(db_affected_rows(), ' [role] created permissions: ' . $permstring);
  331. $this->_cleanupRoles[] = $role->rid;
  332. return $role->rid;
  333. } else {
  334. return false;
  335. }
  336. }
  337. /**
  338. * Creates a user / role / permissions combination specified by permissions
  339. *
  340. * @param array $permissions Array of the permission strings
  341. * @return array/boolean false if fails. fully loaded user object with added pass_raw property
  342. */
  343. function drupalCreateUserRolePerm($permissions = NULL) {
  344. /* Create role */
  345. $rid = $this->drupalCreateRolePerm($permissions);
  346. if (!$rid) {
  347. return FALSE;
  348. }
  349. /* Create user */
  350. $ua = array();
  351. $ua['name'] = $this->randomName();
  352. $ua['mail'] = $ua['name'] . '@example.com';
  353. $ua['roles'] = array($rid=>$rid);
  354. $ua['pass'] = user_password();
  355. $ua['status'] = 1;
  356. $u = user_save('', $ua);
  357. $this->assertTrue(!empty($u->uid), " [user] name: $ua[name] pass: $ua[pass] created");
  358. if (empty($u->uid)) {
  359. return FALSE;
  360. }
  361. /* Add to cleanup list */
  362. $this->_cleanupUsers[] = $u->uid;
  363. /* Add the raw password */
  364. $u->pass_raw = $ua['pass'];
  365. return $u;
  366. }
  367. /**
  368. * Logs in a user with the internal browser
  369. *
  370. * @param object user object with pass_raw property!
  371. * @param $submit value of submit button on log in form
  372. */
  373. function drupalLoginUser($user = NULL, $submit = 'Log in') {
  374. $this->drupalGet('user');
  375. // Going to the page retrieves the cookie, as the browser should save it
  376. if ($user === NULL) {
  377. $user = $this->drupalCreateUserRolePerm();
  378. }
  379. $edit = array('name' => $user->name, 'pass' => $user->pass_raw);
  380. $this->drupalPost('user', $edit, $submit);
  381. $this->assertText( $user->name, ' [login] found name: ' . $user->name);
  382. $this->assertNoText(t('The username %name has been blocked.', array('%name' => $user->name)), ' [login] not blocked');
  383. $this->assertNoText(t('The name %name is a reserved username.', array('%name' => $user->name)), ' [login] not reserved');
  384. return $user;
  385. }
  386. /**
  387. * tearDown implementation, setting back switched modules etc
  388. */
  389. function tearDown() {
  390. if ($this->_modules != $this->_originalModules) {
  391. $form_state['values'] = array('status' => $this->_originalModules, 'op' => t('Save configuration'));
  392. drupal_execute('system_modules', $form_state);
  393. //rebuilding all caches
  394. drupal_rebuild_theme_registry();
  395. node_types_rebuild();
  396. menu_rebuild();
  397. cache_clear_all('schema', 'cache');
  398. module_rebuild_cache();
  399. $this->_modules = $this->_originalModules;
  400. }
  401. foreach ($this->_cleanupVariables as $name => $value) {
  402. if (is_null($value)) {
  403. variable_del($name);
  404. } else {
  405. variable_set($name, $value);
  406. }
  407. }
  408. $this->_cleanupVariables = array();
  409. //delete nodes
  410. foreach ($this->_cleanupNodes as $nid) {
  411. node_delete($nid);
  412. }
  413. $this->_cleanupNodes = array();
  414. //delete roles
  415. while (sizeof($this->_cleanupRoles) > 0) {
  416. $rid = array_pop($this->_cleanupRoles);
  417. db_query("DELETE FROM {role} WHERE rid = %d", $rid);
  418. db_query("DELETE FROM {permission} WHERE rid = %d", $rid);
  419. }
  420. //delete users and their content
  421. while (sizeof($this->_cleanupUsers) > 0) {
  422. $uid = array_pop($this->_cleanupUsers);
  423. // cleanup nodes this user created
  424. $result = db_query("SELECT nid FROM {node} WHERE uid = %d", $uid);
  425. while ($node = db_fetch_array($result)) {
  426. node_delete($node['nid']);
  427. }
  428. user_delete(array(), $uid);
  429. }
  430. //delete content types
  431. foreach ($this->_cleanupContentTypes as $type) {
  432. node_type_delete($type);
  433. }
  434. $this->_cleanupContentTypes = array();
  435. //Output drupal warnings and messages into assert messages
  436. $drupal_msgs = drupal_get_messages();
  437. foreach($drupal_msgs as $type => $msgs) {
  438. foreach ($msgs as $msg) {
  439. $this->assertTrue(TRUE, "$type: $msg");
  440. }
  441. }
  442. parent::tearDown();
  443. }
  444. /**
  445. * Just some info for the reporter
  446. */
  447. function run(&$reporter) {
  448. $arr = array('class' => get_class($this));
  449. if (method_exists($this, 'get_info')) {
  450. $arr = array_merge($arr, $this->get_info());
  451. }
  452. $reporter->test_info_stack[] = $arr;
  453. parent::run($reporter);
  454. array_pop($reporter->test_info_stack);
  455. }
  456. /**
  457. * Will trigger a pass if the raw text is found on the loaded page
  458. * Fail otherwise.
  459. * @param string $raw Raw string to look for
  460. * @param string $message Message to display.
  461. * @return boolean True on pass
  462. * @access public
  463. */
  464. function assertWantedRaw($raw, $message = "%s") {
  465. return $this->assertExpectation(
  466. new TextExpectation($raw),
  467. $this->_browser->getContent(),
  468. $message);
  469. }
  470. /**
  471. * Will trigger a pass if the raw text is NOT found on the loaded page
  472. * Fail otherwise.
  473. * @param string $raw Raw string to look for
  474. * @param string $message Message to display.
  475. * @return boolean True on pass
  476. * @access public
  477. */
  478. function assertNoUnwantedRaw($raw, $message = "%s") {
  479. return $this->assertExpectation(
  480. new NoTextExpectation($raw),
  481. $this->_browser->getContent(),
  482. $message);
  483. }
  484. /* Taken from UnitTestCase */
  485. /**
  486. * Will be true if the value is null.
  487. * @param null $value Supposedly null value.
  488. * @param string $message Message to display.
  489. * @return boolean True on pass
  490. * @access public
  491. */
  492. function assertNull($value, $message = "%s") {
  493. $dumper = &new SimpleDumper();
  494. $message = sprintf(
  495. $message,
  496. "[" . $dumper->describeValue($value) . "] should be null");
  497. return $this->assertTrue(! isset($value), $message);
  498. }
  499. /**
  500. * Will be true if the value is set.
  501. * @param mixed $value Supposedly set value.
  502. * @param string $message Message to display.
  503. * @return boolean True on pass.
  504. * @access public
  505. */
  506. function assertNotNull($value, $message = "%s") {
  507. $dumper = &new SimpleDumper();
  508. $message = sprintf(
  509. $message,
  510. "[" . $dumper->describeValue($value) . "] should not be null");
  511. return $this->assertTrue(isset($value), $message);
  512. }
  513. /**
  514. * Type and class test. Will pass if class
  515. * matches the type name or is a subclass or
  516. * if not an object, but the type is correct.
  517. * @param mixed $object Object to test.
  518. * @param string $type Type name as string.
  519. * @param string $message Message to display.
  520. * @return boolean True on pass.
  521. * @access public
  522. */
  523. function assertIsA($object, $type, $message = "%s") {
  524. return $this->assertExpectation(
  525. new IsAExpectation($type),
  526. $object,
  527. $message);
  528. }
  529. /**
  530. * Type and class mismatch test. Will pass if class
  531. * name or underling type does not match the one
  532. * specified.
  533. * @param mixed $object Object to test.
  534. * @param string $type Type name as string.
  535. * @param string $message Message to display.
  536. * @return boolean True on pass.
  537. * @access public
  538. */
  539. function assertNotA($object, $type, $message = "%s") {
  540. return $this->assertExpectation(
  541. new NotAExpectation($type),
  542. $object,
  543. $message);
  544. }
  545. /**
  546. * Will trigger a pass if the two parameters have
  547. * the same value only. Otherwise a fail.
  548. * @param mixed $first Value to compare.
  549. * @param mixed $second Value to compare.
  550. * @param string $message Message to display.
  551. * @return boolean True on pass
  552. * @access public
  553. */
  554. function assertEqual($first, $second, $message = "%s") {
  555. return $this->assertExpectation(
  556. new EqualExpectation($first),
  557. $second,
  558. $message);
  559. }
  560. /**
  561. * Will trigger a pass if the two parameters have
  562. * a different value. Otherwise a fail.
  563. * @param mixed $first Value to compare.
  564. * @param mixed $second Value to compare.
  565. * @param string $message Message to display.
  566. * @return boolean True on pass
  567. * @access public
  568. */
  569. function assertNotEqual($first, $second, $message = "%s") {
  570. return $this->assertExpectation(
  571. new NotEqualExpectation($first),
  572. $second,
  573. $message);
  574. }
  575. /**
  576. * Will trigger a pass if the two parameters have
  577. * the same value and same type. Otherwise a fail.
  578. * @param mixed $first Value to compare.
  579. * @param mixed $second Value to compare.
  580. * @param string $message Message to display.
  581. * @return boolean True on pass
  582. * @access public
  583. */
  584. function assertIdentical($first, $second, $message = "%s") {
  585. return $this->assertExpectation(
  586. new IdenticalExpectation($first),
  587. $second,
  588. $message);
  589. }
  590. /**
  591. * Will trigger a pass if the two parameters have
  592. * the different value or different type.
  593. * @param mixed $first Value to compare.
  594. * @param mixed $second Value to compare.
  595. * @param string $message Message to display.
  596. * @return boolean True on pass
  597. * @access public
  598. */
  599. function assertNotIdentical($first, $second, $message = "%s") {
  600. return $this->assertExpectation(
  601. new NotIdenticalExpectation($first),
  602. $second,
  603. $message);
  604. }
  605. /**
  606. * Will trigger a pass if both parameters refer
  607. * to the same object. Fail otherwise.
  608. * @param mixed $first Object reference to check.
  609. * @param mixed $second Hopefully the same object.
  610. * @param string $message Message to display.
  611. * @return boolean True on pass
  612. * @access public
  613. */
  614. function assertReference(&$first, &$second, $message = "%s") {
  615. $dumper = &new SimpleDumper();
  616. $message = sprintf(
  617. $message,
  618. "[" . $dumper->describeValue($first) .
  619. "] and [" . $dumper->describeValue($second) .
  620. "] should reference the same object");
  621. return $this->assertTrue(
  622. SimpleTestCompatibility::isReference($first, $second),
  623. $message);
  624. }
  625. /**
  626. * Will trigger a pass if both parameters refer
  627. * to different objects. Fail otherwise.
  628. * @param mixed $first Object reference to check.
  629. * @param mixed $second Hopefully not the same object.
  630. * @param string $message Message to display.
  631. * @return boolean True on pass
  632. * @access public
  633. */
  634. function assertCopy(&$first, &$second, $message = "%s") {
  635. $dumper = &new SimpleDumper();
  636. $message = sprintf(
  637. $message,
  638. "[" . $dumper->describeValue($first) .
  639. "] and [" . $dumper->describeValue($second) .
  640. "] should not be the same object");
  641. return $this->assertFalse(
  642. SimpleTestCompatibility::isReference($first, $second),
  643. $message);
  644. }
  645. /**
  646. * Will trigger a pass if the Perl regex pattern
  647. * is found in the subject. Fail otherwise.
  648. * @param string $pattern Perl regex to look for including
  649. * the regex delimiters.
  650. * @param string $subject String to search in.
  651. * @param string $message Message to display.
  652. * @return boolean True on pass
  653. * @access public
  654. */
  655. function assertWantedPattern($pattern, $subject, $message = "%s") {
  656. return $this->assertExpectation(
  657. new WantedPatternExpectation($pattern),
  658. $subject,
  659. $message);
  660. }
  661. /**
  662. * Will trigger a pass if the Perl regex pattern
  663. * is not present in subject. Fail if found.
  664. * @param string $pattern Perl regex to look for including
  665. * the regex delimiters.
  666. * @param string $subject String to search in.
  667. * @param string $message Message to display.
  668. * @return boolean True on pass
  669. * @access public
  670. */
  671. function assertNoUnwantedPattern($pattern, $subject, $message = "%s") {
  672. return $this->assertExpectation(
  673. new UnwantedPatternExpectation($pattern),
  674. $subject,
  675. $message);
  676. }
  677. /**
  678. * Confirms that no errors have occurred so
  679. * far in the test method.
  680. * @param string $message Message to display.
  681. * @return boolean True on pass
  682. * @access public
  683. */
  684. function assertNoErrors($message = "%s") {
  685. $queue = &SimpleErrorQueue::instance();
  686. return $this->assertTrue(
  687. $queue->isEmpty(),
  688. sprintf($message, "Should be no errors"));
  689. }
  690. /**
  691. * Confirms that an error has occurred and
  692. * optionally that the error text matches exactly.
  693. * @param string $expected Expected error text or
  694. * false for no check.
  695. * @param string $message Message to display.
  696. * @return boolean True on pass
  697. * @access public
  698. */
  699. function assertError($expected = false, $message = "%s") {
  700. $queue = &SimpleErrorQueue::instance();
  701. if ($queue->isEmpty()) {
  702. $this->fail(sprintf($message, "Expected error not found"));
  703. return;
  704. }
  705. list($severity, $content, $file, $line, $globals) = $queue->extract();
  706. $severity = SimpleErrorQueue::getSeverityAsString($severity);
  707. return $this->assertTrue(
  708. ! $expected || ($expected == $content),
  709. "Expected [$expected] in PHP error [$content] severity [$severity] in [$file] line [$line]");
  710. }
  711. /**
  712. * Confirms that an error has occurred and
  713. * that the error text matches a Perl regular
  714. * expression.
  715. * @param string $pattern Perl regular expression to
  716. * match against.
  717. * @param string $message Message to display.
  718. * @return boolean True on pass
  719. * @access public
  720. */
  721. function assertErrorPattern($pattern, $message = "%s") {
  722. $queue = &SimpleErrorQueue::instance();
  723. if ($queue->isEmpty()) {
  724. $this->fail(sprintf($message, "Expected error not found"));
  725. return;
  726. }
  727. list($severity, $content, $file, $line, $globals) = $queue->extract();
  728. $severity = SimpleErrorQueue::getSeverityAsString($severity);
  729. return $this->assertTrue(
  730. (boolean)preg_match($pattern, $content),
  731. "Expected pattern match [$pattern] in PHP error [$content] severity [$severity] in [$file] line [$line]");
  732. }
  733. }
  734. ?>