assertTokens($type, $object, array($token => $expected), $options); } function assertTokens($type, $object, array $tokens, array $options = array()) { $values = token_get_values($type, $object, FALSE, $options); $values = array_combine($values->tokens, $values->values); foreach ($tokens as $token => $expected) { if (!isset($expected)) { $this->assertTrue(!isset($values[$token]), t("Token value for [@token] was not generated.", array('@token' => $token))); } elseif (!isset($values[$token])) { $this->fail(t("Token value for [@token] was not generated.", array('@token' => $token))); } else { $this->assertIdentical($values[$token], $expected, t("Token value for [@token] was '@actual', expected value '@expected'.", array('@token' => $token, '@actual' => $values[$token], '@expected' => $expected))); } } } /** * Make a page request and test for token generation. */ function assertPageTokens($url, array $tokens, array $data = array('global' => NULL), array $options = array()) { if (empty($tokens)) { return TRUE; } $token_page_tokens = array( 'tokens' => $tokens, 'data' => $data, 'options' => $options, ); variable_set('token_page_tokens', $token_page_tokens); $options += array('url_options' => array()); $this->drupalGet($url, $options['url_options']); $this->refreshVariables(); $result = variable_get('token_page_tokens', array()); if (!isset($result['values']) || !is_array($result['values'])) { return $this->fail('Failed to generate tokens.'); } foreach ($tokens as $token => $expected) { if (!isset($expected)) { $this->assertTrue(!isset($result['values'][$token]) || $result['values'][$token] === $token, t("Token value for @token was not generated.", array('@token' => $token))); } elseif (!isset($result['values'][$token])) { $this->fail(t('Failed to generate token @token.', array('@token' => $token))); } else { $this->assertIdentical($result['values'][$token], (string) $expected, t("Token value for @token was '@actual', expected value '@expected'.", array('@token' => $token, '@actual' => $result['values'][$token], '@expected' => $expected))); } } } } class TokenUnitTestCase extends TokenTestHelper { public static function getInfo() { return array( 'name' => 'Token unit tests', 'description' => 'Test basic, low-level token functions.', 'group' => 'Token', ); } /** * Test token_get_invalid_tokens() and token_get_invalid_tokens_by_context(). */ public function testGetInvalidTokens() { $tests = array(); $tests[] = array( 'valid tokens' => array( '[title-raw]', '[yyyy]', '[mod-yyyy]', '[site-name]', '[site-slogan]', '[user-id]', ), 'invalid tokens' => array( '[title-invalid]', '[invalid]', '[mod-invalid]', '[invalid-title]', '[site-invalid]', '[uid]', '[comment-cid]', ), 'types' => array('node'), ); $tests[] = array( 'valid tokens' => array( '[title-raw]', '[yyyy]', '[mod-yyyy]', '[site-name]', '[site-slogan]', '[user-id]', '[uid]', '[comment-cid]', ), 'invalid tokens' => array( '[title-invalid]', '[invalid]', '[mod-invalid]', '[invalid-title]', '[site-invalid]', ), 'types' => array('all'), ); $tests[] = array( 'valid tokens' => array( '[alpha]', '[beta-1]', '[beta-2]', '[gamma_A]', '[delta-extra]', '[epsilon-zeta-A]', ), 'invalid tokens' => array( '[alpha-plus]', '[beta]', '[beta-]', '[beta_]', '[beta_1]', '[beta-A]', '[gamma]', '[gamma_]', '[gamma-A]', '[delta]', '[epsilon-zeta-]', ), 'types' => array('all'), ); foreach ($tests as $test) { $tokens = array_merge($test['valid tokens'], $test['invalid tokens']); shuffle($tokens); $invalid_tokens = token_get_invalid_tokens_by_context(implode(' ', $tokens), $test['types']); sort($invalid_tokens); sort($test['invalid tokens']); $this->assertEqual($invalid_tokens, $test['invalid tokens'], 'Invalid tokens detected properly: ' . implode(', ', $invalid_tokens)); } } /** * Test the $options['clear'] parameter for token_replace(). */ public function testClearOption() { $tests[] = array( 'input' => 'Foo [site-name][invalid-token] bar [another-invalid-token] [invalid-token]', 'output' => 'Foo Drupal bar ', 'options' => array('clear' => TRUE), ); $tests[] = array( 'input' => 'Foo [site-name][invalid-token] bar [another-invalid-token] [invalid-token]', 'output' => 'Foo Drupal[invalid-token] bar [another-invalid-token] [invalid-token]', 'options' => array(), ); foreach ($tests as $test) { $output = token_replace($test['input'], 'global', NULL, TOKEN_PREFIX, TOKEN_SUFFIX, $test['options']); $this->assertIdentical($output, $test['output']); } } /** * Test whether token-replacement works in various contexts. * * @see http://drupal.org/node/733192 */ function testSystemTokenRecognition() { global $language; // Generate prefixes and suffixes for the token context. $tests = array( array('prefix' => 'this is the ', 'suffix' => ' site'), array('prefix' => 'this is the', 'suffix' => 'site'), array('prefix' => '[', 'suffix' => ']'), array('prefix' => '', 'suffix' => ']]]'), array('prefix' => '[[[', 'suffix' => ''), array('prefix' => ':[:', 'suffix' => '--]'), array('prefix' => '-[-', 'suffix' => ':]:'), array('prefix' => '[:', 'suffix' => ']'), array('prefix' => '[site:', 'suffix' => ':name]'), array('prefix' => '[site:', 'suffix' => ']'), ); // Check if the token is recognized in each of the contexts. foreach ($tests as $test) { $input = $test['prefix'] . '[site-name]' . $test['suffix']; $expected = $test['prefix'] . 'Drupal' . $test['suffix']; $output = token_replace($input); $this->assertEqual($output, $expected); } } /** * Test token caching. */ function testTokenCaching() { // Run global tokens once so that the cache is primed. $tokens = array( 'option-foo' => '', ); $this->assertTokens('global', NULL, $tokens); // Run global tokens again with different options. This should return a // different value for the [option-foo] token. $tokens = array( 'option-foo' => 'bar', ); $this->assertTokens('global', NULL, $tokens, array('foo' => 'bar')); } /** * Test the token_scan() function. */ function testTokenScan() { $tests = array( array('text' => 'Test [foo] [[bar]] test.', 'tokens' => array('foo', 'bar')), array('text' => 'Test [foo] [] test.', 'tokens' => array('foo')), array('text' => 'Test [foo][] test.', 'tokens' => array('foo')), array('text' => 'Test [foo][bar] test.', 'tokens' => array('foo', 'bar')), // Test the e-mail token syntax. array('text' => 'Test %foo %%bar test.', 'tokens' => array('foo', 'bar'), 'leading' => '%', 'trailing' => ''), array('text' => 'Test %foo % test.', 'tokens' => array('foo'), 'leading' => '%', 'trailing' => ''), array('text' => 'Test %foo% test.', 'tokens' => array('foo'), 'leading' => '%', 'trailing' => ''), array('text' => 'Test %foo%%bar test.', 'tokens' => array('foo', 'bar'), 'leading' => '%', 'trailing' => ''), // Test the rules token syntax. array('text' => 'Test [global:foo] [global:bar] test.', 'tokens' => array('foo', 'bar'), 'leading' => '[global:'), array('text' => 'Test [node:foo] [node:] test.', 'tokens' => array('foo'), 'leading' => '[node:'), array('text' => 'Test [node:foo][node:] test.', 'tokens' => array('foo'), 'leading' => '[node:'), array('text' => 'Test [node:foo][node:bar] test.', 'tokens' => array('foo', 'bar'), 'leading' => '[node:'), ); foreach ($tests as $test) { $test += array('leading' => TOKEN_PREFIX, 'trailing' => TOKEN_SUFFIX); $this->assertEqual(token_scan($test['text'], $test['leading'], $test['trailing']), $test['tokens']); } } } class TokenNodeTestCase extends TokenTestHelper { public static function getInfo() { return array( 'name' => 'Node token tests', 'description' => 'Test the node tokens.', 'group' => 'Token', ); } function testNodeTokens() { $time = time(); $created = gmmktime(0, 0, 0, 11, 19, 1978); $changed = gmmktime(0, 0, 0, 7, 4, 1984); $node = $this->drupalCreateNode(array( 'type' => 'page', 'language' => 'und', 'created' => $created, 'log' => '' . $this->randomName() . '', )); $node->changed = $changed; path_set_alias('node/' . $node->nid, 'content/first-node'); $tokens = array( 'nid' => $node->nid, 'type' => 'page', 'type-name' => 'Page', 'language' => 'und', 'node-path' => 'content/first-node', 'node-url' => url('node/' . $node->nid, array('absolute' => TRUE)), 'small' => '11/19/1978 - 00:00', 'yyyy' => '1978', 'yy' => '78', 'month' => 'November', 'mon' => 'Nov', 'mm' => '11', 'm' => '11', 'ww' => '46', 'date' => '7', 'day' => 'Sunday', 'ddd' => 'Sun', 'dd' => '19', 'd' => '19', 'raw' => 280281600, 'since' => format_interval($time - 280281600), 'mod-small' => '07/04/1984 - 00:00', 'mod-yyyy' => '1984', 'mod-yy' => '84', 'mod-month' => 'July', 'mod-mon' => 'Jul', 'mod-mm' => '07', 'mod-m' => '7', 'mod-ww' => '27', 'mod-date' => '3', 'mod-day' => 'Wednesday', 'mod-ddd' => 'Wed', 'mod-dd' => '04', 'mod-d' => '4', 'mod-raw' => 457747200, 'mod-since' => format_interval($time - 457747200), 'log' => filter_xss($node->log), 'log-raw' => $node->log, ); $this->assertTokens('node', $node, $tokens); // Check that a new revision of a node returns different tokens. $node->revision = TRUE; $node->title = 'New revision'; node_save($node); $this->assertTokens('node', $node, array('title' => 'New revision')); } } class TokenCommentTestCase extends TokenTestHelper { protected $node; public static function getInfo() { return array( 'name' => 'Comment token tests', 'description' => 'Test the comment tokens.', 'group' => 'Token', ); } function setUp(array $modules = array()) { $modules[] = 'comment'; parent::setUp($modules); $this->node = $this->drupalCreateNode(array('comment' => 2)); } function loadComment($cid) { return db_fetch_object(db_query('SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.signature, u.signature_format, u.picture, u.data, c.status FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d', $cid)); } function createComment(array $comment) { $comment += array( 'cid' => 0, 'nid' => $this->node->nid, 'pid' => 0, 'uid' => 0, 'subject' => $this->randomName(), 'comment' => $this->randomName(64), 'format' => 1, 'timestamp' => gmmktime(0, 0, 0, 7, 4, 1984), 'status' => COMMENT_PUBLISHED, ); $cid = comment_save($comment); return $this->loadComment($cid); } function testCommentTokens() { $time = time(); $comment = $this->createComment(array( 'timestamp' => gmmktime(0, 0, 0, 7, 4, 1984), )); $tokens = array( 'comment-cid' => $comment->cid, 'comment-nid' => $this->node->nid, 'comment-yyyy' => '1984', 'comment-yy' => '84', 'comment-month' => 'July', 'comment-mon' => 'Jul', 'comment-mm' => '07', 'comment-m' => '7', 'comment-ww' => '27', 'comment-date' => '3', 'comment-day' => 'Wednesday', 'comment-ddd' => 'Wed', 'comment-dd' => '04', 'comment-d' => '4', 'comment-raw' => '457747200', 'comment-since' => format_interval($time - 457747200), 'comment-node-title' => check_plain($this->node->title), 'comment-node-title-raw' => $this->node->title, ); $this->assertTokens('comment', $comment, $tokens); } } class TokenTaxonomyTestCase extends TokenTestHelper { protected $vocabulary; public static function getInfo() { return array( 'name' => 'Taxonomy and vocabulary token tests', 'description' => 'Test the taxonomy tokens.', 'group' => 'Token', ); } function setUp(array $modules = array()) { $modules[] = 'taxonomy'; parent::setUp($modules); // Reset the static taxonomy.module caches. taxonomy_vocabulary_load(0, TRUE); taxonomy_get_term(0, TRUE); } function addVocabulary(array $vocabulary = array()) { $vocabulary += array( 'name' => drupal_strtolower($this->randomName(5)), 'nodes' => array('story' => 'story'), ); taxonomy_save_vocabulary($vocabulary); return (object) $vocabulary; } function addTerm(stdClass $vocabulary, array $term = array()) { $term += array( 'name' => drupal_strtolower($this->randomName(5)), 'vid' => $vocabulary->vid, ); taxonomy_save_term($term); return (object) $term; } function testTaxonomyTokens() { $vocabulary = $this->addVocabulary(array( 'name' => 'Vocab Name', 'description' => 'Vocab Description', )); $term = $this->addTerm($vocabulary, array( 'name' => 'Term Name', 'description' => 'Term Description', )); $tokens = array( 'tid' => $term->tid, 'cat' => check_plain($term->name), 'cat-raw' => $term->name, 'cat-description' => 'Term Description', 'vid' => $vocabulary->vid, 'vocab' => check_plain($vocabulary->name), 'vocab-raw' => $vocabulary->name, 'vocab-description' => 'Vocab Description', 'vocab-description-raw' => $vocabulary->description, ); $this->assertTokens('taxonomy', $term, $tokens); $tokens = array( 'vocabulary-vid' => $vocabulary->vid, 'vocabulary-name' => check_plain($vocabulary->name), 'vocabulary-name-raw' => $vocabulary->name, 'vocabulary-description' => 'Vocab Description', 'vocabulary-description-raw' => $vocabulary->description, ); $this->assertTokens('vocabulary', $vocabulary, $tokens); } } class TokenMenuTestCase extends TokenTestHelper { public static function getInfo() { return array( 'name' => 'Menu token tests', 'description' => 'Test the menu tokens.', 'group' => 'Token', ); } function setUp(array $modules = array()) { $modules[] = 'menu'; parent::setUp($modules); } function testMenuTokens() { $root_link = array( 'link_path' => 'root', 'link_title' => 'Root link', 'menu_name' => 'primary-links', ); menu_link_save($root_link); // Add another link with the root link as the parent $parent_link = array( 'link_path' => 'root/parent', 'link_title' => 'Parent link', 'menu_name' => 'primary-links', 'plid' => $root_link['mlid'], ); menu_link_save($parent_link); $node_link = array( 'enabled' => TRUE, 'link_title' => 'Node link', 'plid' => $parent_link['mlid'], 'customized' => 0, ); $node = $this->drupalCreateNode(array('menu' => $node_link)); // Test [node:menu] tokens. $tokens = array( 'menu' => 'Primary links', 'menu-raw' => 'Primary links', 'menupath' => 'Root link/Parent link/Node link', 'menupath-raw' => 'Root link/Parent link/Node link', 'menu-link-title' => 'Node link', 'menu-link-title-raw' => 'Node link', 'menu-link-mlid' => $node->menu['mlid'], 'menu-link-plid' => $node->menu['plid'], 'menu-link-plid' => $parent_link['mlid'], 'menu-link-parent-path' => 'root/parent', 'menu-link-parent-path-raw' => 'root/parent', ); $this->assertTokens('node', $node, $tokens); // Reload the node which will not have $node->menu defined and re-test. $loaded_node = node_load($node->nid); // We have to reset the token static cache because tokens are cached by // node ID only and not if the node object has changed. $this->assertTokens('node', $loaded_node, $tokens, array('reset' => TRUE)); // Regression test for http://drupal.org/node/1317926 to ensure the // original node object is not changed when calling menu_node_prepare(). $this->assertTrue(!isset($loaded_node->menu), t('The $node->menu property was not modified during token replacement.'), 'Regression'); } } /* * Unit tests for the book tokens provided by Pathauto. */ class TokenBookTestCase extends TokenTestHelper { public static function getInfo() { return array( 'name' => 'Book tokens', 'description' => 'Tests the book tokens.', 'group' => 'Token', ); } function setUp(array $modules = array()) { $modules[] = 'book'; $modules[] = 'menu'; parent::setUp($modules); variable_set('book_allowed_types', array('book', 'page')); } function testBookTokens() { // Add a non-book node. $non_book_node = $this->drupalCreateNode(array('type' => 'book')); $tokens = array( 'book' => '', 'book-raw' => '', 'book_id' => '', 'bookpath' => '', 'bookpath-raw' => '', ); $this->assertTokens('node', $non_book_node, $tokens); // Add a root book page. $parent_node = $this->drupalCreateNode(array( 'type' => 'book', 'title' => 'Root', 'book' => array('bid' => 'new') + _book_link_defaults('new'), )); $tokens = array( 'book' => 'Root', 'book-raw' => 'Root', 'book_id' => $parent_node->book['bid'], 'bookpath' => '', 'bookpath-raw' => '', // Check that even those book menu links have been created for this node, // that the menu links still return nothing. 'menu' => '', 'menupath' => '', 'menu-link-title' => '', 'menu-link-title-raw' => '', 'menu-link-mlid' => '', 'menu-link-plid' => '', 'menu-link-parent-path' => '', ); $this->assertTokens('node', $parent_node, $tokens); // Add a first child page. $child_node1 = $this->drupalCreateNode(array( 'type' => 'book', 'title' => 'Sub page1', 'book' => array( 'bid' => $parent_node->book['bid'], 'plid' => $parent_node->book['mlid'], ) + _book_link_defaults('new'), )); $tokens = array( 'book' => 'Root', 'book-raw' => 'Root', 'book_id' => $parent_node->book['bid'], 'bookpath' => 'Root', 'bookpath-raw' => 'Root', ); $this->assertTokens('node', $child_node1, $tokens); // Add a second child page. $child_node2 = $this->drupalCreateNode(array( 'type' => 'book', 'title' => 'Sub page2', 'book' => array( 'bid' => $parent_node->book['bid'], 'plid' => $parent_node->book['mlid'], ) + _book_link_defaults('new'), )); $tokens = array( 'book' => 'Root', 'book-raw' => 'Root', 'book_id' => $parent_node->book['bid'], 'bookpath' => 'Root', 'bookpath-raw' => 'Root', ); $this->assertTokens('node', $child_node2, $tokens); // Add a child page on an existing child page. $sub_child_node1 = $this->drupalCreateNode(array( 'type' => 'page', 'title' => 'Sub-sub Page1', 'book' => array( 'bid' => $parent_node->book['bid'], 'plid' => $child_node1->book['mlid'], ) + _book_link_defaults('new'), )); $tokens = array( 'book' => 'Root', 'book-raw' => 'Root', 'book_id' => $parent_node->book['bid'], 'bookpath' => 'Root/Sub page1', 'bookpath-raw' => 'Root/Sub page1', ); $this->assertTokens('node', $sub_child_node1, $tokens); } } /** * Test the current page tokens. */ class TokenCurrentPageTestCase extends TokenTestHelper { public static function getInfo() { return array( 'name' => 'Current page token tests', 'description' => 'Test the current page tokens.', 'group' => 'Token', ); } function testCurrentPageTokens() { $tokens = array( '[current-page-title]' => '', '[current-page-path]' => 'node', '[current-page-url]' => url('node', array('absolute' => TRUE)), '[current-page-number]' => 1, ); $this->assertPageTokens('', $tokens); $node = $this->drupalCreateNode(array('title' => 'Node title', 'path' => 'node-alias')); $tokens = array( '[current-page-title]' => 'Node title', '[current-page-path]' => 'node-alias', '[current-page-url]' => url("node/{$node->nid}", array('absolute' => TRUE)), '[current-page-number]' => 1, ); $this->assertPageTokens("node/{$node->nid}", $tokens); } }