Initial Drupal 11 with DDEV setup
This commit is contained in:
@ -0,0 +1,439 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\devel_generate\Functional;
|
||||
|
||||
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
|
||||
use Drupal\media\Entity\Media;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
|
||||
/**
|
||||
* Tests the logic to generate data.
|
||||
*
|
||||
* @group devel_generate
|
||||
*/
|
||||
class DevelGenerateBrowserTest extends DevelGenerateBrowserTestBase {
|
||||
|
||||
use MediaTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* Tests generating users.
|
||||
*/
|
||||
public function testDevelGenerateUsers(): void {
|
||||
$this->drupalGet('admin/config/development/generate/user');
|
||||
$edit = [
|
||||
'num' => 4,
|
||||
];
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('4 users created.');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that if no content types are selected an error message is shown.
|
||||
*/
|
||||
public function testDevelGenerateContent(): void {
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$edit = [
|
||||
'num' => 4,
|
||||
'title_length' => 4,
|
||||
];
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Please select at least one content type');
|
||||
|
||||
// Create a node in order to test the Delete content checkbox.
|
||||
$this->drupalCreateNode(['type' => 'article']);
|
||||
|
||||
// Generate articles with comments and aliases.
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$edit = [
|
||||
'num' => 4,
|
||||
'kill' => TRUE,
|
||||
'node_types[article]' => TRUE,
|
||||
'time_range' => 604800,
|
||||
'max_comments' => 3,
|
||||
'title_length' => 4,
|
||||
'add_alias' => 1,
|
||||
];
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Deleted 1 node');
|
||||
$this->assertSession()->pageTextContains('Created 4 nodes');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
$this->assertSession()->pageTextNotContains('translations');
|
||||
|
||||
// Tests that nodes have been created in the generation process.
|
||||
$nodes = Node::loadMultiple();
|
||||
$this->assertEquals(4, count($nodes), 'Nodes generated successfully.');
|
||||
|
||||
// Tests url alias for the generated nodes.
|
||||
foreach ($nodes as $node) {
|
||||
$alias = 'node-' . $node->id() . '-' . $node->bundle();
|
||||
$this->drupalGet($alias);
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->pageTextContains($node->getTitle());
|
||||
}
|
||||
|
||||
// Generate articles with translations.
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$edit = [
|
||||
'num' => 3,
|
||||
'kill' => TRUE,
|
||||
'node_types[article]' => TRUE,
|
||||
'add_language[]' => ['en'],
|
||||
'translate_language[]' => ['de', 'ca'],
|
||||
'add_alias' => TRUE,
|
||||
];
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Deleted 4 nodes');
|
||||
$this->assertSession()->pageTextContains('Created 3 nodes');
|
||||
// Two translations for each node makes six.
|
||||
$this->assertSession()->pageTextContains('Created 6 node translations');
|
||||
$articles = \Drupal::entityQuery('node')->accessCheck(FALSE)->execute();
|
||||
$this->assertCount(3, $articles);
|
||||
$node = Node::load(end($articles));
|
||||
$this->assertTrue($node->hasTranslation('de'));
|
||||
$this->assertTrue($node->hasTranslation('ca'));
|
||||
$this->assertFalse($node->hasTranslation('fr'));
|
||||
|
||||
// Check url alias for each of the translations.
|
||||
foreach (Node::loadMultiple($articles) as $node) {
|
||||
foreach (['de', 'ca'] as $langcode) {
|
||||
$translation_node = $node->getTranslation($langcode);
|
||||
$alias = 'node-' . $translation_node->id() . '-' . $translation_node->bundle() . '-' . $langcode;
|
||||
$this->drupalGet($langcode . '/' . $alias);
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->pageTextContains($translation_node->getTitle());
|
||||
}
|
||||
}
|
||||
|
||||
// Create article to make sure it is not deleted when only killing pages.
|
||||
$article = $this->drupalCreateNode(['type' => 'article', 'title' => 'Alive']);
|
||||
// The 'page' content type is not enabled for translation.
|
||||
$edit = [
|
||||
'num' => 2,
|
||||
'kill' => TRUE,
|
||||
'node_types[page]' => TRUE,
|
||||
'add_language[]' => ['en'],
|
||||
'translate_language[]' => ['fr'],
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextNotContains('Deleted');
|
||||
$this->assertSession()->pageTextContains('Created 2 nodes');
|
||||
$this->assertSession()->pageTextNotContains('node translations');
|
||||
// Check that 'kill' has not deleted the article.
|
||||
$this->assertNotEmpty(Node::load($article->id()));
|
||||
$pages = \Drupal::entityQuery('node')->condition('type', 'page')->accessCheck(FALSE)->execute();
|
||||
$this->assertCount(2, $pages);
|
||||
$node = Node::load(end($pages));
|
||||
$this->assertFalse($node->hasTranslation('fr'));
|
||||
|
||||
// Create articles with add-type-label option.
|
||||
$edit = [
|
||||
'num' => 5,
|
||||
'kill' => TRUE,
|
||||
'node_types[article]' => TRUE,
|
||||
'add_type_label' => TRUE,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Created 5 nodes');
|
||||
$this->assertSession()->pageTextContains('Generate process complete');
|
||||
|
||||
// Count the articles created in the generation process.
|
||||
$nodes = \Drupal::entityQuery('node')->accessCheck(FALSE)->condition('type', 'article')->execute();
|
||||
$this->assertCount(5, $nodes);
|
||||
|
||||
// Load the final node and verify that the title starts with the label.
|
||||
$node = Node::load(end($nodes));
|
||||
$this->assertEquals('Article - ', substr($node->title->value, 0, 10));
|
||||
|
||||
// Test creating content with specified authors. First create 15 more users
|
||||
// making 18 in total, to make the test much stronger.
|
||||
for ($i = 0; $i < 15; ++$i) {
|
||||
$this->drupalCreateUser();
|
||||
}
|
||||
|
||||
$edit = [
|
||||
'num' => 10,
|
||||
'kill' => TRUE,
|
||||
'node_types[article]' => TRUE,
|
||||
'authors[3]' => TRUE,
|
||||
'authors[4]' => TRUE,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
|
||||
// Display the full content list for information and debug only.
|
||||
$this->drupalGet('admin/content');
|
||||
|
||||
// Count all the articles by user 3 and 4 and by others. We count the two
|
||||
// users nodes separately to ensure that there are some by each user.
|
||||
$nodes_by_user_3 = \Drupal::entityQuery('node')->accessCheck(FALSE)->condition('type', 'article')->condition('uid', ['3'], 'IN')->execute();
|
||||
$nodes_by_user_4 = \Drupal::entityQuery('node')->accessCheck(FALSE)->condition('type', 'article')->condition('uid', ['4'], 'IN')->execute();
|
||||
$nodes_by_others = \Drupal::entityQuery('node')->accessCheck(FALSE)->condition('type', 'article')->condition('uid', ['3', '4'], 'NOT IN')->execute();
|
||||
|
||||
// If the user option was not working correctly and users were assigned at
|
||||
// random, then the chance that these assertions will correctly detect the
|
||||
// error is 1 - (2/18 ** 10) = 99.99%.
|
||||
$this->assertEquals(10, count($nodes_by_user_3) + count($nodes_by_user_4));
|
||||
$this->assertCount(0, $nodes_by_others);
|
||||
|
||||
// If the user option is coded correctly the chance of either of these
|
||||
// assertions giving a false failure is 1/2 ** 10 = 0.097%.
|
||||
$this->assertGreaterThan(0, count($nodes_by_user_3));
|
||||
$this->assertGreaterThan(0, count($nodes_by_user_4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating terms.
|
||||
*/
|
||||
public function testDevelGenerateTerms(): void {
|
||||
// Generate terms.
|
||||
$edit = [
|
||||
'vids[]' => $this->vocabulary->id(),
|
||||
'num' => 5,
|
||||
'title_length' => 12,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/term');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Created 5 new terms');
|
||||
$this->assertSession()->pageTextContains('In vocabulary ' . $this->vocabulary->label());
|
||||
$this->assertSession()->pageTextNotContains('translations');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
$this->assertCount(5, \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->execute());
|
||||
|
||||
// Generate terms with translations.
|
||||
$edit = [
|
||||
'vids[]' => $this->vocabulary->id(),
|
||||
'num' => 3,
|
||||
'add_language[]' => ['en'],
|
||||
'translate_language[]' => ['ca'],
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/term');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextNotContains('Deleted');
|
||||
$this->assertSession()->pageTextContains('Created 3 new terms');
|
||||
$this->assertSession()->pageTextContains('Created 3 term translations');
|
||||
// Not using 'kill' so there should be 8 terms.
|
||||
$terms = \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->execute();
|
||||
$this->assertCount(8, $terms);
|
||||
// Check the translations created (and not created).
|
||||
$term = Term::load(end($terms));
|
||||
$this->assertTrue($term->hasTranslation('ca'));
|
||||
$this->assertFalse($term->hasTranslation('de'));
|
||||
$this->assertFalse($term->hasTranslation('fr'));
|
||||
|
||||
// Generate terms in vocabulary 2 only.
|
||||
$edit = [
|
||||
'vids[]' => $this->vocabulary2->id(),
|
||||
'num' => 4,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/term');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Created 4 new terms');
|
||||
$this->assertSession()->pageTextNotContains('In vocabulary ' . $this->vocabulary->label());
|
||||
$this->assertSession()->pageTextContains('In vocabulary ' . $this->vocabulary2->label());
|
||||
// Check the term count in each vocabulary.
|
||||
$terms1 = \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->condition('vid', $this->vocabulary->id())->execute();
|
||||
$this->assertCount(8, $terms1);
|
||||
$terms2 = \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->condition('vid', $this->vocabulary2->id())->execute();
|
||||
$this->assertCount(4, $terms2);
|
||||
|
||||
// Generate in vocabulary 2 with 'kill' to remove the existing vocab2 terms.
|
||||
$edit = [
|
||||
'vids[]' => $this->vocabulary2->id(),
|
||||
'num' => 6,
|
||||
'kill' => TRUE,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/term');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Deleted 4 existing terms');
|
||||
$this->assertSession()->pageTextContains('Created 6 new terms');
|
||||
// Check the term count in vocabulary 1 has not changed.
|
||||
$terms1 = \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->condition('vid', $this->vocabulary->id())->execute();
|
||||
$this->assertCount(8, $terms1);
|
||||
// Check the term count in vocabulary 2 is just from the second call.
|
||||
$terms2 = \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->condition('vid', $this->vocabulary2->id())->execute();
|
||||
$this->assertCount(6, $terms2);
|
||||
|
||||
// Generate in both vocabularies and specify minimum and maximum depth.
|
||||
$edit = [
|
||||
'vids[]' => [$this->vocabulary->id(), $this->vocabulary2->id()],
|
||||
'num' => 9,
|
||||
'minimum_depth' => 2,
|
||||
'maximum_depth' => 6,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/term');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Created 9 new terms');
|
||||
// Check the total term count is 8 + 6 + 9 = 23.
|
||||
$terms1 = \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->condition('vid', $this->vocabulary->id())->execute();
|
||||
$terms2 = \Drupal::entityQuery('taxonomy_term')->accessCheck(FALSE)->condition('vid', $this->vocabulary2->id())->execute();
|
||||
$this->assertCount(23, $terms1 + $terms2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating vocabularies.
|
||||
*/
|
||||
public function testDevelGenerateVocabs(): void {
|
||||
$edit = [
|
||||
'num' => 5,
|
||||
'title_length' => 12,
|
||||
'kill' => TRUE,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/vocabs');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Created the following new vocabularies: ');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating menus.
|
||||
*
|
||||
* @todo Add test coverage to check:
|
||||
* - title_length is not exceeded.
|
||||
* - max_depth and max_width work as designed.
|
||||
* - generating links in existing menus, and then deleting them with kill.
|
||||
* - using specific link_types settings only create those links.
|
||||
*/
|
||||
public function testDevelGenerateMenus(): void {
|
||||
$edit = [
|
||||
'num_menus' => 5,
|
||||
'num_links' => 7,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/menu');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Created the following 5 new menus: ');
|
||||
$this->assertSession()->pageTextContains('Created 7 new menu links');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
|
||||
// Use big numbers for menus and links, but short text, to test for clashes.
|
||||
// Also verify the kill option.
|
||||
$edit = [
|
||||
'num_menus' => 160,
|
||||
'num_links' => 380,
|
||||
'title_length' => 3,
|
||||
'kill' => 1,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/menu');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Deleted 5 menu(s) and 0 other link(s).');
|
||||
$this->assertSession()->pageTextContains('Created the following 160 new menus: ');
|
||||
$this->assertSession()->pageTextContains('Created 380 new menu links');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating media.
|
||||
*/
|
||||
public function testDevelGenerateMedia(): void {
|
||||
// As the 'media' plugin has a dependency on 'media' module, the plugin is
|
||||
// not generating a route to the plugin form.
|
||||
$this->drupalGet('admin/config/development/generate/media');
|
||||
$this->assertSession()->statusCodeEquals(404);
|
||||
// Enable the module and retry.
|
||||
\Drupal::service('module_installer')->install(['media']);
|
||||
$this->getSession()->reload();
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->pageTextContains('Generate media');
|
||||
|
||||
// Create two media types.
|
||||
$media_type1 = $this->createMediaType('image');
|
||||
$media_type2 = $this->createMediaType('audio_file');
|
||||
|
||||
// Creating media items (non-batch mode).
|
||||
$edit = [
|
||||
'num' => 5,
|
||||
'name_length' => 12,
|
||||
sprintf('media_types[%s]', $media_type1->id()) => 1,
|
||||
sprintf('media_types[%s]', $media_type2->id()) => 1,
|
||||
'base_fields' => 'phish',
|
||||
'kill' => 1,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/media');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Finished creating 5 media items.');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
$medias = \Drupal::entityQuery('media')->accessCheck(FALSE)->execute();
|
||||
$this->assertCount(5, $medias);
|
||||
$media = Media::load(end($medias));
|
||||
$this->assertNotEmpty($media->get('phish')->getString());
|
||||
|
||||
// Creating media items (batch mode).
|
||||
$edit = [
|
||||
'num' => 56,
|
||||
'name_length' => 6,
|
||||
sprintf('media_types[%s]', $media_type1->id()) => 1,
|
||||
sprintf('media_types[%s]', $media_type2->id()) => 1,
|
||||
'base_fields' => 'phish',
|
||||
'kill' => 1,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/media');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Finished 56 elements created successfully.');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
$this->assertCount(56, \Drupal::entityQuery('media')->accessCheck(FALSE)->execute());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating content in batch mode.
|
||||
*/
|
||||
public function testDevelGenerateBatchContent(): void {
|
||||
// For 50 or more nodes, the processing will be done via batch.
|
||||
$edit = [
|
||||
'num' => 55,
|
||||
'kill' => TRUE,
|
||||
'node_types[article]' => TRUE,
|
||||
'node_types[page]' => TRUE,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertSession()->pageTextContains('Finished 55 elements created successfully.');
|
||||
$this->assertSession()->pageTextContains('Generate process complete.');
|
||||
|
||||
// Tests that the expected number of nodes have been created.
|
||||
$count = count(Node::loadMultiple());
|
||||
$this->assertEquals(55, $count, sprintf('The expected total number of nodes is %s, found %s', 55, $count));
|
||||
|
||||
// Create nodes with translations via batch.
|
||||
$edit = [
|
||||
'num' => 52,
|
||||
'kill' => TRUE,
|
||||
'node_types[article]' => TRUE,
|
||||
'node_types[page]' => TRUE,
|
||||
'add_language[]' => ['en'],
|
||||
'translate_language[]' => ['de', 'ca'],
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
$this->assertCount(52, \Drupal::entityQuery('node')->accessCheck(FALSE)->execute());
|
||||
// Only articles will have translations so get that number.
|
||||
$articles = \Drupal::entityQuery('node')->accessCheck(FALSE)->condition('type', 'article')->execute();
|
||||
$this->assertSession()->pageTextContains(sprintf('Finished 52 elements and %s translations created successfully.', 2 * count($articles)));
|
||||
|
||||
// Generate only articles.
|
||||
$edit = [
|
||||
'num' => 60,
|
||||
'kill' => TRUE,
|
||||
'node_types[article]' => TRUE,
|
||||
'node_types[page]' => FALSE,
|
||||
];
|
||||
$this->drupalGet('admin/config/development/generate/content');
|
||||
$this->submitForm($edit, 'Generate');
|
||||
|
||||
// Tests that all the created nodes were of the node type selected.
|
||||
$nodeStorage = $this->container->get('entity_type.manager')->getStorage('node');
|
||||
$type = 'article';
|
||||
$count = $nodeStorage->getQuery()
|
||||
->condition('type', $type)
|
||||
->accessCheck(FALSE)
|
||||
->count()
|
||||
->execute();
|
||||
$this->assertEquals(60, $count, sprintf('The expected number of %s is %s, found %s', $type, 60, $count));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\devel_generate\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\devel_generate\Traits\DevelGenerateSetupTrait;
|
||||
|
||||
/**
|
||||
* Base class for devel_generate functional browser tests.
|
||||
*
|
||||
* DevelGenerateCommandsTest should not extend this class so that it can remain
|
||||
* independent and be used as a cut-and-paste example for other developers.
|
||||
*/
|
||||
abstract class DevelGenerateBrowserTestBase extends BrowserTestBase {
|
||||
|
||||
use DevelGenerateSetupTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected static $modules = [
|
||||
'content_translation',
|
||||
'devel',
|
||||
'devel_generate',
|
||||
'devel_generate_fields',
|
||||
'language',
|
||||
'menu_ui',
|
||||
'node',
|
||||
'comment',
|
||||
'taxonomy',
|
||||
'path',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Prepares the testing environment.
|
||||
*/
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->setUpData();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,320 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\devel_generate\Functional;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\devel_generate\Traits\DevelGenerateSetupTrait;
|
||||
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
|
||||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\devel_generate\Drush\Commands\DevelGenerateCommands;
|
||||
use Drupal\media\Entity\Media;
|
||||
use Drupal\menu_link_content\Entity\MenuLinkContent;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\system\Entity\Menu;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\user\Entity\User;
|
||||
use Drush\TestTraits\DrushTestTrait;
|
||||
|
||||
/**
|
||||
* Test class for the Devel Generate drush commands.
|
||||
*
|
||||
* Note: Drush must be in the Composer project.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\devel_generate\Drush\Commands\DevelGenerateCommands
|
||||
* @group devel_generate
|
||||
*/
|
||||
class DevelGenerateCommandsTest extends BrowserTestBase {
|
||||
|
||||
use DrushTestTrait;
|
||||
use DevelGenerateSetupTrait;
|
||||
use MediaTypeCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'comment',
|
||||
'content_translation',
|
||||
'devel',
|
||||
'devel_generate',
|
||||
'devel_generate_fields',
|
||||
'language',
|
||||
'media',
|
||||
'menu_ui',
|
||||
'node',
|
||||
'path',
|
||||
'taxonomy',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $defaultTheme = 'stark';
|
||||
|
||||
/**
|
||||
* Prepares the testing environment.
|
||||
*/
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->setUpData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating users.
|
||||
*/
|
||||
public function testDrushGenerateUsers(): void {
|
||||
// Make sure users get created, and with correct roles.
|
||||
$this->drush(DevelGenerateCommands::USERS, ['55'], [
|
||||
'kill' => NULL,
|
||||
'roles' => 'administrator',
|
||||
]);
|
||||
$user = User::load(55);
|
||||
$this->assertTrue($user->hasRole('administrator'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating terms.
|
||||
*/
|
||||
public function testDrushGenerateTerms(): void {
|
||||
// Make sure terms get created, and with correct vocab.
|
||||
$this->drush(DevelGenerateCommands::TERMS, ['55'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => $this->vocabulary->id(),
|
||||
]);
|
||||
$term = Term::load(55);
|
||||
$this->assertEquals($this->vocabulary->id(), $term->bundle());
|
||||
|
||||
// Make sure terms get created, with proper language.
|
||||
$this->drush(DevelGenerateCommands::TERMS, ['10'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => $this->vocabulary->id(),
|
||||
'languages' => 'fr',
|
||||
]);
|
||||
$term = Term::load(60);
|
||||
$this->assertEquals('fr', $term->language()->getId());
|
||||
|
||||
// Make sure terms gets created, with proper translation.
|
||||
$this->drush(DevelGenerateCommands::TERMS, ['10'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => $this->vocabulary->id(),
|
||||
'languages' => 'fr',
|
||||
'translations' => 'de',
|
||||
]);
|
||||
$term = Term::load(70);
|
||||
$this->assertTrue($term->hasTranslation('de'));
|
||||
$this->assertTrue($term->hasTranslation('fr'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating vocabularies.
|
||||
*/
|
||||
public function testDrushGenerateVocabs(): void {
|
||||
// Make sure vocabs get created.
|
||||
$this->drush(DevelGenerateCommands::VOCABS, ['5'], ['kill' => NULL]);
|
||||
$vocabs = Vocabulary::loadMultiple();
|
||||
$this->assertGreaterThan(4, count($vocabs));
|
||||
$vocab = array_pop($vocabs);
|
||||
$this->assertNotEmpty($vocab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating menus.
|
||||
*/
|
||||
public function testDrushGenerateMenus(): void {
|
||||
$generatedMenu = NULL;
|
||||
|
||||
// Make sure menus, and with correct properties.
|
||||
$this->drush(DevelGenerateCommands::MENUS, ['1', '5'], ['kill' => NULL]);
|
||||
$menus = Menu::loadMultiple();
|
||||
foreach ($menus as $menu) {
|
||||
if (str_contains($menu->id(), 'devel-')) {
|
||||
// We have a menu that we created.
|
||||
$generatedMenu = $menu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$link = MenuLinkContent::load(5);
|
||||
|
||||
$this->assertNotNull($generatedMenu, 'Generated menu successfully.');
|
||||
$this->assertNotNull($link, 'Generated link successfully.');
|
||||
$this->assertEquals($generatedMenu->id(), $link->getMenuName(), 'Generated menu ID matches link menu name.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating content.
|
||||
*/
|
||||
public function testDrushGenerateContent(): void {
|
||||
// Generate content using the minimum parameters.
|
||||
$this->drush(DevelGenerateCommands::CONTENT, ['21']);
|
||||
$node = Node::load(21);
|
||||
$this->assertNotEmpty($node);
|
||||
|
||||
// Make sure articles get comments. Only one third of articles will have
|
||||
// comment status 'open' and therefore the ability to receive a comment.
|
||||
// However, generating 30 articles will give the likelihood of test failure
|
||||
// (i.e. no article gets a comment) as 2/3 ^ 30 = 0.00052% or 1 in 191751.
|
||||
$this->drush(DevelGenerateCommands::CONTENT, ['30', '9'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => 'article',
|
||||
]);
|
||||
$comment = Comment::load(1);
|
||||
$this->assertNotEmpty($comment);
|
||||
|
||||
// Generate content with a higher number that triggers batch running.
|
||||
$this->drush(DevelGenerateCommands::CONTENT, ['55'], ['kill' => NULL]);
|
||||
$nodes = \Drupal::entityQuery('node')->accessCheck(FALSE)->execute();
|
||||
$this->assertCount(55, $nodes);
|
||||
$messages = $this->getErrorOutput();
|
||||
$this->assertStringContainsStringIgnoringCase('Finished 55 elements created successfully.', $messages, 'devel-generate-content batch ending message not found');
|
||||
|
||||
// Generate specified language. Verify base field is populated.
|
||||
$this->drush(DevelGenerateCommands::CONTENT, ['10'], [
|
||||
'kill' => NULL,
|
||||
'languages' => 'fr',
|
||||
'base-fields' => 'phish',
|
||||
]);
|
||||
$nodes = \Drupal::entityQuery('node')->accessCheck(FALSE)->execute();
|
||||
$node = Node::load(end($nodes));
|
||||
$this->assertEquals('fr', $node->language()->getId());
|
||||
$this->assertNotEmpty($node->get('phish')->getString());
|
||||
|
||||
// Generate content with translations.
|
||||
$this->drush(DevelGenerateCommands::CONTENT, ['18'], [
|
||||
'kill' => NULL,
|
||||
'languages' => 'fr',
|
||||
'translations' => 'de',
|
||||
]);
|
||||
// Only articles are enabled for translations.
|
||||
$articles = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('type', 'article')
|
||||
->execute();
|
||||
$pages = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('type', 'page')
|
||||
->execute();
|
||||
$this->assertCount(18, $articles + $pages);
|
||||
// Check that the last article has 'de' and 'fr' but no 'ca' translation.
|
||||
$node = Node::load(end($articles));
|
||||
$this->assertTrue($node->hasTranslation('de'));
|
||||
$this->assertTrue($node->hasTranslation('fr'));
|
||||
$this->assertFalse($node->hasTranslation('ca'));
|
||||
|
||||
// Generate just page content with option --add-type-label.
|
||||
// Note: Use the -v verbose option to get the ending message shown when not
|
||||
// generating enough to trigger batch mode.
|
||||
// @todo Remove -v when the messages are shown for both run types.
|
||||
$this->drush(DevelGenerateCommands::CONTENT . ' -v', ['9'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => 'page',
|
||||
'add-type-label' => NULL,
|
||||
]);
|
||||
// Count the page nodes.
|
||||
$nodes = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('type', 'page')
|
||||
->execute();
|
||||
$this->assertCount(9, $nodes);
|
||||
$messages = $this->getErrorOutput();
|
||||
$this->assertStringContainsStringIgnoringCase('Created 9 nodes', $messages, 'batch end message not found');
|
||||
// Load the final node and verify that the title starts with the label.
|
||||
$node = Node::load(end($nodes));
|
||||
$this->assertEquals('Basic Page - ', substr($node->title->value, 0, 13));
|
||||
|
||||
// Generate articles with a specified users.
|
||||
$this->drush(DevelGenerateCommands::CONTENT . ' -v', ['10'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => 'article',
|
||||
'authors' => '2',
|
||||
]);
|
||||
// Count the nodes assigned to user 2. We have two other users (0 and 1) so
|
||||
// if the code was broken and users were assigned randomly the chance that
|
||||
// this fauly would be detected is 1 - (1/3 ** 10) = 99.998%.
|
||||
$nodes = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('type', 'article')
|
||||
->condition('uid', ['2'], 'IN')
|
||||
->execute();
|
||||
$this->assertCount(10, $nodes);
|
||||
|
||||
// Generate page content using the 'roles' option to select authors based
|
||||
// on the roles that the user has. For this we need a new user with a
|
||||
// distinct role.
|
||||
$userA = $this->drupalCreateUser(['access content']);
|
||||
$roleA = $userA->getRoles()[1];
|
||||
$this->drush(DevelGenerateCommands::CONTENT . ' -v', ['8'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => 'page',
|
||||
'roles' => $roleA,
|
||||
]);
|
||||
// Count the number of nodes assigned to User A. There are three other users
|
||||
// so if the code was broken and authors assigned randomly, the chance that
|
||||
// this test would detect the fault is 1 - (1/4 ^ 8) = 99.998%.
|
||||
$nodesA = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('type', 'page')
|
||||
->condition('uid', $userA->id())
|
||||
->execute();
|
||||
$this->assertCount(8, $nodesA, 'User A should have all the generated content');
|
||||
|
||||
// Repeat the above using two roles and two users.
|
||||
$userB = $this->drupalCreateUser(['create page content']);
|
||||
$roleB = $userB->getRoles()[1];
|
||||
$this->drush(DevelGenerateCommands::CONTENT . ' -v', ['20'], [
|
||||
'kill' => NULL,
|
||||
'bundles' => 'page',
|
||||
'roles' => sprintf('%s, %s', $roleA, $roleB),
|
||||
]);
|
||||
// Count the nodes assigned to users A and B. There are three other users
|
||||
// so if the code was broken and users were assigned randomly the chance
|
||||
// that the test would detect the fault is 1 - (2/5 ^ 20) = 99.999%.
|
||||
$nodesA = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('type', 'page')
|
||||
->condition('uid', $userA->id())
|
||||
->execute();
|
||||
$nodesB = \Drupal::entityQuery('node')
|
||||
->accessCheck(FALSE)
|
||||
->condition('type', 'page')
|
||||
->condition('uid', $userB->id())
|
||||
->execute();
|
||||
$this->assertGreaterThan(0, count($nodesA), 'User A should have some content');
|
||||
$this->assertGreaterThan(0, count($nodesB), 'User B should have some content');
|
||||
$this->assertCount(20, $nodesA + $nodesB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests generating media.
|
||||
*/
|
||||
public function testDrushGenerateMedia(): void {
|
||||
// Create two media types.
|
||||
$media_type1 = $this->createMediaType('image');
|
||||
$media_type2 = $this->createMediaType('audio_file');
|
||||
// Make sure media items gets created with batch process.
|
||||
$this->drush(DevelGenerateCommands::MEDIA, ['53'], [
|
||||
'kill' => NULL,
|
||||
'base-fields' => 'phish',
|
||||
]);
|
||||
$this->assertCount(53, \Drupal::entityQuery('media')
|
||||
->accessCheck(FALSE)
|
||||
->execute());
|
||||
$messages = $this->getErrorOutput();
|
||||
$this->assertStringContainsStringIgnoringCase('Finished 53 elements created successfully.', $messages, 'devel-generate-media batch ending message not found');
|
||||
$medias = \Drupal::entityQuery('media')->accessCheck(FALSE)->execute();
|
||||
$media = Media::load(end($medias));
|
||||
// Verify that base field populates.
|
||||
$this->assertNotEmpty($media->get('phish')->getString());
|
||||
|
||||
// Test also with a non-batch process. We're testing also --kill here.
|
||||
$this->drush(DevelGenerateCommands::MEDIA, ['7'], [
|
||||
'media-types' => $media_type1->id() . ',' . $media_type2->id(),
|
||||
'kill' => NULL,
|
||||
]);
|
||||
$this->assertCount(7, \Drupal::entityQuery('media')
|
||||
->accessCheck(FALSE)
|
||||
->execute());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\devel_generate\Traits;
|
||||
|
||||
use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Tests\field\Traits\EntityReferenceFieldCreationTrait;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
|
||||
/**
|
||||
* Provides methods to assist Devel Generate testing.
|
||||
*
|
||||
* Referenced in DevelGenerateBrowserTestBase and DevelGenerateCommandsTest.
|
||||
*/
|
||||
trait DevelGenerateSetupTrait {
|
||||
|
||||
use CommentTestTrait;
|
||||
use EntityReferenceFieldCreationTrait;
|
||||
|
||||
/**
|
||||
* Vocabulary for testing generation of terms.
|
||||
*
|
||||
* @var \Drupal\taxonomy\VocabularyInterface
|
||||
*/
|
||||
protected $vocabulary;
|
||||
|
||||
/**
|
||||
* Second vocabulary for testing generation of terms.
|
||||
*
|
||||
* @var \Drupal\taxonomy\VocabularyInterface
|
||||
*/
|
||||
protected $vocabulary2;
|
||||
|
||||
/**
|
||||
* General set-up for all tests.
|
||||
*/
|
||||
public function setUpData(): void {
|
||||
// Create user with devel_generate permissions and access to admin/content.
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'administer devel_generate',
|
||||
'access devel information',
|
||||
'access content overview',
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$entity_type_manager = $this->container->get('entity_type.manager');
|
||||
// Create Basic page and Article node types.
|
||||
if ($this->profile != 'standard') {
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Basic Page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
$this->addDefaultCommentField('node', 'article');
|
||||
}
|
||||
|
||||
// Enable translation for article content type (but not for page).
|
||||
\Drupal::service('content_translation.manager')->setEnabled('node', 'article', TRUE);
|
||||
// Create languages for generated translations.
|
||||
ConfigurableLanguage::createFromLangcode('ca')->save();
|
||||
ConfigurableLanguage::createFromLangcode('de')->save();
|
||||
ConfigurableLanguage::createFromLangcode('fr')->save();
|
||||
|
||||
// Creating a vocabulary to associate taxonomy terms generated.
|
||||
$this->vocabulary = Vocabulary::create([
|
||||
'name' => 'Vocab 1 ' . $this->randomString(15),
|
||||
'description' => $this->randomMachineName(),
|
||||
'vid' => 'vocab_1_' . mb_strtolower($this->randomMachineName()),
|
||||
'langcode' => Language::LANGCODE_NOT_SPECIFIED,
|
||||
]);
|
||||
$this->vocabulary->save();
|
||||
// Enable translation for terms in this vocabulary.
|
||||
\Drupal::service('content_translation.manager')->setEnabled('taxonomy_term', $this->vocabulary->id(), TRUE);
|
||||
|
||||
// Creates a field of an entity reference field storage on article.
|
||||
$field_name = 'taxonomy_' . $this->vocabulary->id();
|
||||
|
||||
$handler_settings = [
|
||||
'target_bundles' => [
|
||||
$this->vocabulary->id() => $this->vocabulary->id(),
|
||||
],
|
||||
'auto_create' => TRUE,
|
||||
];
|
||||
$this->createEntityReferenceField('node', 'article', $field_name, '', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
|
||||
|
||||
$entity_type_manager->getStorage('entity_form_display')
|
||||
->load('node.article.default')
|
||||
->setComponent($field_name, [
|
||||
'type' => 'options_select',
|
||||
])
|
||||
->save();
|
||||
|
||||
$entity_type_manager->getStorage('entity_view_display')
|
||||
->load('node.article.default')
|
||||
->setComponent($field_name, [
|
||||
'type' => 'entity_reference_label',
|
||||
])
|
||||
->save();
|
||||
|
||||
// Create the second vocabulary.
|
||||
$this->vocabulary2 = Vocabulary::create([
|
||||
'name' => 'Vocab 2 ' . $this->randomString(15),
|
||||
'vid' => 'vocab_2_' . mb_strtolower($this->randomMachineName()),
|
||||
'langcode' => Language::LANGCODE_NOT_SPECIFIED,
|
||||
]);
|
||||
$this->vocabulary2->save();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\devel_generate\Unit;
|
||||
|
||||
use Drupal\Component\Datetime\TimeInterface;
|
||||
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Entity\EntityFieldManagerInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManager;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\devel_generate\DevelGeneratePluginManager;
|
||||
use Drupal\devel_generate_example\Plugin\DevelGenerate\ExampleDevelGenerate;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\devel_generate\DevelGeneratePluginManager
|
||||
* @group devel_generate
|
||||
*/
|
||||
class DevelGenerateManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The plugin discovery.
|
||||
*/
|
||||
protected MockObject|DiscoveryInterface $discovery;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
// Mock the plugin discovery.
|
||||
$this->discovery = $this->createMock(DiscoveryInterface::class);
|
||||
$this->discovery->expects($this->any())
|
||||
->method('getDefinitions')
|
||||
->willReturnCallback(function (): array {
|
||||
return $this->getMockDefinitions();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating an instance of the DevelGenerateManager.
|
||||
*/
|
||||
public function testCreateInstance(): void {
|
||||
$namespaces = new \ArrayObject(['Drupal\devel_generate_example' => realpath(__DIR__ . '/../../../modules/devel_generate_example/lib')]);
|
||||
$cache_backend = $this->createMock(CacheBackendInterface::class);
|
||||
$module_handler = $this->createMock(ModuleHandlerInterface::class);
|
||||
$entity_type_manager = $this->createMock(EntityTypeManager::class);
|
||||
$messenger = $this->createMock(MessengerInterface::class);
|
||||
$language_manager = $this->createMock(LanguageManagerInterface::class);
|
||||
$string_translation = $this->createMock(TranslationInterface::class);
|
||||
$entityFieldManager = $this->createMock(EntityFieldManagerInterface::class);
|
||||
|
||||
$manager = new DevelGeneratePluginManager(
|
||||
$namespaces,
|
||||
$cache_backend,
|
||||
$module_handler,
|
||||
$entity_type_manager,
|
||||
$messenger,
|
||||
$language_manager,
|
||||
$string_translation,
|
||||
$entityFieldManager,
|
||||
);
|
||||
|
||||
// Use reflection to set the protected discovery property.
|
||||
$reflection = new \ReflectionClass($manager);
|
||||
$property = $reflection->getProperty('discovery');
|
||||
$property->setValue($manager, $this->discovery);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$time = $this->createMock(TimeInterface::class);
|
||||
$container->set('entity_type.manager', $entity_type_manager);
|
||||
$container->set('messenger', $messenger);
|
||||
$container->set('language_manager', $language_manager);
|
||||
$container->set('module_handler', $module_handler);
|
||||
$container->set('string_translation', $string_translation);
|
||||
$container->set('entity_field.manager', $entityFieldManager);
|
||||
$container->set('datetime.time', $time);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$example_instance = $manager->createInstance('devel_generate_example');
|
||||
$plugin_def = $example_instance->getPluginDefinition();
|
||||
|
||||
$this->assertInstanceOf(ExampleDevelGenerate::class, $example_instance);
|
||||
$this->assertArrayHasKey('url', $plugin_def);
|
||||
$this->assertTrue($plugin_def['url'] == 'devel_generate_example');
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function to return mock definitions.
|
||||
*
|
||||
* @return array
|
||||
* The mock of devel generate plugin definitions.
|
||||
*/
|
||||
public function getMockDefinitions(): array {
|
||||
return [
|
||||
'devel_generate_example' => [
|
||||
'id' => 'devel_generate_example',
|
||||
'class' => ExampleDevelGenerate::class,
|
||||
'url' => 'devel_generate_example',
|
||||
'dependencies' => [],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user