zaya-1.0.x-dev/tests/src/Functional/ZayaBrowserTestBase.php
tests/src/Functional/ZayaBrowserTestBase.php
<?php
declare(strict_types=1);
namespace Drupal\Tests\zaya\Functional;
use Drupal\Component\Serialization\Json;
use Drupal\group\Entity\GroupInterface;
use Drupal\group\PermissionScopeInterface;
use Drupal\Tests\group\Functional\GroupBrowserTestBase;
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
use Drupal\user\Entity\Role;
/**
* Test description.
*
* @group zaya_itinerary_tests
*/
class ZayaBrowserTestBase extends GroupBrowserTestBase {
use TaxonomyTestTrait;
use MediaTypeCreationTrait;
/**
* {@inheritdoc}
*/
// Protected $defaultTheme = 'claro';
// protected $profile = 'standard';.
/**
* {@inheritdoc}
*/
protected static $modules = [
'path',
'views',
'group',
'group_test_config',
'gnode',
'block',
'filter',
'taxonomy',
'zaya',
'media',
// 'charts',
'zaya_test',
];
/**
* {@inheritdoc}
*/
protected static $configSchemaCheckerExclusions = [
// This view is intentionally excluded to prevent schema errors due
// the schema check done by core.
// @see https://www.drupal.org/project/drupal/issues/2976616
'views.view.chart_itinerary_progress',
'views.view.itineraries_progress',
// views.view.itineraries_
// Need to remove description prop in time_diff or exclude here.
// @see https://www.drupal.org/project/drupal/issues/3400522
// views.view.progress_group_members
// Everywhere with matomo needs to be removed from data_extensions,
// or exclude here:
// views.view.itinerary_chapters
];
/**
* User.
*
* @var \Drupal\user\Entity\User
*/
protected $user;
/**
* Group.
*
* @var \Drupal\group\Entity\Group
*/
protected $group;
/**
* The config to apply on init.
*/
protected function initConfig($container) {
parent::initConfig($container);
$this->addOptionalRoles();
}
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->setUpGroupCreator();
$this->addContentEditorPermissions();
}
/**
* Add the optional config roles that usually come from standard.
*/
protected function addOptionalRoles(): void {
if ($this->profile != 'standard') {
$this->createAdminRole('administrator', 'administrator');
$this->createRole([], 'content_editor', 'content_editor');
}
}
/**
* Set the permissions of the global role content editor.
*
* @todo it needs to import same permissions as zaya_install.
*/
protected function addContentEditorPermissions():void {
if ($this->profile != 'standard') {
// $zaya_path = \Drupal::service('extension.list.module')
// ->getPath('zaya');
// perform zaya_install() better!
// $config_path = "{$zaya_path}/config/optional/r";
/** @var \Drupal\user\RoleInterface $role */
$role = Role::load('content_editor');
$this->grantPermissions($role, [
'create zaya_chapter content',
'access content',
'view zaya_chapter revisions',
'edit own zaya_chapter content',
]);
}
}
/**
* Prepare Group and operator that perform the test and login.
*/
protected function createGroupAndOperator($scope = '', $global_role = '', $global_permissions = []):void {
$this->group = $this->createGroup(['type' => 'zaya_itinerary', 'uid' => $this->loggedInUser->id()]);
if ($global_role != 'anonymous') {
// , TRUE);
$this->user = $this->createUser($global_permissions, "user_{$global_role}_global_role" . $this->randomMachineName(4), values: ['roles' => [$global_role]]);
}
if ($scope == PermissionScopeInterface::INSIDER_ID) {
$this->group->addMember($this->user);
}
if ($global_role != 'anonymous') {
$this->drupalLogin($this->user);
}
else {
$this->drupalLogout();
}
}
/**
* Adds an user to be group creator with admin role and login with it.
*/
protected function setUpGroupCreator(): void {
// Create a user that will serve as the group creator.
$this->groupCreator = $this->createUser(name:"user_with_administrator_global_role", values: ['roles' => ['administrator']]);
$this->drupalLogin($this->groupCreator);
}
/**
* Create group chapter.
*
* @param \Drupal\group\Entity\GroupInterface $group
* The group to where relate content.
* @param array $node_values
* The node values for the new created node.
*
* @return array
* With node and relationship keyed values.
*/
protected function createGroupChapter(GroupInterface $group, $node_values = []): array {
$node = $this->createNode(['type' => 'zaya_chapter', ...$node_values]);
$relationship = $group->addRelationship($node, 'group_node:zaya_chapter');
return ['node' => $node, 'relationship' => $relationship];
}
/**
* Create group resource.
*
* @param \Drupal\group\Entity\GroupInterface $group
* The group to where relate content.
* @param array $node_values
* The node values for the new created node.
*
* @return array
* With node and relationship keyed values.
*/
protected function createGroupResource(GroupInterface $group, $node_values = []): array {
$node = $this->createNode(['type' => 'zaya_resource', ...$node_values]);
$relationship = $group->addRelationship($node, 'group_node:zaya_resource');
return ['node' => $node, 'relationship' => $relationship];
}
/**
* Adds an itinerary contents.
*
* @param \Drupal\group\Entity\GroupInterface $group
* The group which to relate content.
* @param array $relationships
* The relationships, key order will be weight, and dependencies will be
* linear.
* @param array $resources_sets
* The resources nodes to be added to group grouped, an array of resources
* keyed by chapter_id.
*
* @return array
* The relationships of chapters.
*/
protected function addItineraryContents(GroupInterface $group, $relationships = [], $resources_sets = []): array {
foreach ($relationships as $weight => $relationship) {
foreach ($resources_sets as $chapter_id => $resources) {
if ($chapter_id === (int) $relationship->getEntity()->id()) {
$chapter = $relationship->getEntity();
foreach ($resources as $resource) {
$chapter->zaya_chapter_resources[] = [
'target_id' => $resource->getEntity()->id(),
'target_revision_id' => $resource->getEntity()->getRevisionId(),
];
}
$chapter->zaya_weight = $weight;
$chapter->save();
if ($weight === 0) {
$previous_relationship = $relationship;
}
if ($weight > 0) {
$relationship->zaya_dependency = $previous_relationship->getEntity();
$previous_relationship = $relationship;
}
$relationship->save();
}
}
}
return $relationships;
}
/**
* Creates content for an itinerary.
*
* @param \Drupal\group\Entity\GroupInterface $group
* The group which to create content.
*
* @return array
* The relationships of chapters.
*/
protected function createItineraryWithContent(GroupInterface $group): array {
$chapters = ['chapter_1', 'chapter_2', 'chapter_3', 'chapter_4'];
$resources_chapters = [
'chapter_1' => ['chapter_1_resource_1', 'chapter_1_resource_2', 'chapter_1_resource_3'],
'chapter_2' => ['chapter_2_resource_1', 'chapter_2_resource_2', 'chapter_2_resource_3'],
'chapter_3' => ['chapter_3_resource_1'],
'chapter_4' => ['chapter_4_resource_1', 'chapter_4_resource_2', 'chapter_4_resource_3', 'chapter_4_resource_4'],
];
$relationships = [];
$resources_sets = [];
foreach ($chapters as $chapter) {
$relationship_and_node = $this->createGroupChapter($group, node_values: ['title' => $chapter]);
$relationships[] = $relationship_and_node['relationship'];
foreach ($resources_chapters[$chapter] as $resource_title) {
$resource_relationship_and_node = $this->createGroupResource($group, node_values: ['title' => $resource_title]);
$resources_sets[$relationship_and_node['node']->id()][] = $resource_relationship_and_node['relationship'];
}
}
return $this->addItineraryContents($group, $relationships, $resources_sets);
}
/**
* Test adding target bundle in resource if media types defined.
*/
/*
public function testAddTargetBundlesToResource() {
#$this->createMediaType('file', ['id' => 'document']);
#$this->createMediaType('image', ['id' => 'image']);
#$this->createMediaType('video_file', ['id' => 'video']);
#$this->createMediaType('oembed:video', ['id' => 'remote_video']);
# Launch hook_install logic to test if will be added as targetBundles.
//zaya_install();
}
*/
/**
* Helper function for JSON formatted requests.
*
* @param string|\Drupal\Core\Url $path
* Drupal path or URL to load into Mink controlled browser.
* @param array $options
* (optional) Options to be forwarded to the URL generator.
* @param string[] $headers
* (optional) An array containing additional HTTP request headers.
*
* @return string[]
* Array representing decoded JSON response.
*/
protected function drupalGetJson($path, array $options = [], array $headers = []):array {
$options = array_merge_recursive(['query' => ['_format' => 'json']], $options);
return Json::decode($this->drupalGet($path, $options, $headers));
}
}
