SimplesitemapTest.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. <?php
  2. namespace Drupal\Tests\simple_sitemap\Functional;
  3. use Drupal\Core\Url;
  4. /**
  5. * Tests Simple XML sitemap functional integration.
  6. *
  7. * @group simple_sitemap
  8. */
  9. class SimplesitemapTest extends SimplesitemapTestBase {
  10. /**
  11. * Verify sitemap.xml has the link to the front page after first generation.
  12. *
  13. * @throws \Drupal\Component\Plugin\Exception\PluginException
  14. * @throws \Behat\Mink\Exception\ExpectationException
  15. */
  16. public function testInitialGeneration() {
  17. $this->generator->generateSitemap('backend');
  18. $this->drupalGet($this->defaultSitemapUrl);
  19. $this->assertSession()->responseContains('urlset');
  20. $this->assertSession()->responseContains(
  21. Url::fromRoute('<front>')->setAbsolute()->toString()
  22. );
  23. $this->assertSession()->responseContains('1.0');
  24. $this->assertSession()->responseContains('daily');
  25. }
  26. /**
  27. * Test custom link.
  28. *
  29. * @throws \Drupal\Component\Plugin\Exception\PluginException
  30. * @throws \Behat\Mink\Exception\ExpectationException
  31. */
  32. public function testAddCustomLink() {
  33. $this->generator->addCustomLink(
  34. '/node/' . $this->node->id(),
  35. ['priority' => 0.2, 'changefreq' => 'monthly']
  36. )->generateSitemap('backend');
  37. $this->drupalGet($this->defaultSitemapUrl);
  38. $this->assertSession()->responseContains('node/' . $this->node->id());
  39. $this->assertSession()->responseContains('0.2');
  40. $this->assertSession()->responseContains('monthly');
  41. $this->drupalLogin($this->privilegedUser);
  42. $this->drupalGet('admin/config/search/simplesitemap/custom');
  43. $this->assertSession()->pageTextContains(
  44. '/node/' . $this->node->id() . ' 0.2 monthly'
  45. );
  46. $this->generator->addCustomLink(
  47. '/node/' . $this->node->id(),
  48. ['changefreq' => 'yearly']
  49. )->generateSitemap('backend');
  50. $this->drupalGet('admin/config/search/simplesitemap/custom');
  51. $this->assertSession()->pageTextContains(
  52. '/node/' . $this->node->id() . ' yearly'
  53. );
  54. }
  55. /**
  56. * Test default settings of custom links.
  57. *
  58. * @throws \Drupal\Component\Plugin\Exception\PluginException
  59. * @throws \Behat\Mink\Exception\ExpectationException
  60. */
  61. public function testAddCustomLinkDefaults() {
  62. $this->generator->removeCustomLinks()
  63. ->addCustomLink('/node/' . $this->node->id())
  64. ->generateSitemap('backend');
  65. $this->drupalGet($this->defaultSitemapUrl);
  66. $this->assertSession()->responseContains('node/' . $this->node->id());
  67. $this->assertSession()->responseContains('0.5');
  68. $this->assertSession()->responseNotContains('changefreq');
  69. }
  70. /**
  71. * Test removing custom paths from the sitemap settings.
  72. *
  73. * @throws \Drupal\Component\Plugin\Exception\PluginException
  74. * @throws \Behat\Mink\Exception\ExpectationException
  75. */
  76. public function testRemoveCustomLinks() {
  77. // Test removing one custom path from the sitemap.
  78. $this->generator->addCustomLink('/node/' . $this->node->id())
  79. ->removeCustomLinks('/node/' . $this->node->id())
  80. ->generateSitemap('backend');
  81. $this->drupalGet($this->defaultSitemapUrl);
  82. $this->assertSession()->responseNotContains('node/' . $this->node->id());
  83. //todo Not working
  84. // // Test removing all custom paths from the sitemap.
  85. // $this->generator->removeCustomLinks()
  86. // ->generateSitemap('backend');
  87. //
  88. // $this->drupalGet($this->defaultSitemapUrl);
  89. // $this->assertSession()->responseNotContains(
  90. // Url::fromRoute('<front>')->setAbsolute()->toString()
  91. // );
  92. }
  93. /**
  94. * Tests setting bundle settings.
  95. *
  96. * @throws \Drupal\Component\Plugin\Exception\PluginException
  97. * @throws \Behat\Mink\Exception\ExpectationException
  98. *
  99. * @todo Add form tests
  100. */
  101. public function testSetBundleSettings() {
  102. $this->assertFalse($this->generator->bundleIsIndexed('node', 'page'));
  103. // Index new bundle.
  104. $this->generator->removeCustomLinks()
  105. ->setBundleSettings('node', 'page', [
  106. 'index' => TRUE,
  107. 'priority' => 0.5,
  108. 'changefreq' => 'hourly',
  109. ])
  110. ->generateSitemap('backend');
  111. $this->drupalGet($this->defaultSitemapUrl);
  112. $this->assertSession()->responseContains('node/' . $this->node->id());
  113. $this->assertSession()->responseContains('0.5');
  114. $this->assertSession()->responseContains('hourly');
  115. $this->assertTrue($this->generator->bundleIsIndexed('node', 'page'));
  116. // Only change bundle priority.
  117. $this->generator->setBundleSettings('node', 'page', ['priority' => 0.9])
  118. ->generateSitemap('backend');
  119. $this->drupalGet($this->defaultSitemapUrl);
  120. $this->assertSession()->responseContains('node/' . $this->node->id());
  121. $this->assertSession()->responseNotContains('0.5');
  122. $this->assertSession()->responseContains('0.9');
  123. // Only change bundle changefreq.
  124. $this->generator->setBundleSettings(
  125. 'node',
  126. 'page',
  127. ['changefreq' => 'daily']
  128. )->generateSitemap('backend');
  129. $this->drupalGet($this->defaultSitemapUrl);
  130. $this->assertSession()->responseContains('node/' . $this->node->id());
  131. $this->assertSession()->responseNotContains('hourly');
  132. $this->assertSession()->responseContains('daily');
  133. // Remove changefreq setting.
  134. $this->generator->setBundleSettings('node', 'page', ['changefreq' => ''])
  135. ->generateSitemap('backend');
  136. $this->drupalGet($this->defaultSitemapUrl);
  137. $this->assertSession()->responseContains('node/' . $this->node->id());
  138. $this->assertSession()->responseNotContains('changefreq');
  139. $this->assertSession()->responseNotContains('daily');
  140. // Index two bundles.
  141. $this->drupalCreateContentType(['type' => 'blog']);
  142. $node3 = $this->createNode(['title' => 'Node3', 'type' => 'blog']);
  143. $this->generator->setBundleSettings('node', 'page', ['index' => TRUE])
  144. ->setBundleSettings('node', 'blog', ['index' => TRUE])
  145. ->generateSitemap('backend');
  146. $this->drupalGet($this->defaultSitemapUrl);
  147. $this->assertSession()->responseContains('node/' . $this->node->id());
  148. $this->assertSession()->responseContains('node/' . $node3->id());
  149. // todo Now working
  150. // // Set bundle 'index' setting to false.
  151. // $this->generator
  152. // ->setBundleSettings('node', 'page', ['index' => FALSE])
  153. // ->setBundleSettings('node', 'blog', ['index' => FALSE])
  154. // ->generateSitemap('backend');
  155. //
  156. // $this->drupalGet($this->defaultSitemapUrl);
  157. //
  158. // $this->assertSession()->responseNotContains('node/' . $this->node->id());
  159. // $this->assertSession()->responseNotContains('node/' . $node3->id());
  160. }
  161. /**
  162. * Test default settings of bundles.
  163. *
  164. * @throws \Drupal\Component\Plugin\Exception\PluginException
  165. * @throws \Behat\Mink\Exception\ExpectationException
  166. */
  167. public function testSetBundleSettingsDefaults() {
  168. $this->generator->setBundleSettings('node', 'page')
  169. ->removeCustomLinks()
  170. ->generateSitemap('backend');
  171. $this->drupalGet($this->defaultSitemapUrl);
  172. $this->assertSession()->responseContains('node/' . $this->node->id());
  173. $this->assertSession()->responseContains('0.5');
  174. $this->assertSession()->responseNotContains('changefreq');
  175. }
  176. /**
  177. * Test the lastmod parameter in different scenarios.
  178. *
  179. * @throws \Drupal\Component\Plugin\Exception\PluginException
  180. * @throws \Behat\Mink\Exception\ExpectationException
  181. */
  182. public function testLastmod() {
  183. // Entity links should have 'lastmod'.
  184. $this->generator->setBundleSettings('node', 'page')
  185. ->removeCustomLinks()
  186. ->generateSitemap('backend');
  187. $this->drupalGet($this->defaultSitemapUrl);
  188. $this->assertSession()->responseContains('lastmod');
  189. // Entity custom links should have 'lastmod'.
  190. $this->generator->setBundleSettings('node', 'page', ['index' => FALSE])
  191. ->addCustomLink('/node/' . $this->node->id())
  192. ->generateSitemap('backend');
  193. $this->drupalGet($this->defaultSitemapUrl);
  194. $this->assertSession()->responseContains('lastmod');
  195. // Non-entity custom links should not have 'lastmod'.
  196. $this->generator->removeCustomLinks()
  197. ->addCustomLink('/')
  198. ->generateSitemap('backend');
  199. $this->drupalGet($this->defaultSitemapUrl);
  200. $this->assertSession()->responseNotContains('lastmod');
  201. }
  202. /**
  203. * Tests the duplicate setting.
  204. *
  205. * @throws \Drupal\Component\Plugin\Exception\PluginException
  206. */
  207. public function testRemoveDuplicatesSetting() {
  208. $this->generator->setBundleSettings('node', 'page')
  209. ->addCustomLink('/node/1')
  210. ->saveSetting('remove_duplicates', TRUE)
  211. ->generateSitemap('backend');
  212. $this->drupalGet($this->defaultSitemapUrl);
  213. $this->assertUniqueTextWorkaround('node/' . $this->node->id());
  214. $this->generator->saveSetting('remove_duplicates', FALSE)
  215. ->generateSitemap('backend');
  216. $this->drupalGet($this->defaultSitemapUrl);
  217. $this->assertNoUniqueTextWorkaround('node/' . $this->node->id());
  218. }
  219. /**
  220. * Test max links setting and the sitemap index.
  221. *
  222. * @throws \Drupal\Component\Plugin\Exception\PluginException
  223. * @throws \Behat\Mink\Exception\ExpectationException
  224. */
  225. public function testMaxLinksSetting() {
  226. $this->generator->setBundleSettings('node', 'page')
  227. ->saveSetting('max_links', 1)
  228. ->removeCustomLinks()
  229. ->generateSitemap('backend');
  230. $this->drupalGet($this->defaultSitemapUrl);
  231. $this->assertSession()->responseContains('sitemap.xml?page=1');
  232. $this->assertSession()->responseContains('sitemap.xml?page=2');
  233. $this->drupalGet('sitemap.xml', ['query' => ['page' => 1]]);
  234. $this->assertSession()->responseContains('node/' . $this->node->id());
  235. $this->assertSession()->responseContains('0.5');
  236. $this->assertSession()->responseNotContains('node/' . $this->node2->id());
  237. $this->drupalGet('sitemap.xml', ['query' => ['page' => 2]]);
  238. $this->assertSession()->responseContains('node/' . $this->node2->id());
  239. $this->assertSession()->responseContains('0.5');
  240. $this->assertSession()->responseNotContains('node/' . $this->node->id());
  241. }
  242. /**
  243. * @todo testGenerateDurationSetting
  244. */
  245. /**
  246. * Test setting the base URL.
  247. *
  248. * @throws \Drupal\Component\Plugin\Exception\PluginException
  249. * @throws \Behat\Mink\Exception\ExpectationException
  250. */
  251. public function testBaseUrlSetting() {
  252. $this->generator->setBundleSettings('node', 'page')
  253. ->saveSetting('base_url', 'http://base_url_test')
  254. ->generateSitemap('backend');
  255. $this->drupalGet($this->defaultSitemapUrl);
  256. $this->assertSession()->responseContains('http://base_url_test');
  257. // Set base URL in the sitemap index.
  258. $this->generator->saveSetting('max_links', 1)
  259. ->generateSitemap('backend');
  260. $this->drupalGet($this->defaultSitemapUrl);
  261. $this->assertSession()->responseContains('http://base_url_test/sitemap.xml?page=1');
  262. }
  263. /**
  264. * Test overriding of bundle settings for a single entity.
  265. *
  266. * @throws \Drupal\Component\Plugin\Exception\PluginException
  267. * @throws \Behat\Mink\Exception\ExpectationException
  268. *
  269. * @todo: Use form testing instead of responseContains().
  270. */
  271. public function testSetEntityInstanceSettings() {
  272. $this->generator->setBundleSettings('node', 'page')
  273. ->removeCustomLinks()
  274. ->setEntityInstanceSettings('node', $this->node->id(), ['priority' => 0.1, 'changefreq' => 'never'])
  275. ->setEntityInstanceSettings('node', $this->node2->id(), ['index' => FALSE])
  276. ->generateSitemap('backend');
  277. // Test sitemap result.
  278. $this->drupalGet($this->defaultSitemapUrl);
  279. $this->assertSession()->responseContains('node/' . $this->node->id());
  280. $this->assertSession()->responseContains('0.1');
  281. $this->assertSession()->responseContains('never');
  282. $this->assertSession()->responseNotContains('node/' . $this->node2->id());
  283. $this->assertSession()->responseNotContains('0.5');
  284. $this->drupalLogin($this->privilegedUser);
  285. // Test UI changes.
  286. $this->drupalGet('node/' . $this->node->id() . '/edit');
  287. $this->assertSession()->responseContains('<option value="0.1" selected="selected">0.1</option>');
  288. $this->assertSession()->responseContains('<option value="never" selected="selected">never</option>');
  289. // Test database changes.
  290. $result = $this->database->select('simple_sitemap_entity_overrides', 'o')
  291. ->fields('o', ['inclusion_settings'])
  292. ->condition('o.entity_type', 'node')
  293. ->condition('o.entity_id', $this->node->id())
  294. ->execute()
  295. ->fetchField();
  296. $this->assertFalse(empty($result));
  297. $this->generator->setBundleSettings('node', 'page', ['priority' => 0.1, 'changefreq' => 'never'])
  298. ->generateSitemap('backend');
  299. // Test sitemap result.
  300. $this->drupalGet($this->defaultSitemapUrl);
  301. $this->assertSession()->responseContains('node/' . $this->node->id());
  302. $this->assertSession()->responseContains('0.1');
  303. $this->assertSession()->responseContains('never');
  304. $this->assertSession()->responseNotContains('node/' . $this->node2->id());
  305. $this->assertSession()->responseNotContains('0.5');
  306. // Test UI changes.
  307. $this->drupalGet('node/' . $this->node->id() . '/edit');
  308. $this->assertSession()->responseContains('<option value="0.1" selected="selected">0.1 (default)</option>');
  309. $this->assertSession()->responseContains('<option value="never" selected="selected">never (default)</option>');
  310. // Test if entity override has been removed from database after its equal to
  311. // its bundle settings.
  312. $result = $this->database->select('simple_sitemap_entity_overrides', 'o')
  313. ->fields('o', ['inclusion_settings'])
  314. ->condition('o.entity_type', 'node')
  315. ->condition('o.entity_id', $this->node->id())
  316. ->execute()
  317. ->fetchField();
  318. $this->assertTrue(empty($result));
  319. }
  320. /**
  321. * Test indexing an atomic entity (here: a user)
  322. */
  323. public function testAtomicEntityIndexation() {
  324. $user_id = $this->privilegedUser->id();
  325. $this->generator->setBundleSettings('user')
  326. ->generateSitemap('backend');
  327. $this->drupalGet($this->defaultSitemapUrl);
  328. $this->assertSession()->responseNotContains('user/' . $user_id);
  329. user_role_grant_permissions('anonymous', ['access user profiles']);
  330. drupal_flush_all_caches(); //todo Not pretty.
  331. $this->generator->generateSitemap('backend');
  332. $this->drupalGet($this->defaultSitemapUrl);
  333. $this->assertSession()->responseContains('user/' . $user_id);
  334. }
  335. /**
  336. * @todo Test indexing menu.
  337. */
  338. /**
  339. * @todo Test deleting a bundle.
  340. */
  341. /**
  342. * Test disabling sitemap support for an entity type.
  343. *
  344. * @throws \Drupal\Component\Plugin\Exception\PluginException
  345. * @throws \Behat\Mink\Exception\ExpectationException
  346. */
  347. public function testDisableEntityType() {
  348. $this->generator->setBundleSettings('node', 'page')
  349. ->disableEntityType('node');
  350. $this->drupalLogin($this->privilegedUser);
  351. $this->drupalGet('admin/structure/types/manage/page');
  352. $this->assertSession()->pageTextNotContains('Simple XML sitemap');
  353. $this->generator->generateSitemap('backend');
  354. $this->drupalGet($this->defaultSitemapUrl);
  355. $this->assertSession()->responseNotContains('node/' . $this->node->id());
  356. $this->assertFalse($this->generator->entityTypeIsEnabled('node'));
  357. }
  358. /**
  359. * Test enabling sitemap support for an entity type.
  360. *
  361. * @throws \Drupal\Component\Plugin\Exception\PluginException
  362. * @throws \Behat\Mink\Exception\ExpectationException
  363. *
  364. * @todo Test admin/config/search/simplesitemap/entities form.
  365. */
  366. public function testEnableEntityType() {
  367. $this->generator->disableEntityType('node')
  368. ->enableEntityType('node')
  369. ->setBundleSettings('node', 'page');
  370. $this->drupalLogin($this->privilegedUser);
  371. $this->drupalGet('admin/structure/types/manage/page');
  372. $this->assertSession()->pageTextContains('Simple XML sitemap');
  373. $this->generator->generateSitemap('backend');
  374. $this->drupalGet($this->defaultSitemapUrl);
  375. $this->assertSession()->responseContains('node/' . $this->node->id());
  376. $this->assertTrue($this->generator->entityTypeIsEnabled('node'));
  377. }
  378. /**
  379. * @todo testSitemapLanguages
  380. */
  381. /**
  382. * Test adding and removing sitemap variants.
  383. *
  384. * @throws \Behat\Mink\Exception\ExpectationException
  385. * @throws \Drupal\Component\Plugin\Exception\PluginException
  386. */
  387. public function testSitemapVariants() {
  388. // Test adding a variant.
  389. $this->generator->getSitemapManager()->addSitemapVariant('test');
  390. $this->generator
  391. ->setBundleSettings('node', 'page')
  392. ->generateSitemap('backend');
  393. $variants = $this->generator->getSitemapManager()->getSitemapVariants();
  394. $this->assertTrue(isset($variants['test']));
  395. $this->drupalGet($this->defaultSitemapUrl);
  396. $this->assertSession()->responseContains('node/' . $this->node->id());
  397. // Test if generation affected the default variant only.
  398. $this->drupalGet('test/sitemap.xml');
  399. $this->assertSession()->responseNotContains('node/' . $this->node->id());
  400. $this->generator
  401. ->setVariants('test')
  402. ->setBundleSettings('node', 'page')
  403. ->generateSitemap('backend');
  404. // Test if bundle settings have been set for correct variant.
  405. $this->drupalGet($this->defaultSitemapUrl);
  406. $this->assertSession()->responseContains('node/' . $this->node->id());
  407. $this->generator->getSitemapManager()->removeSitemapVariants('test');
  408. $variants = $this->generator->getSitemapManager()->getSitemapVariants();
  409. $this->assertFalse(isset($variants['test']));
  410. // Test if sitemap has been removed along with the variant.
  411. $this->drupalGet('test/sitemap.xml');
  412. $this->assertSession()->statusCodeEquals(404);
  413. }
  414. /**
  415. * @todo Test removeSitemap().
  416. */
  417. /**
  418. * Test cases for ::testGenerationResume.
  419. */
  420. public function generationResumeProvider() {
  421. return [
  422. [1000, 500, 1],
  423. [1000, 500, 3, ['de']],
  424. [1000, 500, 5, ['de', 'es']],
  425. [10, 10000, 10],
  426. ];
  427. }
  428. /**
  429. * @throws \Drupal\Component\Plugin\Exception\PluginException
  430. *
  431. * @dataProvider generationResumeProvider
  432. */
  433. public function testGenerationResume($element_count, $generate_duration, $max_links, $langcodes = []) {
  434. $this->addLanguages($langcodes);
  435. $expected_sitemap_count = (int) ceil(($element_count * (count($langcodes) + 1)) / $max_links);
  436. $this->drupalCreateContentType(['type' => 'blog']);
  437. for ($i = 1; $i <= $element_count; $i++) {
  438. $this->createNode(['title' => 'node-' . $i, 'type' => 'blog']);
  439. }
  440. $this->generator
  441. ->removeCustomLinks()
  442. ->saveSetting('generate_duration', $generate_duration)
  443. ->saveSetting('max_links', $max_links)
  444. ->saveSetting('skip_untranslated', FALSE)
  445. ->setBundleSettings('node', 'blog');
  446. $queue = $this->generator->getQueueWorker()->rebuildQueue();
  447. $generate_count = 0;
  448. while ($queue->generationInProgress()) {
  449. $generate_count++;
  450. $this->generator->generateSitemap('backend');
  451. }
  452. // Test if sitemap generation has been resumed when time limit is very low.
  453. $this->assertTrue($generate_duration > $element_count || $generate_count > 1, 'This assertion tests if the sitemap generation is split up into batches due to a low generation time limit setting. The failing of this assertion can mean that the sitemap was wrongfully generated in one go, but it can also mean that the assumed low time setting is still high enough for a one pass generation.');
  454. // Test if correct number of sitemaps have been created.
  455. $chunks = $this->database->query('SELECT id FROM {simple_sitemap} WHERE delta != 0 AND status = 1');
  456. $chunks->allowRowCount = TRUE;
  457. $chunk_count = $chunks->rowCount();
  458. $this->assertTrue($chunk_count === $expected_sitemap_count);
  459. // Test if index has been created when necessary.
  460. $index = $this->database->query('SELECT id FROM {simple_sitemap} WHERE delta = 0 AND status = 1')
  461. ->fetchField();
  462. $this->assertTrue($chunk_count > 1 ? (FALSE !== $index) : !$index);
  463. }
  464. }