updated core to 8.6.3
This commit is contained in:
+4
@@ -60,4 +60,8 @@ foreach ($hierarchy as $tid => $parents) {
|
||||
}
|
||||
}
|
||||
|
||||
// Insert an extra record with no corresponding term.
|
||||
// See https://www.drupal.org/project/drupal/issues/2997982
|
||||
$query->values(['tid' => max($tids) + 1, 'parent' => 0]);
|
||||
|
||||
$query->execute();
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
* Example implementation of accept header based content negotation.
|
||||
* Example implementation of "accept header"-based content negotiation.
|
||||
*/
|
||||
class AcceptHeaderMiddleware implements HttpKernelInterface {
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ class AcceptHeaderRoutingTestServiceProvider implements ServiceModifierInterface
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
// Remove the basic content negotation middleware and replace it with a
|
||||
// Remove the basic content negotiation middleware and replace it with a
|
||||
// basic header based one.
|
||||
$container->register('http_middleware.negotiation', 'Drupal\accept_header_routing_test\AcceptHeaderMiddleware')
|
||||
->addTag('http_middleware', ['priority' => 400]);
|
||||
|
||||
@@ -7,7 +7,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Test controller for content negotation tests.
|
||||
* Test controller for content negotiation tests.
|
||||
*/
|
||||
class TestController {
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class EntityTestAccessControlHandler extends EntityAccessControlHandler {
|
||||
/** @var \Drupal\entity_test\Entity\EntityTest $entity */
|
||||
|
||||
// Always forbid access to entities with the label 'forbid_access', used for
|
||||
// \Drupal\system\Tests\Entity\EntityAccessHControlandlerTest::testDefaultEntityAccess().
|
||||
// \Drupal\system\Tests\Entity\EntityAccessControlHandlerTest::testDefaultEntityAccess().
|
||||
if ($entity->label() == 'forbid_access') {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
|
||||
@@ -513,3 +513,10 @@ form_test.optional_container:
|
||||
_title: 'Optional container testing'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
form_test.javascript_states_form:
|
||||
path: '/form-test/javascript-states-form'
|
||||
defaults:
|
||||
_form: '\Drupal\form_test\Form\JavascriptStatesForm'
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\form_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Builds a simple form to test states.
|
||||
*
|
||||
* @see \Drupal\FunctionalJavascriptTests\Core\Form\JavascriptStatesTest
|
||||
*/
|
||||
class JavascriptStatesForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'javascript_states_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$form['select'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => 'select 1',
|
||||
'#options' => [0 => 0, 1 => 1, 2 => 2],
|
||||
];
|
||||
$form['number'] = [
|
||||
'#type' => 'number',
|
||||
'#title' => 'enter 1',
|
||||
];
|
||||
$form['textfield'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => 'textfield',
|
||||
'#states' => [
|
||||
'visible' => [
|
||||
[':input[name="select"]' => ['value' => '1']],
|
||||
'or',
|
||||
[':input[name="number"]' => ['value' => '1']],
|
||||
],
|
||||
],
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
name: 'HTML mail test support'
|
||||
description: 'Test if HTML in mails works as expected.'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Helper module for the html mail and url conversion tests.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_mail().
|
||||
*/
|
||||
function mail_html_test_mail($key, &$message, $params) {
|
||||
switch ($key) {
|
||||
case 'render_from_message_param':
|
||||
$message['body'][] = \Drupal::service('renderer')->renderPlain($params['message']);
|
||||
break;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\mail_html_test\Plugin\Mail;
|
||||
|
||||
use Drupal\Core\Mail\MailFormatHelper;
|
||||
use Drupal\Core\Mail\Plugin\Mail\TestMailCollector;
|
||||
|
||||
/**
|
||||
* Defines a mail backend that captures sent HTML messages in the state system.
|
||||
*
|
||||
* This class is for running tests or for development and does not convert HTML
|
||||
* to plaintext.
|
||||
*
|
||||
* @Mail(
|
||||
* id = "test_html_mail_collector",
|
||||
* label = @Translation("HTML mail collector"),
|
||||
* description = @Translation("Does not send the message, but stores its HTML in Drupal within the state system. Used for testing.")
|
||||
* )
|
||||
*/
|
||||
class TestHtmlMailCollector extends TestMailCollector {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format(array $message) {
|
||||
// Join the body array into one string.
|
||||
$message['body'] = implode(PHP_EOL, $message['body']);
|
||||
// Wrap the mail body for sending.
|
||||
$message['body'] = MailFormatHelper::wrapMail($message['body']);
|
||||
return $message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,6 +50,18 @@ menu_test.local_action6:
|
||||
appears_on:
|
||||
- menu_test.local_action1
|
||||
|
||||
menu_test.local_action7:
|
||||
route_name: menu_test.local_action7
|
||||
title: 'Local action with access'
|
||||
appears_on:
|
||||
- menu_test.local_action7
|
||||
|
||||
menu_test.local_action8:
|
||||
route_name: menu_test.local_action8
|
||||
title: 'Local action without access'
|
||||
appears_on:
|
||||
- menu_test.local_action7
|
||||
|
||||
menu_test.hidden_menu_add:
|
||||
route_name: menu_test.hidden_menu_add
|
||||
title: 'Add menu'
|
||||
|
||||
@@ -125,6 +125,20 @@ menu_test.local_action6:
|
||||
requirements:
|
||||
_access: 'TRUE'
|
||||
|
||||
menu_test.local_action7:
|
||||
path: '/menu-test-local-action-7/cache-check'
|
||||
defaults:
|
||||
_controller: '\Drupal\menu_test\TestControllers::test2'
|
||||
requirements:
|
||||
_custom_access: '\Drupal\menu_test\Access\AccessCheck::menuLocalAction7'
|
||||
|
||||
menu_test.local_action8:
|
||||
path: '/menu-test-local-action-8/cache-check'
|
||||
defaults:
|
||||
_controller: '\Drupal\menu_test\TestControllers::test2'
|
||||
requirements:
|
||||
_custom_access: '\Drupal\menu_test\Access\AccessCheck::menuLocalAction8'
|
||||
|
||||
menu_test.contextual_test:
|
||||
path: '/menu-test-contextual/default'
|
||||
defaults:
|
||||
|
||||
@@ -26,4 +26,18 @@ class AccessCheck implements AccessInterface {
|
||||
return $result->setCacheMaxAge(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Drupal\Core\Access\AccessResultForbidden
|
||||
*/
|
||||
public function menuLocalAction7() {
|
||||
return AccessResult::forbidden()->addCacheTags(['menu_local_action7'])->addCacheContexts(['url.query_args:menu_local_action7']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Drupal\Core\Access\AccessResultAllowed
|
||||
*/
|
||||
public function menuLocalAction8() {
|
||||
return AccessResult::allowed()->addCacheTags(['menu_local_action8'])->addCacheContexts(['url.query_args:menu_local_action8']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
* Test module.
|
||||
*/
|
||||
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_user_login().
|
||||
*/
|
||||
function session_test_user_login($account) {
|
||||
function session_test_user_login(UserInterface $account) {
|
||||
if ($account->getUsername() == 'session_test_user') {
|
||||
// Exit so we can verify that the session was regenerated
|
||||
// before hook_user_login() was called.
|
||||
|
||||
+1
-1
@@ -287,7 +287,7 @@ class SystemTestController extends ControllerBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* A plain Symfony reponse with Cache-Control: public, max-age=60.
|
||||
* A plain Symfony response with Cache-Control: public, max-age=60.
|
||||
*/
|
||||
public function respondWithPublicResponse() {
|
||||
return (new Response('test'))->setPublic()->setMaxAge(60);
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ class ThemeTestSubscriber implements EventSubscriberInterface {
|
||||
/**
|
||||
* The used container.
|
||||
*
|
||||
* @todo This variable is never initialzed, so we don't know what it is.
|
||||
* @todo This variable is never initialized, so we don't know what it is.
|
||||
* See https://www.drupal.org/node/2721315
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
@@ -314,7 +314,7 @@ class UrlTest extends BrowserTestBase {
|
||||
$url = $test_url . '?drupal=awesome';
|
||||
$query = ['awesome' => 'drupal'];
|
||||
$result = Url::fromUri($url, ['query' => $query])->toString();
|
||||
$this->assertEqual('https://www.drupal.org/?awesome=drupal&drupal=awesome', $result);
|
||||
$this->assertEqual('https://www.drupal.org/?drupal=awesome&awesome=drupal', $result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Condition;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests that condition plugins basic form handling is working.
|
||||
*
|
||||
* Checks condition forms and submission and gives a very cursory check to make
|
||||
* sure the configuration that was submitted actually causes the condition to
|
||||
* validate correctly.
|
||||
*
|
||||
* @group Condition
|
||||
*/
|
||||
class ConditionFormTest extends BrowserTestBase {
|
||||
|
||||
public static $modules = ['node', 'condition_test'];
|
||||
|
||||
/**
|
||||
* Submit the condition_node_type_test_form to test condition forms.
|
||||
*/
|
||||
public function testConfigForm() {
|
||||
$this->drupalCreateContentType(['type' => 'page', 'name' => 'Page']);
|
||||
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
|
||||
|
||||
$article = Node::create([
|
||||
'type' => 'article',
|
||||
'title' => $this->randomMachineName(),
|
||||
]);
|
||||
$article->save();
|
||||
|
||||
$this->drupalGet('condition_test');
|
||||
$this->assertField('bundles[article]', 'There is an article bundle selector.');
|
||||
$this->assertField('bundles[page]', 'There is a page bundle selector.');
|
||||
$this->drupalPostForm(NULL, ['bundles[page]' => 'page', 'bundles[article]' => 'article'], t('Submit'));
|
||||
// @see \Drupal\condition_test\FormController::submitForm()
|
||||
$this->assertText('Bundle: page');
|
||||
$this->assertText('Bundle: article');
|
||||
$this->assertText('Executed successfully.', 'The form configured condition executed properly.');
|
||||
}
|
||||
|
||||
}
|
||||
+96
-2
@@ -7,10 +7,12 @@ use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\comment\CommentInterface;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\media\Entity\Media;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\taxonomy\Entity\Term;
|
||||
use Drupal\taxonomy\Entity\Vocabulary;
|
||||
use Drupal\node\NodeInterface;
|
||||
use Drupal\Tests\media\Traits\MediaTypeCreationTrait;
|
||||
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
|
||||
use Drupal\Tests\user\Traits\UserCreationTrait;
|
||||
use Drupal\user\Entity\User;
|
||||
@@ -25,6 +27,7 @@ class EntityReferenceSelectionAccessTest extends KernelTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
use ContentTypeCreationTrait;
|
||||
use MediaTypeCreationTrait;
|
||||
use UserCreationTrait;
|
||||
|
||||
/**
|
||||
@@ -32,7 +35,7 @@ class EntityReferenceSelectionAccessTest extends KernelTestBase {
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['comment', 'field', 'node', 'system', 'taxonomy', 'text', 'user'];
|
||||
public static $modules = ['comment', 'field', 'file', 'image', 'node', 'media', 'system', 'taxonomy', 'text', 'user'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -42,13 +45,16 @@ class EntityReferenceSelectionAccessTest extends KernelTestBase {
|
||||
|
||||
$this->installSchema('system', 'sequences');
|
||||
$this->installSchema('comment', ['comment_entity_statistics']);
|
||||
$this->installSchema('file', ['file_usage']);
|
||||
|
||||
$this->installEntitySchema('comment');
|
||||
$this->installEntitySchema('file');
|
||||
$this->installEntitySchema('media');
|
||||
$this->installEntitySchema('node');
|
||||
$this->installEntitySchema('taxonomy_term');
|
||||
$this->installEntitySchema('user');
|
||||
|
||||
$this->installConfig(['comment', 'field', 'node', 'taxonomy', 'user']);
|
||||
$this->installConfig(['comment', 'field', 'media', 'node', 'taxonomy', 'user']);
|
||||
|
||||
// Create the anonymous and the admin users.
|
||||
$anonymous_user = User::create([
|
||||
@@ -681,4 +687,92 @@ class EntityReferenceSelectionAccessTest extends KernelTestBase {
|
||||
$this->assertReferenceable($selection_options, $referenceable_tests, 'Term handler (admin)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the selection handler for the media entity type.
|
||||
*/
|
||||
public function testMediaHandler() {
|
||||
$selection_options = [
|
||||
'target_type' => 'media',
|
||||
'handler' => 'default',
|
||||
'target_bundles' => NULL,
|
||||
];
|
||||
|
||||
// Build a set of test data.
|
||||
$media_type = $this->createMediaType('file');
|
||||
$media_values = [
|
||||
'published' => [
|
||||
'bundle' => $media_type->id(),
|
||||
'status' => 1,
|
||||
'name' => 'Media published',
|
||||
'uid' => 1,
|
||||
],
|
||||
'unpublished' => [
|
||||
'bundle' => $media_type->id(),
|
||||
'status' => 0,
|
||||
'name' => 'Media unpublished',
|
||||
'uid' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
$media_entities = [];
|
||||
$media_labels = [];
|
||||
foreach ($media_values as $key => $values) {
|
||||
$media = Media::create($values);
|
||||
$media->save();
|
||||
$media_entities[$key] = $media;
|
||||
$media_labels[$key] = Html::escape($media->label());
|
||||
}
|
||||
|
||||
// Test as a non-admin.
|
||||
$normal_user = $this->createUser(['view media']);
|
||||
$this->setCurrentUser($normal_user);
|
||||
$referenceable_tests = [
|
||||
[
|
||||
'arguments' => [
|
||||
[NULL, 'CONTAINS'],
|
||||
],
|
||||
'result' => [
|
||||
$media_type->id() => [
|
||||
$media_entities['published']->id() => $media_labels['published'],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'arguments' => [
|
||||
['Media unpublished', 'CONTAINS'],
|
||||
],
|
||||
'result' => [],
|
||||
],
|
||||
];
|
||||
$this->assertReferenceable($selection_options, $referenceable_tests, 'Media handler');
|
||||
|
||||
// Test as an admin.
|
||||
$admin_user = $this->createUser(['view media', 'administer media']);
|
||||
$this->setCurrentUser($admin_user);
|
||||
$referenceable_tests = [
|
||||
[
|
||||
'arguments' => [
|
||||
[NULL, 'CONTAINS'],
|
||||
],
|
||||
'result' => [
|
||||
$media_type->id() => [
|
||||
$media_entities['published']->id() => $media_labels['published'],
|
||||
$media_entities['unpublished']->id() => $media_labels['unpublished'],
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'arguments' => [
|
||||
['Media unpublished', 'CONTAINS'],
|
||||
],
|
||||
'result' => [
|
||||
$media_type->id() => [
|
||||
$media_entities['unpublished']->id() => $media_labels['unpublished'],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->assertReferenceable($selection_options, $referenceable_tests, 'Media handler (admin)');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use Drupal\Component\PhpStorage\FileStorage;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests the log message added by file_save_htacess().
|
||||
* Tests the log message added by file_save_htaccess().
|
||||
*
|
||||
* @group File
|
||||
*/
|
||||
|
||||
@@ -51,4 +51,29 @@ class ModulesListFormWebTest extends BrowserTestBase {
|
||||
$this->assertText('simpletest');
|
||||
}
|
||||
|
||||
public function testModulesListFormWithInvalidInfoFile() {
|
||||
$broken_info_yml = <<<BROKEN
|
||||
name: Module With Broken Info file
|
||||
type: module
|
||||
BROKEN;
|
||||
$path = \Drupal::service('site.path') . "/modules/broken";
|
||||
mkdir($path, 0777, TRUE);
|
||||
file_put_contents("$path/broken.info.yml", $broken_info_yml);
|
||||
|
||||
$this->drupalLogin(
|
||||
$this->drupalCreateUser(
|
||||
['administer modules', 'administer permissions']
|
||||
)
|
||||
);
|
||||
$this->drupalGet('admin/modules');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
|
||||
// Confirm that the error message is shown.
|
||||
$this->assertSession()
|
||||
->pageTextContains('Modules could not be listed due to an error: Missing required keys (core) in ' . $path . '/broken.info.yml');
|
||||
|
||||
// Check that the module filter text box is available.
|
||||
$this->assertTrue($this->xpath('//input[@name="text"]'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Mail;
|
||||
|
||||
use Drupal\Component\Utility\Random;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Mail\MailFormatHelper;
|
||||
use Drupal\Core\Mail\Plugin\Mail\TestMailCollector;
|
||||
use Drupal\Core\Render\Markup;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\system_mail_failure_test\Plugin\Mail\TestPhpMailFailure;
|
||||
|
||||
@@ -19,7 +24,7 @@ class MailTest extends BrowserTestBase {
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['simpletest', 'system_mail_failure_test'];
|
||||
public static $modules = ['simpletest', 'system_mail_failure_test', 'mail_html_test', 'file', 'image'];
|
||||
|
||||
/**
|
||||
* Assert that the pluggable mail system is functional.
|
||||
@@ -104,4 +109,178 @@ class MailTest extends BrowserTestBase {
|
||||
$this->assertFalse(isset($sent_message['headers']['Errors-To']), 'Errors-to header must not be set, it is deprecated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that relative paths in mails are converted into absolute URLs.
|
||||
*/
|
||||
public function testConvertRelativeUrlsIntoAbsolute() {
|
||||
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
|
||||
|
||||
// Use the HTML compatible state system collector mail backend.
|
||||
$this->config('system.mail')->set('interface.default', 'test_html_mail_collector')->save();
|
||||
|
||||
// Fetch the hostname and port for matching against.
|
||||
$http_host = \Drupal::request()->getSchemeAndHttpHost();
|
||||
|
||||
// Random generator.
|
||||
$random = new Random();
|
||||
|
||||
// One random tag name.
|
||||
$tag_name = strtolower($random->name(8, TRUE));
|
||||
|
||||
// Test root relative urls.
|
||||
foreach (['href', 'src'] as $attribute) {
|
||||
// Reset the state variable that holds sent messages.
|
||||
\Drupal::state()->set('system.test_mail_collector', []);
|
||||
|
||||
$html = "<$tag_name $attribute=\"/root-relative\">root relative url in mail test</$tag_name>";
|
||||
$expected_html = "<$tag_name $attribute=\"{$http_host}/root-relative\">root relative url in mail test</$tag_name>";
|
||||
|
||||
// Prepare render array.
|
||||
$render = ['#markup' => Markup::create($html)];
|
||||
|
||||
// Send a test message that simpletest_mail_alter should cancel.
|
||||
\Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]);
|
||||
// Retrieve sent message.
|
||||
$captured_emails = \Drupal::state()->get('system.test_mail_collector');
|
||||
$sent_message = end($captured_emails);
|
||||
|
||||
// Wrap the expected HTML and assert.
|
||||
$expected_html = MailFormatHelper::wrapMail($expected_html);
|
||||
$this->assertSame($expected_html, $sent_message['body'], "Asserting that {$attribute} is properly converted for mails.");
|
||||
}
|
||||
|
||||
// Test protocol relative urls.
|
||||
foreach (['href', 'src'] as $attribute) {
|
||||
// Reset the state variable that holds sent messages.
|
||||
\Drupal::state()->set('system.test_mail_collector', []);
|
||||
|
||||
$html = "<$tag_name $attribute=\"//example.com/protocol-relative\">protocol relative url in mail test</$tag_name>";
|
||||
$expected_html = "<$tag_name $attribute=\"//example.com/protocol-relative\">protocol relative url in mail test</$tag_name>";
|
||||
|
||||
// Prepare render array.
|
||||
$render = ['#markup' => Markup::create($html)];
|
||||
|
||||
// Send a test message that simpletest_mail_alter should cancel.
|
||||
\Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]);
|
||||
// Retrieve sent message.
|
||||
$captured_emails = \Drupal::state()->get('system.test_mail_collector');
|
||||
$sent_message = end($captured_emails);
|
||||
|
||||
// Wrap the expected HTML and assert.
|
||||
$expected_html = MailFormatHelper::wrapMail($expected_html);
|
||||
$this->assertSame($expected_html, $sent_message['body'], "Asserting that {$attribute} is properly converted for mails.");
|
||||
}
|
||||
|
||||
// Test absolute urls.
|
||||
foreach (['href', 'src'] as $attribute) {
|
||||
// Reset the state variable that holds sent messages.
|
||||
\Drupal::state()->set('system.test_mail_collector', []);
|
||||
|
||||
$html = "<$tag_name $attribute=\"http://example.com/absolute\">absolute url in mail test</$tag_name>";
|
||||
$expected_html = "<$tag_name $attribute=\"http://example.com/absolute\">absolute url in mail test</$tag_name>";
|
||||
|
||||
// Prepare render array.
|
||||
$render = ['#markup' => Markup::create($html)];
|
||||
|
||||
// Send a test message that simpletest_mail_alter should cancel.
|
||||
\Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]);
|
||||
// Retrieve sent message.
|
||||
$captured_emails = \Drupal::state()->get('system.test_mail_collector');
|
||||
$sent_message = end($captured_emails);
|
||||
|
||||
// Wrap the expected HTML and assert.
|
||||
$expected_html = MailFormatHelper::wrapMail($expected_html);
|
||||
$this->assertSame($expected_html, $sent_message['body'], "Asserting that {$attribute} is properly converted for mails.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that mails built from render arrays contain absolute paths.
|
||||
*
|
||||
* By default Drupal uses relative paths for images and links. When sending
|
||||
* emails, absolute paths should be used instead.
|
||||
*/
|
||||
public function testRenderedElementsUseAbsolutePaths() {
|
||||
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
|
||||
|
||||
// Use the HTML compatible state system collector mail backend.
|
||||
$this->config('system.mail')->set('interface.default', 'test_html_mail_collector')->save();
|
||||
|
||||
// Fetch the hostname and port for matching against.
|
||||
$http_host = \Drupal::request()->getSchemeAndHttpHost();
|
||||
|
||||
// Random generator.
|
||||
$random = new Random();
|
||||
$image_name = $random->name();
|
||||
|
||||
// Create an image file.
|
||||
$file = File::create(['uri' => "public://{$image_name}.png", 'filename' => "{$image_name}.png"]);
|
||||
$file->save();
|
||||
|
||||
$base_path = base_path();
|
||||
|
||||
$path_pairs = [
|
||||
'root relative' => [$file->getFileUri(), "{$http_host}{$base_path}{$this->publicFilesDirectory}/{$image_name}.png"],
|
||||
'protocol relative' => ['//example.com/image.png', '//example.com/image.png'],
|
||||
'absolute' => ['http://example.com/image.png', 'http://example.com/image.png'],
|
||||
];
|
||||
|
||||
// Test images.
|
||||
foreach ($path_pairs as $test_type => $paths) {
|
||||
list($input_path, $expected_path) = $paths;
|
||||
|
||||
// Reset the state variable that holds sent messages.
|
||||
\Drupal::state()->set('system.test_mail_collector', []);
|
||||
|
||||
// Build the render array.
|
||||
$render = [
|
||||
'#theme' => 'image',
|
||||
'#uri' => $input_path,
|
||||
];
|
||||
$expected_html = "<img src=\"$expected_path\" alt=\"\" />";
|
||||
|
||||
// Send a test message that simpletest_mail_alter should cancel.
|
||||
\Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]);
|
||||
// Retrieve sent message.
|
||||
$captured_emails = \Drupal::state()->get('system.test_mail_collector');
|
||||
$sent_message = end($captured_emails);
|
||||
|
||||
// Wrap the expected HTML and assert.
|
||||
$expected_html = MailFormatHelper::wrapMail($expected_html);
|
||||
$this->assertSame($expected_html, $sent_message['body'], "Asserting that {$test_type} paths are converted properly.");
|
||||
}
|
||||
|
||||
// Test links.
|
||||
$path_pairs = [
|
||||
'root relative' => [Url::fromUserInput('/path/to/something'), "{$http_host}{$base_path}path/to/something"],
|
||||
'protocol relative' => [Url::fromUri('//example.com/image.png'), '//example.com/image.png'],
|
||||
'absolute' => [Url::fromUri('http://example.com/image.png'), 'http://example.com/image.png'],
|
||||
];
|
||||
|
||||
foreach ($path_pairs as $paths) {
|
||||
list($input_path, $expected_path) = $paths;
|
||||
|
||||
// Reset the state variable that holds sent messages.
|
||||
\Drupal::state()->set('system.test_mail_collector', []);
|
||||
|
||||
// Build the render array.
|
||||
$render = [
|
||||
'#title' => 'Link',
|
||||
'#type' => 'link',
|
||||
'#url' => $input_path,
|
||||
];
|
||||
$expected_html = "<a href=\"$expected_path\">Link</a>";
|
||||
|
||||
// Send a test message that simpletest_mail_alter should cancel.
|
||||
\Drupal::service('plugin.manager.mail')->mail('mail_html_test', 'render_from_message_param', 'relative_url@example.com', $language_interface->getId(), ['message' => $render]);
|
||||
// Retrieve sent message.
|
||||
$captured_emails = \Drupal::state()->get('system.test_mail_collector');
|
||||
$sent_message = end($captured_emails);
|
||||
|
||||
// Wrap the expected HTML and assert.
|
||||
$expected_html = MailFormatHelper::wrapMail($expected_html);
|
||||
$this->assertSame($expected_html, $sent_message['body']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Menu;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests breadcrumbs functionality.
|
||||
*
|
||||
* @group Menu
|
||||
*/
|
||||
class BreadcrumbFrontCacheContextsTest extends BrowserTestBase {
|
||||
|
||||
use AssertBreadcrumbTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'block',
|
||||
'node',
|
||||
'path',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* A test node with path alias.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $nodeWithAlias;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('system_breadcrumb_block');
|
||||
|
||||
$user = $this->drupalCreateUser();
|
||||
|
||||
$this->drupalCreateContentType([
|
||||
'type' => 'page',
|
||||
]);
|
||||
|
||||
// Create a node for front page.
|
||||
$node_front = $this->drupalCreateNode([
|
||||
'uid' => $user->id(),
|
||||
]);
|
||||
|
||||
// Create a node with a random alias.
|
||||
$this->nodeWithAlias = $this->drupalCreateNode([
|
||||
'uid' => $user->id(),
|
||||
'type' => 'page',
|
||||
'path' => '/' . $this->randomMachineName(),
|
||||
]);
|
||||
|
||||
// Configure 'node' as front page.
|
||||
$this->config('system.site')
|
||||
->set('page.front', '/node/' . $node_front->id())
|
||||
->save();
|
||||
|
||||
\Drupal::cache('render')->deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that breadcrumb markup get the right cache contexts.
|
||||
*
|
||||
* Checking that the breadcrumb will be printed on node canonical routes even
|
||||
* if it was rendered for the <front> page first.
|
||||
*/
|
||||
public function testBreadcrumbsFrontPageCache() {
|
||||
// Hit front page first as anonymous user with 'cold' render cache.
|
||||
$this->drupalGet('<front>');
|
||||
$web_assert = $this->assertSession();
|
||||
// Verify that no breadcrumb block presents.
|
||||
$web_assert->elementNotExists('css', '.block-system-breadcrumb-block');
|
||||
|
||||
// Verify that breadcrumb appears correctly for the test content
|
||||
// (which is not set as front page).
|
||||
$this->drupalGet($this->nodeWithAlias->path->alias);
|
||||
$breadcrumbs = $this->assertSession()->elementExists('css', '.block-system-breadcrumb-block');
|
||||
$crumbs = $breadcrumbs->findAll('css', 'ol li');
|
||||
$this->assertTrue(count($crumbs) === 1);
|
||||
$this->assertTrue($crumbs[0]->getText() === 'Home');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class MenuAccessTest extends BrowserTestBase {
|
||||
// Test that there's link rendered on the route.
|
||||
$this->drupalGet('menu_test_access_check_session');
|
||||
$this->assertLink('Test custom route access check');
|
||||
// Page still accessible but thre should not be menu link.
|
||||
// Page is still accessible but there should be no menu link.
|
||||
$this->drupalGet('menu_test_access_check_session');
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoLink('Test custom route access check');
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Page;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests default HTML metatags on a page.
|
||||
*
|
||||
* @group Page
|
||||
*/
|
||||
class DefaultMetatagsTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Tests meta tags.
|
||||
*/
|
||||
public function testMetaTag() {
|
||||
$this->drupalGet('');
|
||||
// Ensures that the charset metatag is on the page.
|
||||
$result = $this->xpath('//meta[@charset="utf-8"]');
|
||||
$this->assertEqual(count($result), 1);
|
||||
|
||||
// Ensure that the charset one is the first metatag.
|
||||
$result = $this->xpath('//meta');
|
||||
$this->assertEqual((string) $result[0]->getAttribute('charset'), 'utf-8');
|
||||
|
||||
// Ensure that the shortcut icon is on the page.
|
||||
$result = $this->xpath('//link[@rel = "shortcut icon"]');
|
||||
$this->assertEqual(count($result), 1, 'The shortcut icon is present.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Pager;
|
||||
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Tests pager functionality.
|
||||
*
|
||||
* @group Pager
|
||||
*/
|
||||
class PagerTest extends BrowserTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['dblog', 'pager_test'];
|
||||
|
||||
/**
|
||||
* A user with permission to access site reports.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected $profile = 'testing';
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Insert 300 log messages.
|
||||
$logger = $this->container->get('logger.factory')->get('pager_test');
|
||||
for ($i = 0; $i < 300; $i++) {
|
||||
$logger->debug($this->randomString());
|
||||
}
|
||||
|
||||
$this->adminUser = $this->drupalCreateUser([
|
||||
'access site reports',
|
||||
]);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests markup and CSS classes of pager links.
|
||||
*/
|
||||
public function testActiveClass() {
|
||||
// Verify first page.
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$current_page = 0;
|
||||
$this->assertPagerItems($current_page);
|
||||
|
||||
// Verify any page but first/last.
|
||||
$current_page++;
|
||||
$this->drupalGet('admin/reports/dblog', ['query' => ['page' => $current_page]]);
|
||||
$this->assertPagerItems($current_page);
|
||||
|
||||
// Verify last page.
|
||||
$elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--last']);
|
||||
preg_match('@page=(\d+)@', $elements[0]->getAttribute('href'), $matches);
|
||||
$current_page = (int) $matches[1];
|
||||
$this->drupalGet($GLOBALS['base_root'] . parse_url($this->getUrl())['path'] . $elements[0]->getAttribute('href'), ['external' => TRUE]);
|
||||
$this->assertPagerItems($current_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test proper functioning of the query parameters and the pager cache context.
|
||||
*/
|
||||
public function testPagerQueryParametersAndCacheContext() {
|
||||
// First page.
|
||||
$this->drupalGet('pager-test/query-parameters');
|
||||
$this->assertText(t('Pager calls: 0'), 'Initial call to pager shows 0 calls.');
|
||||
$this->assertText('[url.query_args.pagers:0]=0.0');
|
||||
$this->assertCacheContext('url.query_args');
|
||||
|
||||
// Go to last page, the count of pager calls need to go to 1.
|
||||
$elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--last']);
|
||||
$elements[0]->click();
|
||||
$this->assertText(t('Pager calls: 1'), 'First link call to pager shows 1 calls.');
|
||||
$this->assertText('[url.query_args.pagers:0]=0.60');
|
||||
$this->assertCacheContext('url.query_args');
|
||||
|
||||
// Reset counter to 0.
|
||||
$this->drupalGet('pager-test/query-parameters');
|
||||
// Go back to first page, the count of pager calls need to go to 2.
|
||||
$elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--last']);
|
||||
$elements[0]->click();
|
||||
$elements = $this->xpath('//li[contains(@class, :class)]/a', [':class' => 'pager__item--first']);
|
||||
$elements[0]->click();
|
||||
$this->assertText(t('Pager calls: 2'), 'Second link call to pager shows 2 calls.');
|
||||
$this->assertText('[url.query_args.pagers:0]=0.0');
|
||||
$this->assertCacheContext('url.query_args');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test proper functioning of multiple pagers.
|
||||
*/
|
||||
public function testMultiplePagers() {
|
||||
// First page.
|
||||
$this->drupalGet('pager-test/multiple-pagers');
|
||||
|
||||
// Test data.
|
||||
// Expected URL query string param is 0-indexed.
|
||||
// Expected page per pager is 1-indexed.
|
||||
$test_data = [
|
||||
// With no query, all pagers set to first page.
|
||||
[
|
||||
'input_query' => NULL,
|
||||
'expected_page' => [0 => '1', 1 => '1', 4 => '1'],
|
||||
'expected_query' => '?page=0,0,,,0',
|
||||
],
|
||||
// Blanks around page numbers should not be relevant.
|
||||
[
|
||||
'input_query' => '?page=2 , 10,,, 5 ,,',
|
||||
'expected_page' => [0 => '3', 1 => '11', 4 => '6'],
|
||||
'expected_query' => '?page=2,10,,,5',
|
||||
],
|
||||
// Blanks within page numbers should lead to only the first integer
|
||||
// to be considered.
|
||||
[
|
||||
'input_query' => '?page=2 , 3 0,,, 4 13 ,,',
|
||||
'expected_page' => [0 => '3', 1 => '4', 4 => '5'],
|
||||
'expected_query' => '?page=2,3,,,4',
|
||||
],
|
||||
// If floats are passed as page numbers, only the integer part is
|
||||
// returned.
|
||||
[
|
||||
'input_query' => '?page=2.1,6.999,,,5.',
|
||||
'expected_page' => [0 => '3', 1 => '7', 4 => '6'],
|
||||
'expected_query' => '?page=2,6,,,5',
|
||||
],
|
||||
// Partial page fragment, undefined pagers set to first page.
|
||||
[
|
||||
'input_query' => '?page=5,2',
|
||||
'expected_page' => [0 => '6', 1 => '3', 4 => '1'],
|
||||
'expected_query' => '?page=5,2,,,0',
|
||||
],
|
||||
// Partial page fragment, undefined pagers set to first page.
|
||||
[
|
||||
'input_query' => '?page=,2',
|
||||
'expected_page' => [0 => '1', 1 => '3', 4 => '1'],
|
||||
'expected_query' => '?page=0,2,,,0',
|
||||
],
|
||||
// Partial page fragment, undefined pagers set to first page.
|
||||
[
|
||||
'input_query' => '?page=,',
|
||||
'expected_page' => [0 => '1', 1 => '1', 4 => '1'],
|
||||
'expected_query' => '?page=0,0,,,0',
|
||||
],
|
||||
// With overflow pages, all pagers set to max page.
|
||||
[
|
||||
'input_query' => '?page=99,99,,,99',
|
||||
'expected_page' => [0 => '16', 1 => '16', 4 => '16'],
|
||||
'expected_query' => '?page=15,15,,,15',
|
||||
],
|
||||
// Wrong value for the page resets pager to first page.
|
||||
[
|
||||
'input_query' => '?page=bar,5,foo,qux,bet',
|
||||
'expected_page' => [0 => '1', 1 => '6', 4 => '1'],
|
||||
'expected_query' => '?page=0,5,,,0',
|
||||
],
|
||||
];
|
||||
|
||||
// We loop through the page with the test data query parameters, and check
|
||||
// that the active page for each pager element has the expected page
|
||||
// (1-indexed) and resulting query parameter
|
||||
foreach ($test_data as $data) {
|
||||
$input_query = str_replace(' ', '%20', $data['input_query']);
|
||||
$this->drupalGet($GLOBALS['base_root'] . parse_url($this->getUrl())['path'] . $input_query, ['external' => TRUE]);
|
||||
foreach ([0, 1, 4] as $pager_element) {
|
||||
$active_page = $this->cssSelect("div.test-pager-{$pager_element} ul.pager__items li.is-active:contains('{$data['expected_page'][$pager_element]}')");
|
||||
$destination = str_replace('%2C', ',', $active_page[0]->find('css', 'a')->getAttribute('href'));
|
||||
$this->assertEqual($destination, $data['expected_query']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test proper functioning of the ellipsis.
|
||||
*/
|
||||
public function testPagerEllipsis() {
|
||||
// Insert 100 extra log messages to get 9 pages.
|
||||
$logger = $this->container->get('logger.factory')->get('pager_test');
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$logger->debug($this->randomString());
|
||||
}
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$elements = $this->cssSelect(".pager__item--ellipsis:contains('…')");
|
||||
$this->assertEqual(count($elements), 0, 'No ellipsis has been set.');
|
||||
|
||||
// Insert an extra 50 log messages to get 10 pages.
|
||||
$logger = $this->container->get('logger.factory')->get('pager_test');
|
||||
for ($i = 0; $i < 50; $i++) {
|
||||
$logger->debug($this->randomString());
|
||||
}
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$elements = $this->cssSelect(".pager__item--ellipsis:contains('…')");
|
||||
$this->assertEqual(count($elements), 1, 'Found the ellipsis.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts pager items and links.
|
||||
*
|
||||
* @param int $current_page
|
||||
* The current pager page the internal browser is on.
|
||||
*/
|
||||
protected function assertPagerItems($current_page) {
|
||||
$elements = $this->xpath('//ul[contains(@class, :class)]/li', [':class' => 'pager__items']);
|
||||
$this->assertTrue(!empty($elements), 'Pager found.');
|
||||
|
||||
// Make current page 1-based.
|
||||
$current_page++;
|
||||
|
||||
// Extract first/previous and next/last items.
|
||||
// first/previous only exist, if the current page is not the first.
|
||||
if ($current_page > 1) {
|
||||
$first = array_shift($elements);
|
||||
$previous = array_shift($elements);
|
||||
}
|
||||
// next/last always exist, unless the current page is the last.
|
||||
if ($current_page != count($elements)) {
|
||||
$last = array_pop($elements);
|
||||
$next = array_pop($elements);
|
||||
}
|
||||
|
||||
// We remove elements from the $elements array in the following code, so
|
||||
// we store the total number of pages for verifying the "last" link.
|
||||
$total_pages = count($elements);
|
||||
|
||||
// Verify items and links to pages.
|
||||
foreach ($elements as $page => $element) {
|
||||
// Make item/page index 1-based.
|
||||
$page++;
|
||||
|
||||
if ($current_page == $page) {
|
||||
$this->assertClass($element, 'is-active', 'Element for current page has .is-active class.');
|
||||
$link = $element->find('css', 'a');
|
||||
$this->assertTrue($link, 'Element for current page has link.');
|
||||
$destination = $link->getAttribute('href');
|
||||
// URL query string param is 0-indexed.
|
||||
$this->assertEqual($destination, '?page=' . ($page - 1));
|
||||
}
|
||||
else {
|
||||
$this->assertNoClass($element, 'is-active', "Element for page $page has no .is-active class.");
|
||||
$this->assertClass($element, 'pager__item', "Element for page $page has .pager__item class.");
|
||||
$link = $element->find('css', 'a');
|
||||
$this->assertTrue($link, "Link to page $page found.");
|
||||
$destination = $link->getAttribute('href');
|
||||
$this->assertEqual($destination, '?page=' . ($page - 1));
|
||||
}
|
||||
unset($elements[--$page]);
|
||||
}
|
||||
// Verify that no other items remain untested.
|
||||
$this->assertTrue(empty($elements), 'All expected items found.');
|
||||
|
||||
// Verify first/previous and next/last items and links.
|
||||
if (isset($first)) {
|
||||
$this->assertClass($first, 'pager__item--first', 'Element for first page has .pager__item--first class.');
|
||||
$link = $first->find('css', 'a');
|
||||
$this->assertTrue($link, 'Link to first page found.');
|
||||
$this->assertNoClass($link, 'is-active', 'Link to first page is not active.');
|
||||
$destination = $link->getAttribute('href');
|
||||
$this->assertEqual($destination, '?page=0');
|
||||
}
|
||||
if (isset($previous)) {
|
||||
$this->assertClass($previous, 'pager__item--previous', 'Element for first page has .pager__item--previous class.');
|
||||
$link = $previous->find('css', 'a');
|
||||
$this->assertTrue($link, 'Link to previous page found.');
|
||||
$this->assertNoClass($link, 'is-active', 'Link to previous page is not active.');
|
||||
$destination = $link->getAttribute('href');
|
||||
// URL query string param is 0-indexed, $current_page is 1-indexed.
|
||||
$this->assertEqual($destination, '?page=' . ($current_page - 2));
|
||||
}
|
||||
if (isset($next)) {
|
||||
$this->assertClass($next, 'pager__item--next', 'Element for next page has .pager__item--next class.');
|
||||
$link = $next->find('css', 'a');
|
||||
$this->assertTrue($link, 'Link to next page found.');
|
||||
$this->assertNoClass($link, 'is-active', 'Link to next page is not active.');
|
||||
$destination = $link->getAttribute('href');
|
||||
// URL query string param is 0-indexed, $current_page is 1-indexed.
|
||||
$this->assertEqual($destination, '?page=' . $current_page);
|
||||
}
|
||||
if (isset($last)) {
|
||||
$link = $last->find('css', 'a');
|
||||
$this->assertClass($last, 'pager__item--last', 'Element for last page has .pager__item--last class.');
|
||||
$this->assertTrue($link, 'Link to last page found.');
|
||||
$this->assertNoClass($link, 'is-active', 'Link to last page is not active.');
|
||||
$destination = $link->getAttribute('href');
|
||||
// URL query string param is 0-indexed.
|
||||
$this->assertEqual($destination, '?page=' . ($total_pages - 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that an element has a given class.
|
||||
*
|
||||
* @param \Behat\Mink\Element\NodeElement $element
|
||||
* The element to test.
|
||||
* @param string $class
|
||||
* The class to assert.
|
||||
* @param string $message
|
||||
* (optional) A verbose message to output.
|
||||
*/
|
||||
protected function assertClass(NodeElement $element, $class, $message = NULL) {
|
||||
if (!isset($message)) {
|
||||
$message = "Class .$class found.";
|
||||
}
|
||||
$this->assertTrue($element->hasClass($class) !== FALSE, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that an element does not have a given class.
|
||||
*
|
||||
* @param \Behat\Mink\Element\NodeElement $element
|
||||
* The element to test.
|
||||
* @param string $class
|
||||
* The class to assert.
|
||||
* @param string $message
|
||||
* (optional) A verbose message to output.
|
||||
*/
|
||||
protected function assertNoClass(NodeElement $element, $class, $message = NULL) {
|
||||
if (!isset($message)) {
|
||||
$message = "Class .$class not found.";
|
||||
}
|
||||
$this->assertTrue($element->hasClass($class) === FALSE, $message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Render;
|
||||
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Functional tests for HtmlResponseAttachmentsProcessor.
|
||||
*
|
||||
* @group Render
|
||||
*/
|
||||
class HtmlResponseAttachmentsTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['render_attached_test'];
|
||||
|
||||
/**
|
||||
* Test rendering of ['#attached'].
|
||||
*/
|
||||
public function testAttachments() {
|
||||
// Test ['#attached']['http_header] = ['Status', $code].
|
||||
$this->drupalGet('/render_attached_test/teapot');
|
||||
$this->assertResponse(418);
|
||||
$this->assertHeader('X-Drupal-Cache', 'MISS');
|
||||
// Repeat for the cache.
|
||||
$this->drupalGet('/render_attached_test/teapot');
|
||||
$this->assertResponse(418);
|
||||
$this->assertHeader('X-Drupal-Cache', 'HIT');
|
||||
|
||||
// Test ['#attached']['http_header'] with various replacement rules.
|
||||
$this->drupalGet('/render_attached_test/header');
|
||||
$this->assertTeapotHeaders();
|
||||
$this->assertHeader('X-Drupal-Cache', 'MISS');
|
||||
// Repeat for the cache.
|
||||
$this->drupalGet('/render_attached_test/header');
|
||||
$this->assertHeader('X-Drupal-Cache', 'HIT');
|
||||
|
||||
// Test ['#attached']['feed'].
|
||||
$this->drupalGet('/render_attached_test/feed');
|
||||
$this->assertHeader('X-Drupal-Cache', 'MISS');
|
||||
$this->assertFeed();
|
||||
// Repeat for the cache.
|
||||
$this->drupalGet('/render_attached_test/feed');
|
||||
$this->assertHeader('X-Drupal-Cache', 'HIT');
|
||||
|
||||
// Test ['#attached']['html_head'].
|
||||
$this->drupalGet('/render_attached_test/head');
|
||||
$this->assertHeader('X-Drupal-Cache', 'MISS');
|
||||
$this->assertHead();
|
||||
// Repeat for the cache.
|
||||
$this->drupalGet('/render_attached_test/head');
|
||||
$this->assertHeader('X-Drupal-Cache', 'HIT');
|
||||
|
||||
// Test ['#attached']['html_head_link'] when outputted as HTTP header.
|
||||
$this->drupalGet('/render_attached_test/html_header_link');
|
||||
$expected_link_headers = [
|
||||
'</foo?bar=<baz>&baz=false>; rel="alternate"',
|
||||
'</foo/bar>; hreflang="nl"; rel="alternate"',
|
||||
];
|
||||
$this->assertEqual($this->getSession()->getResponseHeaders()['Link'], $expected_link_headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test caching of ['#attached'].
|
||||
*/
|
||||
public function testRenderCachedBlock() {
|
||||
// Make sure our test block is visible.
|
||||
$this->drupalPlaceBlock('attached_rendering_block', ['region' => 'content']);
|
||||
|
||||
// Get the front page, which should now have our visible block.
|
||||
$this->drupalGet('');
|
||||
// Make sure our block is visible.
|
||||
$this->assertText('Markup from attached_rendering_block.');
|
||||
// Test that all our attached items are present.
|
||||
$this->assertFeed();
|
||||
$this->assertHead();
|
||||
$this->assertResponse(418);
|
||||
$this->assertTeapotHeaders();
|
||||
|
||||
// Reload the page, to test caching.
|
||||
$this->drupalGet('');
|
||||
// Make sure our block is visible.
|
||||
$this->assertText('Markup from attached_rendering_block.');
|
||||
// The header should be present again.
|
||||
$this->assertHeader('X-Test-Teapot', 'Teapot Mode Active');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to make assertions about added HTTP headers.
|
||||
*/
|
||||
protected function assertTeapotHeaders() {
|
||||
$headers = $this->getSession()->getResponseHeaders();
|
||||
$this->assertEquals($headers['X-Test-Teapot'], ['Teapot Mode Active']);
|
||||
$this->assertEquals($headers['X-Test-Teapot-Replace'], ['Teapot replaced']);
|
||||
$this->assertEquals($headers['X-Test-Teapot-No-Replace'], ['This value is not replaced', 'This one is added']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to make assertions about the presence of an RSS feed.
|
||||
*/
|
||||
protected function assertFeed() {
|
||||
// Discover the DOM element for the feed link.
|
||||
$test_meta = $this->xpath('//head/link[@href="test://url"]');
|
||||
$this->assertEqual(1, count($test_meta), 'Link has URL.');
|
||||
// Reconcile the other attributes.
|
||||
$test_meta_attributes = [
|
||||
'href' => 'test://url',
|
||||
'rel' => 'alternate',
|
||||
'type' => 'application/rss+xml',
|
||||
'title' => 'Your RSS feed.',
|
||||
];
|
||||
$test_meta = reset($test_meta);
|
||||
if (empty($test_meta)) {
|
||||
$this->fail('Unable to find feed link.');
|
||||
}
|
||||
else {
|
||||
foreach ($test_meta_attributes as $attribute => $value) {
|
||||
$this->assertEquals($value, $test_meta->getAttribute($attribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to make assertions about HTML head elements.
|
||||
*/
|
||||
protected function assertHead() {
|
||||
// Discover the DOM element for the meta link.
|
||||
$test_meta = $this->xpath('//head/meta[@test-attribute="testvalue"]');
|
||||
$this->assertEqual(1, count($test_meta), 'There\'s only one test attribute.');
|
||||
// Grab the only DOM element.
|
||||
$test_meta = reset($test_meta);
|
||||
if (empty($test_meta)) {
|
||||
$this->fail('Unable to find the head meta.');
|
||||
}
|
||||
else {
|
||||
$this->assertEqual($test_meta->getAttribute('test-attribute'), 'testvalue');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Render;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Tests that URL bubbleable metadata is correctly bubbled.
|
||||
*
|
||||
* @group Render
|
||||
*/
|
||||
class UrlBubbleableMetadataBubblingTest extends BrowserTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['cache_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that URL bubbleable metadata is correctly bubbled.
|
||||
*/
|
||||
public function testUrlBubbleableMetadataBubbling() {
|
||||
// Test that regular URLs bubble up bubbleable metadata when converted to
|
||||
// string.
|
||||
$url = Url::fromRoute('cache_test.url_bubbling');
|
||||
$this->drupalGet($url);
|
||||
$this->assertCacheContext('url.site');
|
||||
$this->assertRaw($url->setAbsolute()->toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\Tests\system\Functional\Routing;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
||||
/**
|
||||
* Tests for $_GET['destination'] and $_REQUEST['destination'] validation.
|
||||
*
|
||||
* Note: This tests basically the same as
|
||||
* \Drupal\Tests\Core\EventSubscriber\RedirectResponseSubscriberTest::testSanitizeDestinationForGet
|
||||
* \Drupal\Tests\Core\EventSubscriber\RedirectResponseSubscriberTest::testSanitizeDestinationForPost
|
||||
* but we want to be absolutely sure it works.
|
||||
*
|
||||
* @group Routing
|
||||
*/
|
||||
class DestinationTest extends BrowserTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system_test'];
|
||||
|
||||
/**
|
||||
* Tests that $_GET/$_REQUEST['destination'] only contain internal URLs.
|
||||
*/
|
||||
public function testDestination() {
|
||||
$http_client = $this->getHttpClient();
|
||||
$session = $this->getSession();
|
||||
|
||||
$test_cases = [
|
||||
[
|
||||
'input' => 'node',
|
||||
'output' => 'node',
|
||||
'message' => "Standard internal example node path is present in the 'destination' parameter.",
|
||||
],
|
||||
[
|
||||
'input' => '/example.com',
|
||||
'output' => '/example.com',
|
||||
'message' => 'Internal path with one leading slash is allowed.',
|
||||
],
|
||||
[
|
||||
'input' => '//example.com/test',
|
||||
'output' => '',
|
||||
'message' => 'External URL without scheme is not allowed.',
|
||||
],
|
||||
[
|
||||
'input' => 'example:test',
|
||||
'output' => 'example:test',
|
||||
'message' => 'Internal URL using a colon is allowed.',
|
||||
],
|
||||
[
|
||||
'input' => 'http://example.com',
|
||||
'output' => '',
|
||||
'message' => 'External URL is not allowed.',
|
||||
],
|
||||
[
|
||||
'input' => 'javascript:alert(0)',
|
||||
'output' => 'javascript:alert(0)',
|
||||
'message' => 'Javascript URL is allowed because it is treated as an internal URL.',
|
||||
],
|
||||
];
|
||||
foreach ($test_cases as $test_case) {
|
||||
// Test $_GET['destination'].
|
||||
$this->drupalGet('system-test/get-destination', ['query' => ['destination' => $test_case['input']]]);
|
||||
$this->assertIdentical($test_case['output'], $session->getPage()->getContent(), $test_case['message']);
|
||||
// Test $_REQUEST['destination'].
|
||||
$post_output = $http_client->request('POST', $this->buildUrl('system-test/request-destination'), [
|
||||
'form_params' => ['destination' => $test_case['input']],
|
||||
]);
|
||||
$this->assertIdentical($test_case['output'], (string) $post_output->getBody(), $test_case['message']);
|
||||
}
|
||||
|
||||
// Make sure that 404 pages do not populate $_GET['destination'] with
|
||||
// external URLs.
|
||||
\Drupal::configFactory()->getEditable('system.site')->set('page.404', '/system-test/get-destination')->save();
|
||||
$this->drupalGet('http://example.com', ['external' => FALSE]);
|
||||
$this->assertResponse(404);
|
||||
$this->assertIdentical(Url::fromRoute('<front>')->toString(), $session->getPage()->getContent(), 'External URL is not allowed on 404 pages.');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests that the allowed html configutations are updated with attributes.
|
||||
* Tests that the allowed html configurations are updated with attributes.
|
||||
*
|
||||
* @group Entity
|
||||
* @group legacy
|
||||
|
||||
+1
-1
@@ -3,10 +3,10 @@
|
||||
namespace Drupal\Tests\system\Kernel\Entity;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
|
||||
|
||||
/**
|
||||
* Tests entity reference selection plugins.
|
||||
|
||||
+6
-3
@@ -5,11 +5,11 @@ namespace Drupal\Tests\system\Kernel\Installer;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests that we handle the absence of a module dependency during install.
|
||||
* Tests that we handle module dependency resolution during install.
|
||||
*
|
||||
* @group Installer
|
||||
*/
|
||||
class InstallerMissingDependenciesTest extends KernelTestBase {
|
||||
class InstallerDependenciesResolutionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@@ -19,7 +19,7 @@ class InstallerMissingDependenciesTest extends KernelTestBase {
|
||||
/**
|
||||
* Verifies that the exception message in the profile step is correct.
|
||||
*/
|
||||
public function testSetUpWithMissingDependencies() {
|
||||
public function testDependenciesResolution() {
|
||||
// Prime the drupal_get_filename() static cache with the location of the
|
||||
// testing profile as it is not the currently active profile and we don't
|
||||
// yet have any cached way to retrieve its location.
|
||||
@@ -32,8 +32,11 @@ class InstallerMissingDependenciesTest extends KernelTestBase {
|
||||
]);
|
||||
|
||||
$message = $info['required_modules']['description']->render();
|
||||
$this->assertContains('Fictional', $message);
|
||||
$this->assertContains('Missing_module1', $message);
|
||||
$this->assertContains('Missing_module2', $message);
|
||||
$this->assertNotContains('Block', $message);
|
||||
$this->assertNotContains('Node', $message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -151,7 +151,7 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
|
||||
|
||||
$breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
|
||||
$this->assertEquals([], $breadcrumb->getLinks());
|
||||
$this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([], $breadcrumb->getCacheTags());
|
||||
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
|
||||
}
|
||||
@@ -168,7 +168,7 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
|
||||
|
||||
$breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
|
||||
$this->assertEquals([0 => new Link('Home', new Url('<front>'))], $breadcrumb->getLinks());
|
||||
$this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([], $breadcrumb->getCacheTags());
|
||||
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
|
||||
}
|
||||
@@ -203,7 +203,11 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
|
||||
|
||||
$breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
|
||||
$this->assertEquals([0 => new Link('Home', new Url('<front>')), 1 => new Link('Example', new Url('example'))], $breadcrumb->getLinks());
|
||||
$this->assertEquals(['url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([
|
||||
'url.path.is_front',
|
||||
'url.path.parent',
|
||||
'user.permissions',
|
||||
], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([], $breadcrumb->getCacheTags());
|
||||
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
|
||||
}
|
||||
@@ -254,7 +258,12 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
|
||||
new Link('Example', new Url('example')),
|
||||
new Link('Bar', new Url('example_bar')),
|
||||
], $breadcrumb->getLinks());
|
||||
$this->assertEquals(['bar', 'url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([
|
||||
'bar',
|
||||
'url.path.is_front',
|
||||
'url.path.parent',
|
||||
'user.permissions',
|
||||
], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals(['example'], $breadcrumb->getCacheTags());
|
||||
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
|
||||
}
|
||||
@@ -281,7 +290,7 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
|
||||
|
||||
// No path matched, though at least the frontpage is displayed.
|
||||
$this->assertEquals([0 => new Link('Home', new Url('<front>'))], $breadcrumb->getLinks());
|
||||
$this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([], $breadcrumb->getCacheTags());
|
||||
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
|
||||
}
|
||||
@@ -325,7 +334,7 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
|
||||
|
||||
// No path matched, though at least the frontpage is displayed.
|
||||
$this->assertEquals([0 => new Link('Home', new Url('<front>'))], $breadcrumb->getLinks());
|
||||
$this->assertEquals(['url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals(['url.path.is_front', 'url.path.parent'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([], $breadcrumb->getCacheTags());
|
||||
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
|
||||
}
|
||||
@@ -373,7 +382,11 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
|
||||
|
||||
$breadcrumb = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
|
||||
$this->assertEquals([0 => new Link('Home', new Url('<front>')), 1 => new Link('Admin', new Url('user_page'))], $breadcrumb->getLinks());
|
||||
$this->assertEquals(['url.path.parent', 'user.permissions'], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([
|
||||
'url.path.is_front',
|
||||
'url.path.parent',
|
||||
'user.permissions',
|
||||
], $breadcrumb->getCacheContexts());
|
||||
$this->assertEquals([], $breadcrumb->getCacheTags());
|
||||
$this->assertEquals(Cache::PERMANENT, $breadcrumb->getCacheMaxAge());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user