improvements-2.x-dev/tests/src/Traits/ImprovementsTestTrait.php
tests/src/Traits/ImprovementsTestTrait.php
<?php
namespace Drupal\Tests\improvements\Traits;
use Drupal\block\BlockInterface;
use Drupal\block_content\BlockContentInterface;
use Drupal\block_content\BlockContentTypeInterface;
use Drupal\block_content\Entity\BlockContent;
use Drupal\block_content\Entity\BlockContentType;
use Drupal\comment\CommentInterface;
use Drupal\comment\Entity\Comment;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\filter\Entity\FilterFormat;
use Drupal\filter\FilterFormatInterface;
use Drupal\menu_link_content\Entity\MenuLinkContent;
use Drupal\menu_link_content\MenuLinkContentInterface;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\node\NodeStorageInterface;
use Drupal\system\Entity\Menu;
use Drupal\system\MenuInterface;
use Drupal\Tests\block\Traits\BlockCreationTrait;
use Drupal\Tests\RandomGeneratorTrait;
use Drupal\Tests\UiHelperTrait;
use Drupal\views\Entity\View;
use Drupal\views\ViewEntityInterface;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
trait ImprovementsTestTrait {
use BlockCreationTrait;
use RandomGeneratorTrait;
use UiHelperTrait;
/**
* Install module.
*/
public function installModule(...$modules): void {
$this->container->get('module_installer')->install($modules);
}
/**
* Run all private tests.
*/
public function runAllPrivateTests(): void {
foreach (get_class_methods(self::class) as $class_method) {
if (str_starts_with($class_method, '_test')) {
$result = $this->{$class_method}();
if ($result === FALSE) {
break;
}
}
}
}
/**
* Create content block.
*/
public function createBlockContent(array $values = []): BlockContentInterface {
$block_content = BlockContent::create($values + [
'info' => $this->randomString(),
'type' => 'basic',
'body' => [
'value' => $this->randomString(),
'format' => 'plain_text',
],
]);
$block_content->save();
return $block_content;
}
/**
* Place content block.
*/
public function placeBlockContent(BlockContentInterface $block_content, array $settings = []): BlockInterface {
return $this->placeBlock('block_content:' . $block_content->uuid(), $settings);
}
/**
* Create field.
*/
public function createField(
string $entity_type,
string $entity_bundle,
string $field_name,
string $field_type,
string $field_label,
array $storage_settings = [],
array $instance_settings = [],
string $widget_type = NULL,
array $widget_options = [],
string $formatter_type = NULL,
array $formatter_options = [],
): void {
$entity_display_repository = $this->container->get('entity_display.repository'); /** @var EntityDisplayRepositoryInterface $entity_display_repository */
// Create field storage
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => $entity_type,
'type' => $field_type,
] + $storage_settings);
$field_storage->save();
// Create field instance
$field_instance = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => $entity_bundle,
'label' => $field_label,
] + $instance_settings);
$field_instance->save();
// Set widget
if ($widget_type || $widget_options) {
if ($widget_type) {
$widget_options['type'] = $widget_type;
}
$entity_form_display = $entity_display_repository->getFormDisplay($entity_type, $entity_bundle);
$entity_form_display->setComponent($field_storage->getName(), $widget_options)->save();
}
// Set formatter
if ($formatter_type || $formatter_options) {
if ($formatter_type) {
$formatter_options['type'] = $formatter_type;
}
$entity_view_display = $entity_display_repository->getViewDisplay($entity_type, $entity_bundle);
$entity_view_display->setComponent($field_storage->getName(), $formatter_options)->save();
}
}
/**
* Delete field.
*/
public function deleteField(string $field_name, string $entity_type = 'node'): void {
FieldStorageConfig::loadByName($entity_type, $field_name)->delete();
}
/**
* Creates a custom block type (bundle).
*/
public function createBlockContentType(string $id = 'basic', string $label = 'Basic', $create_body = TRUE): BlockContentTypeInterface {
$block_content_type = BlockContentType::create([
'id' => $id,
'label' => $label,
'revision' => FALSE,
]);
$block_content_type->save();
if ($create_body) {
block_content_add_body_field($block_content_type->id());
}
return $block_content_type;
}
/**
* Create filter format.
*/
public function createFilterFormat(array $values = []): FilterFormatInterface {
$filter_format_random_name = $this->randomMachineName();
$filter_format = FilterFormat::create($values + [
'format' => $filter_format_random_name,
'name' => $filter_format_random_name,
'weight' => 0,
'filters' => [],
]);
$filter_format->save();
return $filter_format;
}
/**
* Create comment.
*/
public function createComment(EntityInterface $commented_entity, string $field_name = 'comment', array $values = []): CommentInterface {
$values += [
'entity_type' => $commented_entity->getEntityTypeId(),
'entity_id' => $commented_entity->id(),
'field_name' => $field_name,
'uid' => $this->rootUser->id(),
'status' => CommentInterface::PUBLISHED,
'body' => 'Test comment body',
];
$comment = Comment::create($values);
$comment->save();
return $comment;
}
/**
* Create File entity.
*/
public function createFileEntity(array $values): FileInterface {
$file = File::create($values);
$file->save();
return $file;
}
/**
* Create View entity.
*/
public function createView(array $values): ViewEntityInterface {
$view = View::create($values + [
'id' => 'test_view',
'label' => 'Test view',
'base_table' => 'node_field_data',
]);
$view->save();
return $view;
}
/**
* Create menu.
*/
public function createMenu($id, $label): MenuInterface {
$menu = Menu::create([
'id' => $id,
'label' => $label,
]);
$menu->save();
return $menu;
}
/**
* Create menu link for node.
*/
public function createMenuLinkForEntity(EntityInterface $entity, string $menu_name, $values = []): MenuLinkContentInterface {
$menu_link = MenuLinkContent::create([
'title' => $entity->label(),
'menu_name' => $menu_name,
'link' => 'internal:' . $entity->toUrl()->toString(),
] + $values);
$menu_link->save();
return $menu_link;
}
/**
* Login as root
*/
public function drupalLoginAsRoot(): void {
if (!$this->drupalUserIsLoggedIn($this->rootUser)) {
$this->drupalLogin($this->rootUser);
}
}
/**
* Set field widget settings.
*/
public function setFieldWidgetSettings(string $entity_type, string $entity_bundle, string $field_name, array $settings, bool $merge_settings = TRUE): void {
$entity_display_repository = $this->container->get('entity_display.repository'); /** @var EntityDisplayRepositoryInterface $entity_display_repository */
$form_display = $entity_display_repository->getFormDisplay($entity_type, $entity_bundle);
if ($merge_settings) {
$current_widget_settings = $form_display->getComponent($field_name) ?: [];
$settings = NestedArray::mergeDeep($current_widget_settings, $settings);
}
$form_display->setComponent($field_name, $settings)->save();
}
/**
* Set field formatter settings.
*/
public function setFieldFormatterSettings(string $entity_type, string $entity_bundle, string $field_name, array $settings, bool $merge_settings = TRUE): void {
$entity_display_repository = $this->container->get('entity_display.repository'); /** @var EntityDisplayRepositoryInterface $entity_display_repository */
$view_display = $entity_display_repository->getViewDisplay($entity_type, $entity_bundle);
if ($merge_settings) {
$current_formatter_settings = $view_display->getComponent($field_name) ?: [];
$settings = NestedArray::mergeDeep($current_formatter_settings, $settings);
}
$view_display->setComponent($field_name, $settings)->save();
}
/**
* Get entity page.
*/
public function drupalGetEntityPage(EntityInterface $entity, string $rel = 'canonical', array $options = [], array $headers = []): string {
return $this->drupalGet($entity->toUrl($rel), $options, $headers);
}
/**
* Get front page.
*/
public function drupalGetFrontPage(): string {
return $this->drupalGet(Url::fromRoute('<front>'));
}
/**
* Execute View and return query.
*/
public function getViewQuery(string $view_name, string $display_name = 'default', array $arguments = []): SelectInterface {
$view_executable = $this->getExecutedView($view_name, $display_name, $arguments);
return $view_executable->build_info['query'];
}
/**
* Return executed View.
*/
public function getExecutedView(string $view_name, string $display_name = 'default', array $arguments = [], $pre_execute_callback = NULL): ViewExecutable {
$view_executable = Views::getView($view_name);
$view_executable->setDisplay($display_name);
$view_executable->setArguments($arguments);
if ($pre_execute_callback) {
$pre_execute_callback($view_executable);
}
$view_executable->preExecute();
$view_executable->execute();
return $view_executable;
}
/**
* Check page for errors.
*/
public function dontSeeErrorMessage($check_status_code = TRUE, $check_drupal_markup = TRUE, $check_error_message = TRUE): void {
if ($check_status_code) {
$this->assertSession()->statusCodeEquals(200);
}
if ($check_drupal_markup && !$this->cssSelect('div[data-drupal-messages-fallback]')) {
throw new \Exception('Page not contain Drupal markup: "' . $this->getPageContent() . '"');
}
if ($check_error_message && $error_message = $this->cssSelect('.messages--error')) {
throw new \Exception('I see error message — ' . $error_message[0]->getText());
}
}
/**
* Delete entities.
*/
public function deleteEntities(...$entities): void {
foreach ($entities as $entity) {
$entity->delete();
}
}
/**
* Delete nodes by type.
*/
public function deleteNodesByType(string $node_type): void {
$node_storage = $this->container->get('entity_type.manager')->getStorage('node'); /** @var NodeStorageInterface $node_storage */
$nodes = $node_storage->loadByProperties(['type' => $node_type]);
$node_storage->delete($nodes);
}
/**
* Return last added node id.
*/
public function getLastAddedNodeId(string $node_type = NULL): int {
$query = \Drupal::database()->select('node');
$query->addExpression('MAX(nid)', 'nid');
if ($node_type) {
$query->condition('type', $node_type);
}
return (int)$query->execute()->fetchField();
}
/**
* Return last added node.
*/
public function getLastAddedNode(string $node_type = NULL): ?NodeInterface {
if ($last_added_node_id = $this->getLastAddedNodeId($node_type)) {
/** @noinspection All */
return Node::load($last_added_node_id);
}
return NULL;
}
/**
* Count render cache.
*/
public function countRenderCache($cid): int {
return (int)\Drupal::database()
->select('cache_render')
->condition('cid', $cid . '%', 'LIKE')
->countQuery()
->execute()
->fetchField();
}
/**
* Clear render cache.
*/
public function clearRenderCache(): void {
\Drupal::database()->truncate('cache_render')->execute();
}
/**
* Reset storage caches.
*/
public function resetStorageCaches(): void {
$entity_type_manager = \Drupal::entityTypeManager();
foreach (array_keys($entity_type_manager->getDefinitions()) as $entity_type_id) {
$entity_type_manager->getStorage($entity_type_id)->resetCache();
}
}
/**
* Save content.
*/
public function saveData($data, string $filename = 'saved-data.txt'): void {
if (is_array($data)) {
$data = print_r($data, TRUE);
}
file_put_contents('sites/simpletest/' . $filename, (string)$data);
}
/**
* Return page content.
*/
public function getPageContent(): string {
return $this->getSession()->getPage()->getContent();
}
/**
* Save page content.
*/
public function savePageContent($path = NULL): void {
if ($path) {
$this->drupalGet($path);
}
$this->saveData($this->getPageContent(), 'browser-output.html');
}
/**
* Open field widget/formatter settings.
*/
public function openEntityDisplayComponentSettings(string $field_name): void {
$this->submitForm([], $field_name . '_settings_edit');
$this->dontSeeErrorMessage();
}
}
