Pathauto and dependencies

This commit is contained in:
Rob Davies 2017-05-22 15:12:47 +01:00
parent 4b1a293d57
commit 24ffcb956b
257 changed files with 29510 additions and 0 deletions

View file

@ -0,0 +1,156 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\pathauto\PathautoGeneratorInterface;
use Drupal\pathauto\PathautoState;
use Drupal\simpletest\WebTestBase;
/**
* Bulk update functionality tests.
*
* @group pathauto
*/
class PathautoBulkUpdateTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'pathauto', 'forum');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* The created nodes.
*
* @var \Drupal\node\NodeInterface
*/
protected $nodes;
/**
* The created patterns.
*
* @var \Drupal\pathauto\PathautoPatternInterface
*/
protected $patterns;
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
// Allow other modules to add additional permissions for the admin user.
$permissions = array(
'administer pathauto',
'administer url aliases',
'create url aliases',
'administer forums',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
$this->patterns = array();
$this->patterns['node'] = $this->createPattern('node', '/content/[node:title]');
$this->patterns['user'] = $this->createPattern('user', '/users/[user:name]');
$this->patterns['forum'] = $this->createPattern('forum', '/forums/[term:name]');
}
function testBulkUpdate() {
// Create some nodes.
$this->nodes = array();
for ($i = 1; $i <= 5; $i++) {
$node = $this->drupalCreateNode();
$this->nodes[$node->id()] = $node;
}
// Clear out all aliases.
$this->deleteAllAliases();
// Bulk create aliases.
$edit = array(
'update[canonical_entities:node]' => TRUE,
'update[canonical_entities:user]' => TRUE,
'update[forum]' => TRUE,
);
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
// This has generated 8 aliases: 5 nodes, 2 users and 1 forum.
$this->assertText('Generated 8 URL aliases.');
// Check that aliases have actually been created.
foreach ($this->nodes as $node) {
$this->assertEntityAliasExists($node);
}
$this->assertEntityAliasExists($this->adminUser);
// This is the default "General discussion" forum.
$this->assertAliasExists(['source' => '/taxonomy/term/1']);
// Add a new node.
$new_node = $this->drupalCreateNode(array('path' => array('alias' => '', 'pathauto' => PathautoState::SKIP)));
// Run the update again which should not run against any nodes.
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText('No new URL aliases to generate.');
$this->assertNoEntityAliasExists($new_node);
// Make sure existing aliases can be overriden.
$this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_DELETE], t('Save configuration'));
// Patterns did not change, so no aliases should be regenerated.
$edit['action'] = 'all';
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText('No new URL aliases to generate.');
// Update the node pattern, and leave other patterns alone. Existing nodes should get a new alias,
// except the node above whose alias is manually set. Other aliases must be left alone.
$this->patterns['node']->delete();
$this->patterns['node'] = $this->createPattern('node', '/archive/node-[node:nid]');
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText('Generated 5 URL aliases.');
// Prevent existing aliases to be overriden. The bulk generate page should only offer
// to create an alias for paths which have none.
$this->drupalPostForm('admin/config/search/path/settings', ['update_action' => PathautoGeneratorInterface::UPDATE_ACTION_NO_NEW], t('Save configuration'));
$this->drupalGet('admin/config/search/path/update_bulk');
$this->assertFieldByName('action', 'create');
$this->assertText('Pathauto settings are set to ignore paths which already have a URL alias.');
$this->assertNoFieldByName('action', 'update');
$this->assertNoFieldByName('action', 'all');
}
/**
* Tests alias generation for nodes that existed before installing Pathauto.
*/
function testBulkUpdateExistingContent() {
// Create a node.
$node = $this->drupalCreateNode();
// Delete its alias and Pathauto metadata.
\Drupal::service('pathauto.alias_storage_helper')->deleteEntityPathAll($node);
$node->path->first()->get('pathauto')->purge();
\Drupal::entityTypeManager()->getStorage('node')->resetCache(array($node->id()));
// Execute bulk generation.
// Bulk create aliases.
$edit = array(
'update[canonical_entities:node]' => TRUE,
);
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
// Verify that the alias was created for the node.
$this->assertText('Generated 1 URL alias.');
}
}

View file

@ -0,0 +1,87 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\comment\Tests\CommentTestTrait;
/**
* Tests pathauto settings form.
*
* @group pathauto
*/
class PathautoEnablingEntityTypesTest extends WebTestBase {
use PathautoTestHelperTrait;
use CommentTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'pathauto', 'comment');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
$this->drupalCreateContentType(array('type' => 'article'));
$this->addDefaultCommentField('node', 'article');
$permissions = array(
'administer pathauto',
'administer url aliases',
'create url aliases',
'administer nodes',
'post comments',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
}
/**
* A suite of tests to verify if the feature to enable and disable the
* ability to define alias patterns for a given entity type works. Test with
* the comment module, as it is not enabled by default.
*/
function testEnablingEntityTypes() {
// Verify that the comment entity type is not available when trying to add
// a new pattern, nor "broken".
$this->drupalGet('/admin/config/search/path/patterns/add');
$this->assertEqual(count($this->cssSelect('option[value = "canonical_entities:comment"]:contains(Comment)')), 0);
$this->assertEqual(count($this->cssSelect('option:contains(Broken)')), 0);
// Enable the entity type and create a pattern for it.
$this->drupalGet('/admin/config/search/path/settings');
$edit = [
'enabled_entity_types[comment]' => TRUE,
];
$this->drupalPostForm(NULL, $edit, 'Save configuration');
$this->createPattern('comment', '/comment/[comment:body]');
// Create a node, a comment type and a comment entity.
$node = $this->drupalCreateNode(['type' => 'article']);
$this->drupalGet('/node/' . $node->id());
$edit = [
'comment_body[0][value]' => 'test-body',
];
$this->drupalPostForm(NULL, $edit, 'Save');
// Verify that an alias has been generated and that the type can no longer
// be disabled.
$this->assertAliasExists(['alias' => '/comment/test-body']);
$this->drupalGet('/admin/config/search/path/settings');
$this->assertEqual(count($this->cssSelect('input[name = "enabled_entity_types[comment]"][disabled = "disabled"]')), 1);
}
}

View file

@ -0,0 +1,201 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\pathauto\PathautoState;
use Drupal\simpletest\WebTestBase;
/**
* Test pathauto functionality with localization and translation.
*
* @group pathauto
*/
class PathautoLocaleTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'pathauto', 'locale', 'content_translation');
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create Article node type.
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
}
/**
* Test that when an English node is updated, its old English alias is
* updated and its newer French alias is left intact.
*/
function testLanguageAliases() {
$this->createPattern('node', '/content/[node:title]');
// Add predefined French language.
ConfigurableLanguage::createFromLangcode('fr')->save();
$node = array(
'title' => 'English node',
'langcode' => 'en',
'path' => array(array(
'alias' => '/english-node',
'pathauto' => FALSE,
)),
);
$node = $this->drupalCreateNode($node);
$english_alias = \Drupal::service('path.alias_storage')->load(array('alias' => '/english-node', 'langcode' => 'en'));
$this->assertTrue($english_alias, 'Alias created with proper language.');
// Also save a French alias that should not be left alone, even though
// it is the newer alias.
$this->saveEntityAlias($node, '/french-node', 'fr');
// Add an alias with the soon-to-be generated alias, causing the upcoming
// alias update to generate a unique alias with the '-0' suffix.
$this->saveAlias('/node/invalid', '/content/english-node', Language::LANGCODE_NOT_SPECIFIED);
// Update the node, triggering a change in the English alias.
$node->path->pathauto = PathautoState::CREATE;
$node->save();
// Check that the new English alias replaced the old one.
$this->assertEntityAlias($node, '/content/english-node-0', 'en');
$this->assertEntityAlias($node, '/french-node', 'fr');
$this->assertAliasExists(array('pid' => $english_alias['pid'], 'alias' => '/content/english-node-0'));
// Create a new node with the same title as before but without
// specifying a language.
$node = $this->drupalCreateNode(array('title' => 'English node', 'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED));
// Check that the new node had a unique alias generated with the '-0'
// suffix.
$this->assertEntityAlias($node, '/content/english-node-0', LanguageInterface::LANGCODE_NOT_SPECIFIED);
}
/**
* Test that patterns work on multilingual content.
*/
function testLanguagePatterns() {
$this->drupalLogin($this->rootUser);
// Add French language.
$edit = array(
'predefined_langcode' => 'fr',
);
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
$this->enableArticleTranslation();
// Create a pattern for English articles.
$this->drupalGet('admin/config/search/path/patterns/add');
$edit = array(
'type' => 'canonical_entities:node',
);
$this->drupalPostAjaxForm(NULL, $edit, 'type');
$edit += array(
'pattern' => '/the-articles/[node:title]',
'label' => 'English articles',
'id' => 'english_articles',
'bundles[article]' => TRUE,
'languages[en]' => TRUE,
);
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Pattern English articles saved.');
// Create a pattern for French articles.
$this->drupalGet('admin/config/search/path/patterns/add');
$edit = array(
'type' => 'canonical_entities:node',
);
$this->drupalPostAjaxForm(NULL, $edit, 'type');
$edit += array(
'pattern' => '/les-articles/[node:title]',
'label' => 'French articles',
'id' => 'french_articles',
'bundles[article]' => TRUE,
'languages[fr]' => TRUE,
);
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Pattern French articles saved.');
// Create a node and its translation. Assert aliases.
$edit = array(
'title[0][value]' => 'English node',
'langcode[0][value]' => 'en',
);
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
$english_node = $this->drupalGetNodeByTitle('English node');
$this->assertAlias('/node/' . $english_node->id(), '/the-articles/english-node', 'en');
$this->drupalGet('node/' . $english_node->id() . '/translations');
$this->clickLink(t('Add'));
$edit = array(
'title[0][value]' => 'French node',
);
$this->drupalPostForm(NULL, $edit, t('Save and keep published (this translation)'));
$this->rebuildContainer();
$english_node = $this->drupalGetNodeByTitle('English node');
$french_node = $english_node->getTranslation('fr');
$this->assertAlias('/node/' . $french_node->id(), '/les-articles/french-node', 'fr');
// Bulk delete and Bulk generate patterns. Assert aliases.
$this->deleteAllAliases();
// Bulk create aliases.
$edit = array(
'update[canonical_entities:node]' => TRUE,
);
$this->drupalPostForm('admin/config/search/path/update_bulk', $edit, t('Update'));
$this->assertText(t('Generated 2 URL aliases.'));
$this->assertAlias('/node/' . $english_node->id(), '/the-articles/english-node', 'en');
$this->assertAlias('/node/' . $french_node->id(), '/les-articles/french-node', 'fr');
}
/**
* Tests the alias created for a node with language Not Applicable.
*/
public function testLanguageNotApplicable() {
$this->drupalLogin($this->rootUser);
$this->enableArticleTranslation();
// Create a pattern for nodes.
$pattern = $this->createPattern('node', '/content/[node:title]', -1);
$pattern->save();
// Create a node with language Not Applicable.
$node = $this->createNode(['type' => 'article', 'title' => 'Test node', 'langcode' => LanguageInterface::LANGCODE_NOT_APPLICABLE]);
// Check that the generated alias has language Not Specified.
$alias = \Drupal::service('pathauto.alias_storage_helper')->loadBySource('/node/' . $node->id());
$this->assertEqual($alias['langcode'], LanguageInterface::LANGCODE_NOT_SPECIFIED, 'PathautoGenerator::createEntityAlias() adjusts the alias langcode from Not Applicable to Not Specified.');
// Check that the alias works.
$this->drupalGet('content/test-node');
$this->assertResponse(200);
}
/**
* Enables content translation on articles.
*/
protected function enableArticleTranslation() {
// Enable content translation on articles.
$this->drupalGet('admin/config/regional/content-language');
$edit = array(
'entity_types[node]' => TRUE,
'settings[node][article][translatable]' => TRUE,
'settings[node][article][settings][language][language_alterable]' => TRUE,
);
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
}
}

View file

@ -0,0 +1,200 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\pathauto\PathautoState;
use Drupal\simpletest\WebTestBase;
/**
* Mass delete functionality tests.
*
* @group pathauto
*/
class PathautoMassDeleteTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'taxonomy', 'pathauto');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* The test nodes.
*
* @var \Drupal\node\NodeInterface
*/
protected $nodes;
/**
* The test accounts.
*
* @var \Drupal\user\UserInterface
*/
protected $accounts;
/**
* The test terms.
*
* @var \Drupal\taxonomy\TermInterface
*/
protected $terms;
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
$permissions = array(
'administer pathauto',
'administer url aliases',
'create url aliases',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
$this->createPattern('node', '/content/[node:title]');
$this->createPattern('user', '/users/[user:name]');
$this->createPattern('taxonomy_term', '/[term:vocabulary]/[term:name]');
}
/**
* Tests the deletion of all the aliases.
*/
function testDeleteAll() {
// 1. Test that deleting all the aliases, of any type, works.
$this->generateAliases();
$edit = array(
'delete[all_aliases]' => TRUE,
'options[keep_custom_aliases]' => FALSE,
);
$this->drupalPostForm('admin/config/search/path/delete_bulk', $edit, t('Delete aliases now!'));
$this->assertText(t('All of your path aliases have been deleted.'));
$this->assertUrl('admin/config/search/path/delete_bulk');
// Make sure that all of them are actually deleted.
$aliases = \Drupal::database()->select('url_alias', 'ua')->fields('ua', array())->execute()->fetchAll();
$this->assertEqual($aliases, array(), "All the aliases have been deleted.");
// 2. Test deleting only specific (entity type) aliases.
$manager = $this->container->get('plugin.manager.alias_type');
$pathauto_plugins = array('canonical_entities:node' => 'nodes', 'canonical_entities:taxonomy_term' => 'terms', 'canonical_entities:user' => 'accounts');
foreach ($pathauto_plugins as $pathauto_plugin => $attribute) {
$this->generateAliases();
$edit = array(
'delete[plugins][' . $pathauto_plugin . ']' => TRUE,
'options[keep_custom_aliases]' => FALSE,
);
$this->drupalPostForm('admin/config/search/path/delete_bulk', $edit, t('Delete aliases now!'));
$alias_type = $manager->createInstance($pathauto_plugin);
$this->assertRaw(t('All of your %label path aliases have been deleted.', array('%label' => $alias_type->getLabel())));
// Check that the aliases were actually deleted.
foreach ($this->{$attribute} as $entity) {
$this->assertNoEntityAlias($entity);
}
// Check that the other aliases are not deleted.
foreach ($pathauto_plugins as $_pathauto_plugin => $_attribute) {
// Skip the aliases that should be deleted.
if ($_pathauto_plugin == $pathauto_plugin) {
continue;
}
foreach ($this->{$_attribute} as $entity) {
$this->assertEntityAliasExists($entity);
}
}
}
// 3. Test deleting automatically generated aliases only.
$this->generateAliases();
$edit = array(
'delete[all_aliases]' => TRUE,
'options[keep_custom_aliases]' => TRUE,
);
$this->drupalPostForm('admin/config/search/path/delete_bulk', $edit, t('Delete aliases now!'));
$this->assertText(t('All of your automatically generated path aliases have been deleted.'));
$this->assertUrl('admin/config/search/path/delete_bulk');
// Make sure that only custom aliases and aliases with no information about
// their state still exist.
$aliases = \Drupal::database()->select('url_alias', 'ua')->fields('ua', ['source'])->execute()->fetchCol();
$this->assertEqual($aliases, ['/node/101', '/node/104', '/node/105'], 'Custom aliases still exist.');
}
/**
* Helper function to generate aliases.
*/
function generateAliases() {
// Delete all aliases to avoid duplicated aliases. They will be recreated below.
$this->deleteAllAliases();
// We generate a bunch of aliases for nodes, users and taxonomy terms. If
// the entities are already created we just update them, otherwise we create
// them.
if (empty($this->nodes)) {
// Create a large number of nodes (100+) to make sure that the batch code works.
for ($i = 1; $i <= 105; $i++) {
// Set the alias of two nodes manually.
$settings = ($i > 103) ? ['path' => ['alias' => "/custom_alias_$i", 'pathauto' => PathautoState::SKIP]] : [];
$node = $this->drupalCreateNode($settings);
$this->nodes[$node->id()] = $node;
}
}
else {
foreach ($this->nodes as $node) {
if ($node->id() > 103) {
// The alias is set manually.
$node->set('path', ['alias' => '/custom_alias_' . $node->id()]);
}
$node->save();
}
}
// Delete information about the state of an alias to make sure that aliases
// with no such data are left alone by default.
\Drupal::keyValue('pathauto_state.node')->delete(101);
if (empty($this->accounts)) {
for ($i = 1; $i <= 5; $i++) {
$account = $this->drupalCreateUser();
$this->accounts[$account->id()] = $account;
}
}
else {
foreach ($this->accounts as $id => $account) {
$account->save();
}
}
if (empty($this->terms)) {
$vocabulary = $this->addVocabulary(array('name' => 'test vocabulary', 'vid' => 'test_vocabulary'));
for ($i = 1; $i <= 5; $i++) {
$term = $this->addTerm($vocabulary);
$this->terms[$term->id()] = $term;
}
}
else {
foreach ($this->terms as $term) {
$term->save();
}
}
// Check that we have aliases for the entities.
foreach (array('nodes', 'accounts', 'terms') as $attribute) {
foreach ($this->{$attribute} as $entity) {
$this->assertEntityAliasExists($entity);
}
}
}
}

View file

@ -0,0 +1,292 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\pathauto\Entity\PathautoPattern;
use Drupal\node\Entity\Node;
use Drupal\pathauto\PathautoState;
use Drupal\simpletest\WebTestBase;
/**
* Tests pathauto node UI integration.
*
* @group pathauto
*/
class PathautoNodeWebTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'pathauto', 'views', 'taxonomy', 'pathauto_views_test');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
$this->drupalCreateContentType(array('type' => 'article'));
// Allow other modules to add additional permissions for the admin user.
$permissions = array(
'administer pathauto',
'administer url aliases',
'create url aliases',
'administer nodes',
'bypass node access',
'access content overview',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
$this->createPattern('node', '/content/[node:title]');
}
/**
* Tests editing nodes with different settings.
*/
function testNodeEditing() {
// Ensure that the Pathauto checkbox is checked by default on the node add form.
$this->drupalGet('node/add/page');
$this->assertFieldChecked('edit-path-0-pathauto');
// Create a node by saving the node form.
$title = ' Testing: node title [';
$automatic_alias = '/content/testing-node-title';
$this->drupalPostForm(NULL, array('title[0][value]' => $title), t('Save and publish'));
$node = $this->drupalGetNodeByTitle($title);
// Look for alias generated in the form.
$this->drupalGet("node/{$node->id()}/edit");
$this->assertFieldChecked('edit-path-0-pathauto');
$this->assertFieldByName('path[0][alias]', $automatic_alias, 'Generated alias visible in the path alias field.');
// Check whether the alias actually works.
$this->drupalGet($automatic_alias);
$this->assertText($title, 'Node accessible through automatic alias.');
// Manually set the node's alias.
$manual_alias = '/content/' . $node->id();
$edit = array(
'path[0][pathauto]' => FALSE,
'path[0][alias]' => $manual_alias,
);
$this->drupalPostForm($node->toUrl('edit-form'), $edit, t('Save and keep published'));
$this->assertText(t('@type @title has been updated.', array('@type' => 'page', '@title' => $title)));
// Check that the automatic alias checkbox is now unchecked by default.
$this->drupalGet("node/{$node->id()}/edit");
$this->assertNoFieldChecked('edit-path-0-pathauto');
$this->assertFieldByName('path[0][alias]', $manual_alias);
// Submit the node form with the default values.
$this->drupalPostForm(NULL, array('path[0][pathauto]' => FALSE), t('Save and keep published'));
$this->assertText(t('@type @title has been updated.', array('@type' => 'page', '@title' => $title)));
// Test that the old (automatic) alias has been deleted and only accessible
// through the new (manual) alias.
$this->drupalGet($automatic_alias);
$this->assertResponse(404, 'Node not accessible through automatic alias.');
$this->drupalGet($manual_alias);
$this->assertText($title, 'Node accessible through manual alias.');
// Test that the manual alias is not kept for new nodes when the pathauto
// checkbox is ticked.
$title = 'Automatic Title';
$edit = array(
'title[0][value]' => $title,
'path[0][pathauto]' => TRUE,
'path[0][alias]' => '/should-not-get-created',
);
$this->drupalPostForm('node/add/page', $edit, t('Save and publish'));
$this->assertNoAliasExists(array('alias' => 'should-not-get-created'));
$node = $this->drupalGetNodeByTitle($title);
$this->assertEntityAlias($node, '/content/automatic-title');
// Remove the pattern for nodes, the pathauto checkbox should not be
// displayed.
$ids = \Drupal::entityQuery('pathauto_pattern')
->condition('type', 'canonical_entities:node')
->execute();
foreach (PathautoPattern::loadMultiple($ids) as $pattern) {
$pattern->delete();
}
$this->drupalGet('node/add/article');
$this->assertNoFieldById('edit-path-0-pathauto');
$this->assertFieldByName('path[0][alias]', '');
$edit = array();
$edit['title'] = 'My test article';
$this->drupalCreateNode($edit);
//$this->drupalPostForm(NULL, $edit, t('Save and keep published'));
$node = $this->drupalGetNodeByTitle($edit['title']);
// Pathauto checkbox should still not exist.
$this->drupalGet($node->toUrl('edit-form'));
$this->assertNoFieldById('edit-path-0-pathauto');
$this->assertFieldByName('path[0][alias]', '');
$this->assertNoEntityAlias($node);
}
/**
* Test node operations.
*/
function testNodeOperations() {
$node1 = $this->drupalCreateNode(array('title' => 'node1'));
$node2 = $this->drupalCreateNode(array('title' => 'node2'));
// Delete all current URL aliases.
$this->deleteAllAliases();
$this->drupalGet('admin/content');
// Check which of the two nodes is first.
if (strpos($this->getTextContent(), 'node1') < strpos($this->getTextContent(), 'node2')) {
$index = 0;
}
else {
$index = 1;
}
$edit = array(
'action' => 'pathauto_update_alias_node',
'node_bulk_form[' . $index . ']' => TRUE,
);
$this->drupalPostForm(NULL, $edit, t('Apply to selected items'));
$this->assertText('Update URL alias was applied to 1 item.');
$this->assertEntityAlias($node1, '/content/' . $node1->getTitle());
$this->assertEntityAlias($node2, '/node/' . $node2->id());
}
/**
* @todo Merge this with existing node test methods?
*/
public function testNodeState() {
$nodeNoAliasUser = $this->drupalCreateUser(array('bypass node access'));
$nodeAliasUser = $this->drupalCreateUser(array('bypass node access', 'create url aliases'));
$node = $this->drupalCreateNode(array(
'title' => 'Node version one',
'type' => 'page',
'path' => array(
'pathauto' => PathautoState::SKIP,
),
));
$this->assertNoEntityAlias($node);
// Set a manual path alias for the node.
$node->path->alias = '/test-alias';
$node->save();
// Ensure that the pathauto field was saved to the database.
\Drupal::entityTypeManager()->getStorage('node')->resetCache();
$node = Node::load($node->id());
$this->assertIdentical($node->path->pathauto, PathautoState::SKIP);
// Ensure that the manual path alias was saved and an automatic alias was not generated.
$this->assertEntityAlias($node, '/test-alias');
$this->assertNoEntityAliasExists($node, '/content/node-version-one');
// Save the node as a user who does not have access to path fieldset.
$this->drupalLogin($nodeNoAliasUser);
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertNoFieldByName('path[0][pathauto]');
$edit = array('title[0][value]' => 'Node version two');
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Basic page Node version two has been updated.');
$this->assertEntityAlias($node, '/test-alias');
$this->assertNoEntityAliasExists($node, '/content/node-version-one');
$this->assertNoEntityAliasExists($node, '/content/node-version-two');
// Load the edit node page and check that the Pathauto checkbox is unchecked.
$this->drupalLogin($nodeAliasUser);
$this->drupalGet('node/' . $node->id() . '/edit');
$this->assertNoFieldChecked('edit-path-0-pathauto');
// Edit the manual alias and save the node.
$edit = array(
'title[0][value]' => 'Node version three',
'path[0][alias]' => '/manually-edited-alias',
);
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Basic page Node version three has been updated.');
$this->assertEntityAlias($node, '/manually-edited-alias');
$this->assertNoEntityAliasExists($node, '/test-alias');
$this->assertNoEntityAliasExists($node, '/content/node-version-one');
$this->assertNoEntityAliasExists($node, '/content/node-version-two');
$this->assertNoEntityAliasExists($node, '/content/node-version-three');
// Programatically save the node with an automatic alias.
\Drupal::entityTypeManager()->getStorage('node')->resetCache();
$node = Node::load($node->id());
$node->path->pathauto = PathautoState::CREATE;
$node->save();
// Ensure that the pathauto field was saved to the database.
\Drupal::entityTypeManager()->getStorage('node')->resetCache();
$node = Node::load($node->id());
$this->assertIdentical($node->path->pathauto, PathautoState::CREATE);
$this->assertEntityAlias($node, '/content/node-version-three');
$this->assertNoEntityAliasExists($node, '/manually-edited-alias');
$this->assertNoEntityAliasExists($node, '/test-alias');
$this->assertNoEntityAliasExists($node, '/content/node-version-one');
$this->assertNoEntityAliasExists($node, '/content/node-version-two');
$node->delete();
$this->assertNull(\Drupal::keyValue('pathauto_state.node')->get($node->id()), 'Pathauto state was deleted');
}
/**
* Tests that nodes without a Pathauto pattern can set custom aliases.
*/
public function testCustomAliasWithoutPattern() {
// First, delete all patterns to be sure that there will be no match.
$entity_ids = \Drupal::entityQuery('pathauto_pattern')->execute();
$entities = PathautoPattern::loadMultiple($entity_ids);
foreach ($entities as $entity) {
$entity->delete();
}
// Next, create a node with a custom alias.
$edit = [
'title[0][value]' => 'Sample article',
'path[0][alias]' => '/sample-article',
];
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
$this->assertText(t('article Sample article has been created.'));
// Test the alias.
$this->assertAliasExists(array('alias' => '/sample-article'));
$this->drupalGet('sample-article');
$this->assertResponse(200, 'A node without a pattern can have a custom alias.');
// Now create a node through the API.
$node = Node::create(['type' => 'article', 'title' => 'Sample article API', 'path' => ['alias' => '/sample-article-api']]);
$node->save();
// Test the alias.
$this->assertAliasExists(['alias' => '/sample-article-api']);
$this->drupalGet('sample-article-api');
$this->assertResponse(200);
}
}

View file

@ -0,0 +1,240 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\pathauto\PathautoGeneratorInterface;
use Drupal\simpletest\WebTestBase;
/**
* Tests pathauto settings form.
*
* @group pathauto
*/
class PathautoSettingsFormWebTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('node', 'pathauto');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* Form values that are set by default.
*
* @var array
*/
protected $defaultFormValues = array(
'verbose' => FALSE,
'separator' => '-',
'case' => '1',
'max_length' => '100',
'max_component_length' => '100',
'update_action' => '2',
'transliterate' => '1',
'reduce_ascii' => FALSE,
'ignore_words' => 'a, an, as, at, before, but, by, for, from, is, in, into, like, of, off, on, onto, per, since, than, the, this, that, to, up, via, with',
);
/**
* Punctuation form items with default values.
*
* @var array
*/
protected $defaultPunctuations = array(
'punctuation[double_quotes]' => '0',
'punctuation[quotes]' => '0',
'punctuation[backtick]' => '0',
'punctuation[comma]' => '0',
'punctuation[period]' => '0',
'punctuation[hyphen]' => '1',
'punctuation[underscore]' => '0',
'punctuation[colon]' => '0',
'punctuation[semicolon]' => '0',
'punctuation[pipe]' => '0',
'punctuation[left_curly]' => '0',
'punctuation[left_square]' => '0',
'punctuation[right_curly]' => '0',
'punctuation[right_square]' => '0',
'punctuation[plus]' => '0',
'punctuation[equal]' => '0',
'punctuation[asterisk]' => '0',
'punctuation[ampersand]' => '0',
'punctuation[percent]' => '0',
'punctuation[caret]' => '0',
'punctuation[dollar]' => '0',
'punctuation[hash]' => '0',
'punctuation[exclamation]' => '0',
'punctuation[tilde]' => '0',
'punctuation[left_parenthesis]' => '0',
'punctuation[right_parenthesis]' => '0',
'punctuation[question_mark]' => '0',
'punctuation[less_than]' => '0',
'punctuation[greater_than]' => '0',
'punctuation[slash]' => '0',
'punctuation[back_slash]' => '0',
);
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
$this->drupalCreateContentType(array('type' => 'article'));
$permissions = array(
'administer pathauto',
'notify of path changes',
'administer url aliases',
'create url aliases',
'administer nodes',
'bypass node access',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
$this->createPattern('node', '/content/[node:title]');
}
/**
* Test if the default values are shown correctly in the form.
*/
function testDefaultFormValues() {
$this->drupalGet('/admin/config/search/path/settings');
$this->assertNoFieldChecked('edit-verbose');
$this->assertField('edit-separator', $this->defaultFormValues['separator']);
$this->assertFieldChecked('edit-case');
$this->assertField('edit-max-length', $this->defaultFormValues['max_length']);
$this->assertField('edit-max-component-length', $this->defaultFormValues['max_component_length']);
$this->assertFieldChecked('edit-update-action-2');
$this->assertFieldChecked('edit-transliterate');
$this->assertNoFieldChecked('edit-reduce-ascii');
$this->assertField('edit-ignore-words', $this->defaultFormValues['ignore_words']);
}
/**
* Test the verbose option.
*/
function testVerboseOption() {
$edit = array('verbose' => '1');
$this->drupalPostForm('/admin/config/search/path/settings', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
$this->assertFieldChecked('edit-verbose');
$title = 'Verbose settings test';
$this->drupalGet('/node/add/article');
$this->assertFieldChecked('edit-path-0-pathauto');
$this->drupalPostForm(NULL, array('title[0][value]' => $title), t('Save and publish'));
$this->assertText('Created new alias /content/verbose-settings-test for');
$node = $this->drupalGetNodeByTitle($title);
$this->drupalPostForm('/node/' . $node->id() . '/edit', array('title[0][value]' => 'Updated title'), t('Save and keep published'));
$this->assertText('Created new alias /content/updated-title for');
$this->assertText('replacing /content/verbose-settings-test.');
}
/**
* Tests generating aliases with different settings.
*/
function testSettingsForm() {
// Ensure the separator settings apply correctly.
$this->checkAlias('My awesome content', '/content/my.awesome.content', array('separator' => '.'));
// Ensure the character case setting works correctly.
// Leave case the same as source token values.
$this->checkAlias('My awesome Content', '/content/My-awesome-Content', array('case' => FALSE));
$this->checkAlias('Change Lower', '/content/change-lower', array('case' => '1'));
// Ensure the maximum alias length is working.
$this->checkAlias('My awesome Content', '/content/my-awesome', array('max_length' => '23'));
// Ensure the maximum component length is working.
$this->checkAlias('My awesome Content', '/content/my', array('max_component_length' => '2'));
// Ensure transliteration option is working.
$this->checkAlias('è é àl ö äl ü', '/content/e-e-al-o-al-u', array('transliterate' => '1'));
$this->checkAlias('è é àl äl ö ü', '/content/è-é-àl-äl-ö-ü', array('transliterate' => FALSE));
$ignore_words = 'a, new, very, should';
$this->checkAlias('a very new alias to test', '/content/alias-to-test', array('ignore_words' => $ignore_words));
}
/**
* Test the punctuation setting form items.
*/
function testPunctuationSettings() {
// Test the replacement of punctuations.
$settings = [];
foreach ($this->defaultPunctuations as $key => $punctuation) {
$settings[$key] = PathautoGeneratorInterface::PUNCTUATION_REPLACE;
}
$title = 'aa"b`c,d.e-f_g:h;i|j{k[l}m]n+o=p*q%r^s$t#u!v~w(x)y?z>1/2\3';
$alias = '/content/aa-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-1-2-3';
$this->checkAlias($title, $alias, $settings);
// Test the removal of punctuations.
$settings = [];
foreach ($this->defaultPunctuations as $key => $punctuation) {
$settings[$key] = PathautoGeneratorInterface::PUNCTUATION_REMOVE;
}
$title = 'a"b`c,d.e-f_g:h;i|j{k[l}m]n+o=p*q%r^s$t#u!v~w(x)y?z>1/2\3';
$alias = '/content/abcdefghijklmnopqrstuvwxyz123';
$this->checkAlias($title, $alias, $settings);
// Keep all punctuations in alias.
$settings = [];
foreach ($this->defaultPunctuations as $key => $punctuation) {
$settings[$key] = PathautoGeneratorInterface::PUNCTUATION_DO_NOTHING;
}
$title = 'al"b`c,d.e-f_g:h;i|j{k[l}m]n+o=p*q%r^s$t#u!v~w(x)y?z>1/2\3';
$alias = '/content/al"b`c,d.e-f_g:h;i|j{k[l}m]n+o=p*q%r^s$t#u!v~w(x)y?z>1/2\3';
$this->checkAlias($title, $alias, $settings);
}
/**
* Helper method to check the an aliases.
*
* @param string $title
* The node title to build the aliases from.
* @param string $alias
* The expected alias.
* @param array $settings
* The form values the alias should be generated with.
*/
protected function checkAlias($title, $alias, $settings = array()) {
// Submit the settings form.
$edit = array_merge($this->defaultFormValues + $this->defaultPunctuations, $settings);
$this->drupalPostForm('/admin/config/search/path/settings', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'));
// If we do not clear the caches here, AliasCleaner will use its
// cleanStringCache instance variable. Due to that the creation of aliases
// with $this->createNode() will only work correctly on the first call.
\Drupal::service('pathauto.generator')->resetCaches();
// Create a node and check if the settings applied.
$node = $this->createNode(
array(
'title' => $title,
'type' => 'article',
)
);
$this->drupalGet($alias);
$this->assertResponse(200);
$this->assertEntityAlias($node, $alias);
}
}

View file

@ -0,0 +1,102 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Tests pathauto taxonomy UI integration.
*
* @group pathauto
*/
class PathautoTaxonomyWebTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('taxonomy', 'pathauto', 'views');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
// Allow other modules to add additional permissions for the admin user.
$permissions = array(
'administer pathauto',
'administer url aliases',
'create url aliases',
'administer taxonomy',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
$this->createPattern('taxonomy_term', '/[term:vocabulary]/[term:name]');
}
/**
* Basic functional testing of Pathauto with taxonomy terms.
*/
function testTermEditing() {
$this->drupalGet('admin/structure');
$this->drupalGet('admin/structure/taxonomy');
// Add vocabulary "tags".
$vocabulary = $this->addVocabulary(array('name' => 'tags', 'vid' => 'tags'));
// Create term for testing.
$name = 'Testing: term name [';
$automatic_alias = '/tags/testing-term-name';
$this->drupalPostForm('admin/structure/taxonomy/manage/tags/add', array('name[0][value]' => $name), 'Save');
$name = trim($name);
$this->assertText("Created new term $name.");
$term = $this->drupalGetTermByName($name);
// Look for alias generated in the form.
$this->drupalGet("taxonomy/term/{$term->id()}/edit");
$this->assertFieldChecked('edit-path-0-pathauto');
$this->assertFieldByName('path[0][alias]', $automatic_alias, 'Generated alias visible in the path alias field.');
// Check whether the alias actually works.
$this->drupalGet($automatic_alias);
$this->assertText($name, 'Term accessible through automatic alias.');
// Manually set the term's alias.
$manual_alias = '/tags/' . $term->id();
$edit = array(
'path[0][pathauto]' => FALSE,
'path[0][alias]' => $manual_alias,
);
$this->drupalPostForm("taxonomy/term/{$term->id()}/edit", $edit, t('Save'));
$this->assertText("Updated term $name.");
// Check that the automatic alias checkbox is now unchecked by default.
$this->drupalGet("taxonomy/term/{$term->id()}/edit");
$this->assertNoFieldChecked('edit-path-0-pathauto');
$this->assertFieldByName('path[0][alias]', $manual_alias);
// Submit the term form with the default values.
$this->drupalPostForm(NULL, array('path[0][pathauto]' => FALSE), t('Save'));
$this->assertText("Updated term $name.");
// Test that the old (automatic) alias has been deleted and only accessible
// through the new (manual) alias.
$this->drupalGet($automatic_alias);
$this->assertResponse(404, 'Term not accessible through automatic alias.');
$this->drupalGet($manual_alias);
$this->assertText($name, 'Term accessible through manual alias.');
}
}

View file

@ -0,0 +1,190 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\pathauto\Entity\PathautoPattern;
use Drupal\pathauto\PathautoPatternInterface;
use Drupal\taxonomy\VocabularyInterface;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
/**
* Helper test class with some added functions for testing.
*/
trait PathautoTestHelperTrait {
/**
* Creates a pathauto pattern.
*
* @param string $entity_type_id
* The entity type.
* @param string $pattern
* The path pattern.
* @param int $weight
* (optional) The pattern weight.
*
* @return \Drupal\pathauto\PathautoPatternInterface
* The created pattern.
*/
protected function createPattern($entity_type_id, $pattern, $weight = 10) {
$type = ($entity_type_id == 'forum') ? 'forum' : 'canonical_entities:' . $entity_type_id;
$pattern = PathautoPattern::create([
'id' => Unicode::strtolower($this->randomMachineName()),
'type' => $type,
'pattern' => $pattern,
'weight' => $weight,
]);
$pattern->save();
return $pattern;
}
/**
* Add a bundle condition to a pathauto pattern.
*
* @param \Drupal\pathauto\PathautoPatternInterface $pattern
* The pattern.
* @param string $entity_type
* The entity type ID.
* @param string $bundle
* The bundle
*/
protected function addBundleCondition(PathautoPatternInterface $pattern, $entity_type, $bundle) {
$plugin_id = $entity_type == 'node' ? 'node_type' : 'entity_bundle:' . $entity_type;
$pattern->addSelectionCondition(
[
'id' => $plugin_id,
'bundles' => [
$bundle => $bundle,
],
'negate' => FALSE,
'context_mapping' => [
$entity_type => $entity_type,
]
]
);
}
public function assertToken($type, $object, $token, $expected) {
$bubbleable_metadata = new BubbleableMetadata();
$tokens = \Drupal::token()->generate($type, array($token => $token), array($type => $object), [], $bubbleable_metadata);
$tokens += array($token => '');
$this->assertIdentical($tokens[$token], $expected, t("Token value for [@type:@token] was '@actual', expected value '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $tokens[$token], '@expected' => $expected)));
}
public function saveAlias($source, $alias, $langcode = Language::LANGCODE_NOT_SPECIFIED) {
\Drupal::service('path.alias_storage')->delete(array('source' => $source, 'language', 'langcode' => $langcode));
return \Drupal::service('path.alias_storage')->save($source, $alias, $langcode);
}
public function saveEntityAlias(EntityInterface $entity, $alias, $langcode = NULL) {
// By default, use the entity language.
if (!$langcode) {
$langcode = $entity->language()->getId();
}
return $this->saveAlias('/' . $entity->toUrl()->getInternalPath(), $alias, $langcode);
}
public function assertEntityAlias(EntityInterface $entity, $expected_alias, $langcode = NULL) {
// By default, use the entity language.
if (!$langcode) {
$langcode = $entity->language()->getId();
}
$this->assertAlias('/' . $entity->toUrl()->getInternalPath(), $expected_alias, $langcode);
}
public function assertEntityAliasExists(EntityInterface $entity) {
return $this->assertAliasExists(array('source' => '/' . $entity->toUrl()->getInternalPath()));
}
public function assertNoEntityAlias(EntityInterface $entity, $langcode = NULL) {
// By default, use the entity language.
if (!$langcode) {
$langcode = $entity->language()->getId();
}
$this->assertEntityAlias($entity, '/' . $entity->toUrl()->getInternalPath(), $langcode);
}
public function assertNoEntityAliasExists(EntityInterface $entity, $alias = NULL) {
$path = array('source' => '/' . $entity->toUrl()->getInternalPath());
if (!empty($alias)) {
$path['alias'] = $alias;
}
$this->assertNoAliasExists($path);
}
public function assertAlias($source, $expected_alias, $langcode = Language::LANGCODE_NOT_SPECIFIED) {
\Drupal::service('path.alias_manager')->cacheClear($source);
$this->assertEqual($expected_alias, \Drupal::service('path.alias_manager')->getAliasByPath($source, $langcode), t("Alias for %source with language '@language' is correct.",
array('%source' => $source, '@language' => $langcode)));
}
public function assertAliasExists($conditions) {
$path = \Drupal::service('path.alias_storage')->load($conditions);
$this->assertTrue($path, t('Alias with conditions @conditions found.', array('@conditions' => var_export($conditions, TRUE))));
return $path;
}
public function assertNoAliasExists($conditions) {
$alias = \Drupal::service('path.alias_storage')->load($conditions);
$this->assertFalse($alias, t('Alias with conditions @conditions not found.', array('@conditions' => var_export($conditions, TRUE))));
}
public function deleteAllAliases() {
\Drupal::database()->delete('url_alias')->execute();
\Drupal::service('path.alias_manager')->cacheClear();
}
/**
* @param array $values
* @return \Drupal\taxonomy\VocabularyInterface
*/
public function addVocabulary(array $values = array()) {
$name = Unicode::strtolower($this->randomMachineName(5));
$values += array(
'name' => $name,
'vid' => $name,
);
$vocabulary = Vocabulary::create($values);
$vocabulary->save();
return $vocabulary;
}
public function addTerm(VocabularyInterface $vocabulary, array $values = array()) {
$values += array(
'name' => Unicode::strtolower($this->randomMachineName(5)),
'vid' => $vocabulary->id(),
);
$term = Term::create($values);
$term->save();
return $term;
}
public function assertEntityPattern($entity_type, $bundle, $langcode = Language::LANGCODE_NOT_SPECIFIED, $expected) {
$values = [
'langcode' => $langcode,
\Drupal::entityTypeManager()->getDefinition($entity_type)->getKey('bundle') => $bundle,
];
$entity = \Drupal::entityTypeManager()->getStorage($entity_type)->create($values);
$pattern = \Drupal::service('pathauto.generator')->getPatternByEntity($entity);
$this->assertIdentical($expected, $pattern->getPattern());
}
public function drupalGetTermByName($name, $reset = FALSE) {
if ($reset) {
// @todo - implement cache reset.
}
$terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties(array('name' => $name));
return !empty($terms) ? reset($terms) : FALSE;
}
}

View file

@ -0,0 +1,189 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\simpletest\WebTestBase;
use Drupal\pathauto\Entity\PathautoPattern;
/**
* Test basic pathauto functionality.
*
* @group pathauto
*/
class PathautoUiTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('pathauto', 'node');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
$this->drupalCreateContentType(array('type' => 'article'));
// Allow other modules to add additional permissions for the admin user.
$permissions = array(
'administer pathauto',
'administer url aliases',
'create url aliases',
'administer nodes',
'bypass node access',
'access content overview',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
}
function testSettingsValidation() {
$edit = array();
$edit['max_length'] = 'abc';
$edit['max_component_length'] = 'abc';
$this->drupalPostForm('admin/config/search/path/settings', $edit, 'Save configuration');
/*$this->assertText('The field Maximum alias length is not a valid number.');
$this->assertText('The field Maximum component length is not a valid number.');*/
$this->assertNoText('The configuration options have been saved.');
$edit['max_length'] = '0';
$edit['max_component_length'] = '0';
$this->drupalPostForm('admin/config/search/path/settings', $edit, 'Save configuration');
/*$this->assertText('The field Maximum alias length cannot be less than 1.');
$this->assertText('The field Maximum component length cannot be less than 1.');*/
$this->assertNoText('The configuration options have been saved.');
$edit['max_length'] = '999';
$edit['max_component_length'] = '999';
$this->drupalPostForm('admin/config/search/path/settings', $edit, 'Save configuration');
/*$this->assertText('The field Maximum alias length cannot be greater than 255.');
$this->assertText('The field Maximum component length cannot be greater than 255.');*/
$this->assertNoText('The configuration options have been saved.');
$edit['max_length'] = '50';
$edit['max_component_length'] = '50';
$this->drupalPostForm('admin/config/search/path/settings', $edit, 'Save configuration');
$this->assertText('The configuration options have been saved.');
}
function testPatternsWorkflow() {
// Try to save an empty pattern, should not be allowed.
$this->drupalGet('admin/config/search/path/patterns/add');
$edit = array(
'type' => 'canonical_entities:node',
);
$this->drupalPostAjaxForm(NULL, $edit, 'type');
$edit += array(
'bundles[page]' => TRUE,
'label' => 'Page pattern',
'id' => 'page_pattern',
);
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Path pattern field is required.');
$this->assertNoText('The configuration options have been saved.');
// Try to save an invalid pattern.
$edit += array(
'pattern' => '[node:title]/[user:name]/[term:name]',
);
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Path pattern is using the following invalid tokens: [user:name], [term:name].');
$this->assertNoText('The configuration options have been saved.');
$edit['pattern'] = '#[node:title]';
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('The Path pattern is using the following invalid characters: #.');
$this->assertNoText('The configuration options have been saved.');
// Checking whitespace ending of the string.
$edit['pattern'] = '[node:title] ';
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('The Path pattern doesn\'t allow the patterns ending with whitespace.');
$this->assertNoText('The configuration options have been saved.');
// Fix the pattern, then check that it gets saved successfully.
$edit['pattern'] = '[node:title]';
$this->drupalPostForm(NULL, $edit, 'Save');
$this->assertText('Pattern Page pattern saved.');
\Drupal::service('pathauto.generator')->resetCaches();
// Create a node with pattern enabled and check if the pattern applies.
$title = 'Page Pattern enabled';
$alias = '/page-pattern-enabled';
$node = $this->createNode(['title' => $title, 'type' => 'page']);
$this->drupalGet($alias);
$this->assertResponse(200);
$this->assertEntityAlias($node, $alias);
// Edit workflow, set a new label and weight for the pattern.
$this->drupalPostForm('/admin/config/search/path/patterns', ['entities[page_pattern][weight]' => '4'], t('Save'));
$this->clickLink(t('Edit'));
$this->assertUrl('/admin/config/search/path/patterns/page_pattern');
$this->assertFieldByName('pattern', '[node:title]');
$this->assertFieldByName('label', 'Page pattern');
$this->assertFieldChecked('edit-status');
$this->assertLink(t('Delete'));
$edit = array('label' => 'Test');
$this->drupalPostForm('/admin/config/search/path/patterns/page_pattern', $edit, t('Save'));
$this->assertText('Pattern Test saved.');
// Check that the pattern weight did not change.
$this->assertOptionSelected('edit-entities-page-pattern-weight', '4');
// Disable workflow.
$this->drupalGet('/admin/config/search/path/patterns');
$this->assertNoLink(t('Enable'));
$this->clickLink(t('Disable'));
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/disable');
$this->drupalPostForm(NULL, [], t('Disable'));
$this->assertText('Disabled pattern Test.');
// Load the pattern from storage and check if its disabled.
$pattern = PathautoPattern::load('page_pattern');
$this->assertFalse($pattern->status());
\Drupal::service('pathauto.generator')->resetCaches();
// Create a node with pattern disabled and check that we have no new alias.
$title = 'Page Pattern disabled';
$node = $this->createNode(['title' => $title, 'type' => 'page']);
$this->assertNoEntityAlias($node);
// Enable workflow.
$this->drupalGet('/admin/config/search/path/patterns');
$this->assertNoLink(t('Disable'));
$this->clickLink(t('Enable'));
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/enable');
$this->drupalPostForm(NULL, [], t('Enable'));
$this->assertText('Enabled pattern Test.');
// Reload pattern from storage and check if its enabled.
$pattern = PathautoPattern::load('page_pattern');
$this->assertTrue($pattern->status());
// Delete workflow.
$this->drupalGet('/admin/config/search/path/patterns');
$this->clickLink(t('Delete'));
$this->assertUrl('/admin/config/search/path/patterns/page_pattern/delete');
$this->assertText(t('This action cannot be undone.'));
$this->drupalPostForm(NULL, [], t('Delete'));
$this->assertText('The pathauto pattern Test has been deleted.');
$this->assertFalse(PathautoPattern::load('page_pattern'));
}
}

View file

@ -0,0 +1,92 @@
<?php
namespace Drupal\pathauto\Tests;
use Drupal\Component\Utility\Unicode;
use Drupal\simpletest\WebTestBase;
use Drupal\views\Views;
/**
* Tests pathauto user UI integration.
*
* @group pathauto
*/
class PathautoUserWebTest extends WebTestBase {
use PathautoTestHelperTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('pathauto', 'views');
/**
* Admin user.
*
* @var \Drupal\user\UserInterface
*/
protected $adminUser;
/**
* {inheritdoc}
*/
function setUp() {
parent::setUp();
// Allow other modules to add additional permissions for the admin user.
$permissions = array(
'administer pathauto',
'administer url aliases',
'create url aliases',
'administer users',
);
$this->adminUser = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->adminUser);
$this->createPattern('user', '/users/[user:name]');
}
/**
* Basic functional testing of Pathauto with users.
*/
function testUserEditing() {
// There should be no Pathauto checkbox on user forms.
$this->drupalGet('user/' . $this->adminUser->id() . '/edit');
$this->assertNoFieldById('path[0][pathauto]');
}
/**
* Test user operations.
*/
function testUserOperations() {
$account = $this->drupalCreateUser();
// Delete all current URL aliases.
$this->deleteAllAliases();
// Find the position of just created account in the user_admin_people view.
$view = Views::getView('user_admin_people');
$view->initDisplay();
$view->preview('page_1');
foreach ($view->result as $key => $row) {
if ($view->field['name']->getValue($row) == $account->getUsername()) {
break;
}
}
$edit = array(
'action' => 'pathauto_update_alias_user',
"user_bulk_form[$key]" => TRUE,
);
$this->drupalPostForm('admin/people', $edit, t('Apply to selected items'));
$this->assertText('Update URL alias was applied to 1 item.');
$this->assertEntityAlias($account, '/users/' . Unicode::strtolower($account->getUsername()));
$this->assertEntityAlias($this->adminUser, '/user/' . $this->adminUser->id());
}
}