metatag.node.test 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. <?php
  2. /**
  3. * @file
  4. * Tests for the Metatag module and node entities.
  5. */
  6. /**
  7. * Tests for the Metatag module and node entities.
  8. */
  9. class MetatagCoreNodeTest extends MetatagTestHelper {
  10. /**
  11. * {@inheritdoc}
  12. */
  13. public static function getInfo() {
  14. return array(
  15. 'name' => 'Metatag core tests for nodes',
  16. 'description' => 'Test Metatag edit functionality for nodes.',
  17. 'group' => 'Metatag',
  18. 'dependencies' => array('ctools', 'token'),
  19. );
  20. }
  21. /**
  22. * Tests creation of a standard entity.
  23. */
  24. public function testEntityCreationWorkflow() {
  25. $content_type = 'metatag_test';
  26. $content_type_path = str_replace('_', '-', $content_type);
  27. $label = 'Test';
  28. // Create a content type.
  29. $this->createContentType($content_type, $label);
  30. // Create an admin user and log them in.
  31. $perms = array(
  32. // Needed for the content type.
  33. 'create ' . $content_type . ' content',
  34. 'delete any ' . $content_type . ' content',
  35. 'edit any ' . $content_type . ' content',
  36. // Used later for revision handling.
  37. 'view revisions',
  38. 'revert revisions',
  39. 'delete revisions',
  40. // This permission is required in order to create new revisions.
  41. 'administer nodes',
  42. );
  43. $this->adminUser = $this->createAdminUser($perms);
  44. // Log in the admin user.
  45. $this->drupalLogin($this->adminUser);
  46. // Assign default values for the new content type.
  47. // Load the "add default configuration" page.
  48. $this->drupalGet('admin/config/search/metatags/config/add');
  49. $this->assertResponse(200);
  50. // Verify the page loaded correct.
  51. $this->assertText(t('Select the type of default meta tags you would like to add.'));
  52. // Submit the initial form to select an entity bundle.
  53. $this->drupalPost(NULL, array(
  54. 'instance' => 'node:' . $content_type,
  55. ), t('Add and configure'));
  56. $this->assertResponse(200);
  57. // Verify the page loaded correct.
  58. $this->assertText('Node: ' . $label);
  59. // Submit the form with some values.
  60. $this->drupalPost(NULL, array(
  61. 'metatags[und][abstract][value]' => '[node:title]',
  62. ), t('Save'));
  63. $this->assertResponse(200);
  64. // Verify the page loaded correct.
  65. $this->assertText(strip_tags(t('The meta tag defaults for @label have been saved.', array('@label' => 'Node: ' . $label))));
  66. // Verify that the user was redirected to the settings page again.
  67. $this->assertEqual($this->getUrl(), url('admin/config/search/metatags', array('absolute' => TRUE)));
  68. // Create a test node.
  69. // Load the node form.
  70. $this->drupalGet('node/add/' . $content_type_path);
  71. $this->assertResponse(200);
  72. // Verify the page loaded correctly.
  73. // @todo Update this to extract the page title.
  74. $this->assertText(strip_tags(t('Create @name', array('@name' => $label))));
  75. // Verify that it's possible to submit values to the form.
  76. module_load_include('inc', 'devel_generate');
  77. $body = devel_create_para(200);
  78. $this->drupalPost(NULL, array(
  79. 'metatags[und][abstract][value]' => '[node:title] ponies',
  80. 'title' => 'Who likes magic',
  81. 'body[und][0][value]' => $body,
  82. ), t('Save'));
  83. $this->assertResponse(200);
  84. // The meta tags that will be checked for.
  85. $expected = array(
  86. 'und' => array(
  87. 'abstract' => array(
  88. 'value' => '[node:title] ponies',
  89. ),
  90. ),
  91. );
  92. // Verify that the node saved correctly.
  93. // $xpath = $this->xpath("//h1");
  94. $t_args = array('@type' => 'Test', '%title' => 'Who likes magic');
  95. // This doesn't work for some reason, it seems the HTML is stripped off
  96. // during output so the %title's standard Drupal wrappers don't match.
  97. // $this->assertText(t('@type %title has been created.', $t_args));
  98. // .. so this has to be done instead.
  99. $this->assertText(strip_tags(t('@type %title has been created.', $t_args)));
  100. // Verify the node data saved correctly.
  101. $matches = array();
  102. $nid = 0;
  103. if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) {
  104. $nid = end($matches);
  105. $node = node_load($nid);
  106. $this->verbose($node, 'node_load(' . $nid . ')');
  107. // Only the non-default values are stored.
  108. $this->assertEqual($expected, $node->metatags);
  109. // Confirm the APIs can load the data for this node.
  110. $metatags = metatag_metatags_load('node', $node->nid);
  111. $this->verbose($metatags, 'metatag_metatags_load("node", ' . $node->nid . ')');
  112. $this->assertEqual($expected, $metatags);
  113. $metatags = metatag_metatags_load_multiple('node', array($node->nid));
  114. $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $node->nid . '))');
  115. $this->assertEqual(array($node->nid => array($node->vid => $expected)), $metatags);
  116. // Confirm the APIs can load the data for this node revision.
  117. $metatags = metatag_metatags_load('node', $node->nid, $node->vid);
  118. $this->verbose($metatags, 'metatag_metatags_load("node", ' . $node->nid . ', ' . $node->vid . ')');
  119. $this->assertEqual($expected, $metatags);
  120. $metatags = metatag_metatags_load_multiple('node', array($node->nid), array($node->vid));
  121. $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $node->nid . '), array(' . $node->vid . '))');
  122. $this->assertEqual(array($node->nid => array($node->vid => $expected)), $metatags);
  123. }
  124. // This shouldn't happen, it indicates a problem.
  125. else {
  126. $this->fail(t('Could not determine the ID for the created node.'));
  127. }
  128. // Verify the title is using the custom default for this content type.
  129. $xpath = $this->xpath("//meta[@name='abstract']");
  130. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  131. $this->assertEqual($xpath[0]['content'], 'Who likes magic ponies');
  132. // Verify the node summary is being used correctly.
  133. $xpath = $this->xpath("//meta[@name='description']");
  134. $this->assertEqual(count($xpath), 1);
  135. $this->assertEqual($xpath[0]['content'], DrupalDefaultMetaTag::text_summary($body, 380));
  136. // Verify the maxlength functionality is working correctly.
  137. $maxlength = 10;
  138. variable_set('metatag_maxlength_description', $maxlength);
  139. metatag_config_cache_clear();
  140. $this->drupalGet('node/' . $nid);
  141. $xpath = $this->xpath("//meta[@name='description']");
  142. $this->assertEqual(count($xpath), 1);
  143. $this->assertEqual($xpath[0]['content'], trim(substr($xpath[0]['content'], 0, $maxlength)));
  144. // Delete the variable so it goes back to the default.
  145. variable_del('metatag_maxlength_description');
  146. metatag_config_cache_clear();
  147. // Core's canonical tag is a relative URL, whereas Metatag outputs an
  148. // absolute URL.
  149. $old_canonical = url('node/' . $node->nid);
  150. $new_canonical = url('node/' . $node->nid, array('absolute' => TRUE));
  151. // Confirm that the canonical tag is in the correct format.
  152. $xpath = $this->xpath("//link[@rel='canonical']");
  153. $this->assertEqual(count($xpath), 1, 'Exactly one canonical meta tag found.');
  154. $this->assertEqual($xpath[0]['href'], $new_canonical);
  155. $this->assertNotEqual($xpath[0]['href'], $old_canonical);
  156. // Try loading the node revisions page.
  157. $this->drupalGet('node/' . $node->nid . '/revisions');
  158. // Verify the page did not load correctly. This is because the revisions
  159. // page can't be loaded if there's only one revision.
  160. $this->assertResponse(403);
  161. // Try creating a revision of the node.
  162. $old_title = $node->title;
  163. $old_vid = $node->vid;
  164. $new_title = 'Who still likes magic';
  165. // Load the node-edit page.
  166. $this->drupalGet('node/' . $node->nid . '/edit');
  167. // Verify the page loaded correctly.
  168. $this->assertResponse(200);
  169. // Try submitting text to the page.
  170. $args = array(
  171. 'metatags[und][abstract][value]' => '[node:title] kittens',
  172. 'title' => $new_title,
  173. 'revision' => 1,
  174. 'log' => 'Creating a new revision',
  175. );
  176. $this->drupalPost(NULL, $args, t('Save'));
  177. // Verify the page submission loaded correctly.
  178. $this->assertResponse(200);
  179. // A new version of the expected results.
  180. $expected_updated = array(
  181. 'und' => array(
  182. 'abstract' => array(
  183. 'value' => '[node:title] kittens',
  184. ),
  185. ),
  186. );
  187. // Verify that the node saved correctly.
  188. // $xpath = $this->xpath("//h1");
  189. $t_args = array('@type' => 'Test', '%title' => $new_title);
  190. // This doesn't work for some reason, it seems the HTML is stripped off
  191. // during output so the %title's standard Drupal wrappers don't match.
  192. // $this->assertText(t('@type %title has been updated.', $t_args));
  193. // .. so this has to be done instead.
  194. $this->assertText(strip_tags(t('@type %title has been updated.', $t_args)));
  195. // Verify the title is still using the custom default for this content type.
  196. $xpath = $this->xpath("//meta[@name='abstract']");
  197. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  198. $this->assertNotEqual($xpath[0]['content'], $old_title . ' ponies', 'Did not find the new abstract meta tag.');
  199. $this->assertEqual($xpath[0]['content'], $new_title . ' kittens', 'Found the old abstract meta tag.');
  200. // Load the node revisions page.
  201. $this->drupalGet('node/' . $node->nid . '/revisions');
  202. // Verify the page loaded correctly.
  203. $this->assertResponse(200, 'Loaded the revisions page for this node.');
  204. // Confirm there are two revisions.
  205. $xpath = $this->xpath("//body//div[@class='content']//table//tbody//tr");
  206. $this->assertEqual(count($xpath), 2, 'There are two revisions of this node.');
  207. // Load the previous revision.
  208. $this->drupalGet('node/' . $node->nid . '/revisions/' . $old_vid . '/view');
  209. // Verify the page loaded correctly.
  210. $this->assertResponse(200, 'Loaded the original revision of this node.');
  211. $xpath = $this->xpath("//meta[@name='abstract']");
  212. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  213. $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.');
  214. $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag.');
  215. // Load the updated node; force-load it to make sure it's loaded properly.
  216. $updated_node = node_load($node->nid, NULL, TRUE);
  217. $updated_vid = $updated_node->vid;
  218. $this->verbose($updated_node, 'node_load(' . $node->nid . ', NULL, TRUE)');
  219. // Confirm the APIs can load the data for this node.
  220. $metatags = metatag_metatags_load('node', $updated_node->nid);
  221. $this->verbose($metatags, 'metatag_metatags_load("node", ' . $updated_node->nid . ')');
  222. $this->assertEqual($expected_updated, $metatags);
  223. $this->assertNotEqual($expected, $metatags);
  224. // This one is complicated. If only the entity id is passed in it will load
  225. // the {metatag} records for *all* of the entity's revisions.
  226. $metatags = metatag_metatags_load_multiple('node', array($updated_node->nid));
  227. $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $updated_node->nid . '))');
  228. $this->assertEqual(array($updated_node->nid => array($node->vid => $expected, $updated_node->vid => $expected_updated)), $metatags);
  229. // Confirm the APIs can load the data for this node revision.
  230. $metatags = metatag_metatags_load('node', $updated_node->nid, $updated_vid);
  231. $this->verbose($metatags, 'metatag_metatags_load("node", ' . $updated_node->nid . ', ' . $updated_node->vid . ')');
  232. $this->assertEqual($expected_updated, $metatags);
  233. $this->assertNotEqual($expected, $metatags);
  234. $metatags = metatag_metatags_load_multiple('node', array($updated_node->nid), array($updated_node->vid));
  235. $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $updated_node->nid . '), array(' . $updated_node->vid . '))');
  236. $this->assertEqual(array($updated_node->nid => array($updated_node->vid => $expected_updated)), $metatags);
  237. // Load the current revision again.
  238. $this->drupalGet('node/' . $node->nid);
  239. $this->assertResponse(200, 'Loaded the current revision of this node.');
  240. $xpath = $this->xpath("//meta[@name='abstract']");
  241. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  242. $this->assertNotEqual($xpath[0]['content'], $old_title . ' ponies', 'Did not find the old abstract meta tag.');
  243. $this->assertEqual($xpath[0]['content'], $new_title . ' kittens', 'Found the new abstract meta tag.');
  244. // Revert to the original revision.
  245. $this->drupalGet('node/' . $node->nid . '/revisions/' . $old_vid . '/revert');
  246. // Verify the page loaded correctly.
  247. $this->assertResponse(200, 'Loaded the form to revert to the original revision of this node.');
  248. // Try submitting the form.
  249. $this->drupalPost(NULL, array(), t('Revert'));
  250. // Verify the page submission loaded correctly.
  251. $this->assertResponse(200);
  252. // Confirm there are now three revisions.
  253. $xpath = $this->xpath("//body//div[@class='content']//table//tbody//tr");
  254. $this->assertEqual(count($xpath), 3, 'There are now three revisions of this node.');
  255. // Load the current revision, which will now have the old meta tags.
  256. $this->drupalGet('node/' . $node->nid);
  257. $this->assertResponse(200, 'Loaded the current revision of this node.');
  258. $xpath = $this->xpath("//meta[@name='abstract']");
  259. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  260. $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.');
  261. $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag again.');
  262. // Delete the original revision.
  263. $this->drupalGet('node/' . $node->nid . '/revisions/' . $old_vid . '/delete');
  264. // Verify the page loaded correctly.
  265. $this->assertResponse(200, 'Loaded the form to delete the original revision of this node.');
  266. // Try submitting the form.
  267. $this->drupalPost(NULL, array(), t('Delete'));
  268. // Verify the page submission loaded correctly.
  269. $this->assertResponse(200);
  270. // Confirm there are now two revisions again.
  271. $xpath = $this->xpath("//body//div[@class='content']//table//tbody//tr");
  272. $this->assertEqual(count($xpath), 2, 'There are two revisions of this node again.');
  273. // Clear the caches and then load the current revision, just to confirm
  274. // that the page is still loading correctly.
  275. metatag_config_cache_clear();
  276. $this->drupalGet('node/' . $node->nid);
  277. $this->assertResponse(200, 'Loaded the current revision of this node again.');
  278. $xpath = $this->xpath("//meta[@name='abstract']");
  279. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  280. $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.');
  281. $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag again.');
  282. // Delete the second revision.
  283. $this->drupalGet('node/' . $node->nid . '/revisions/' . $updated_vid . '/delete');
  284. // Verify the page loaded correctly.
  285. $this->assertResponse(200, 'Loaded the form to delete the second revision of this node.');
  286. // Try submitting the form.
  287. $this->drupalPost(NULL, array(), t('Delete'));
  288. $this->assertResponse(200);
  289. // Verify that the revisions page no longer loads because there's only one
  290. // revision now.
  291. $this->drupalGet('node/' . $node->nid . '/revisions');
  292. $this->assertResponse(403, 'No longer able to load the node revisions page.');
  293. // Clear the caches and then load the current revision, just to confirm
  294. // that the page is still loading correctly.
  295. metatag_config_cache_clear();
  296. $this->drupalGet('node/' . $node->nid);
  297. $this->assertResponse(200, 'Loaded the current revision of this node again.');
  298. $xpath = $this->xpath("//meta[@name='abstract']");
  299. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  300. $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.');
  301. $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag again.');
  302. }
  303. /**
  304. * Tests different 'preview' options. #1: Disabled.
  305. */
  306. public function testNodePreviewOption0() {
  307. $this->checkNodePreviewOption(0);
  308. }
  309. /**
  310. * Tests different 'preview' options. #2: Optional, without preview.
  311. */
  312. public function testNodePreviewOption1NoPreview() {
  313. $this->checkNodePreviewOption(1, FALSE);
  314. }
  315. /**
  316. * Tests different 'preview' options. #2: Optional, with preview.
  317. */
  318. public function testNodePreviewOption1Preview() {
  319. $this->checkNodePreviewOption(1, TRUE);
  320. }
  321. /**
  322. * Tests different 'preview' options. #3: Preview required.
  323. */
  324. public function testNodePreviewOption2() {
  325. $this->checkNodePreviewOption(2);
  326. }
  327. /**
  328. * Change the node preview option at the content type level, confirm meta tags
  329. * still save correctly.
  330. *
  331. * @param int $option
  332. * A suitable value for the 'node_preview' option for a content type, must
  333. * be either 0, 1 or 2.
  334. * @param bool $preview
  335. * Whether to perform a preview. Has the following implications:
  336. * - if $option === 0, $preview is ignored, no preview is performed.
  337. * - if $option === 1, $preview is considered, a preview may be performed.
  338. * - if $option === 2, $preview is ignored, a preview is performed.
  339. */
  340. function checkNodePreviewOption($option, $preview = FALSE) {
  341. $content_type = 'article';
  342. $label = 'Test';
  343. // Create an admin user and log them in.
  344. $perms = array(
  345. // Needed for the content type.
  346. 'create ' . $content_type . ' content',
  347. 'edit any ' . $content_type . ' content',
  348. // Required for customizing the node preview option.
  349. 'administer content types',
  350. );
  351. $this->adminUser = $this->createAdminUser($perms);
  352. // Log in the admin user.
  353. $this->drupalLogin($this->adminUser);
  354. // Set the node preview mode.
  355. $this->drupalGet('admin/structure/types/manage/' . $content_type);
  356. $this->assertResponse(200);
  357. $edit = array(
  358. 'node_preview' => $option,
  359. );
  360. $this->drupalPost(NULL, $edit, t('Save content type'));
  361. $this->assertText(strip_tags(t('The content type %name has been updated.', array('%name' => t('Article')))));
  362. // Create a test node.
  363. $this->drupalGet('node/add/' . $content_type);
  364. $this->assertResponse(200);
  365. // Save a custom meta tag.
  366. $edit = array(
  367. 'metatags[und][abstract][value]' => '[node:title] ponies',
  368. 'title' => 'Who likes magic',
  369. );
  370. // A preview may be optionally performed. Core allows three combinations:
  371. // * 0 = Disallowed.
  372. // * 1 = Optional.
  373. // * 2 = Required.
  374. if (($option === 1 && $preview) || $option === 2) {
  375. $this->drupalPost(NULL, $edit, t('Preview'));
  376. $this->drupalPost(NULL, array(), t('Save'));
  377. }
  378. else {
  379. $this->drupalPost(NULL, $edit, t('Save'));
  380. }
  381. $this->assertResponse(200);
  382. // Verify the title is using the custom default for this content type.
  383. $xpath = $this->xpath("//meta[@name='abstract']");
  384. $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.');
  385. $this->assertEqual($xpath[0]['content'], 'Who likes magic ponies');
  386. }
  387. }