updated core to 8.6.1 via composer

This commit is contained in:
2018-09-12 13:58:26 +02:00
parent a9a219f2ed
commit ea56b9fba3
4443 changed files with 112098 additions and 40708 deletions
@@ -0,0 +1,222 @@
<?php
namespace Drupal\Tests;
use Drupal\Component\Utility\Html;
use Drupal\Core\Utility\Error;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Provides the debug functions for browser tests.
*/
trait BrowserHtmlDebugTrait {
/**
* Class name for HTML output logging.
*
* @var string
*/
protected $htmlOutputClassName;
/**
* Directory name for HTML output logging.
*
* @var string
*/
protected $htmlOutputDirectory;
/**
* Counter storage for HTML output logging.
*
* @var string
*/
protected $htmlOutputCounterStorage;
/**
* Counter for HTML output logging.
*
* @var int
*/
protected $htmlOutputCounter = 1;
/**
* HTML output output enabled.
*
* @var bool
*/
protected $htmlOutputEnabled = FALSE;
/**
* The file name to write the list of URLs to.
*
* This file is read by the PHPUnit result printer.
*
* @var string
*
* @see \Drupal\Tests\Listeners\HtmlOutputPrinter
*/
protected $htmlOutputFile;
/**
* HTML output test ID.
*
* @var int
*/
protected $htmlOutputTestId;
/**
* Formats HTTP headers as string for HTML output logging.
*
* @param array[] $headers
* Headers that should be formatted.
*
* @return string
* The formatted HTML string.
*/
protected function formatHtmlOutputHeaders(array $headers) {
$flattened_headers = array_map(function ($header) {
if (is_array($header)) {
return implode(';', array_map('trim', $header));
}
else {
return $header;
}
}, $headers);
return '<hr />Headers: <pre>' . Html::escape(var_export($flattened_headers, TRUE)) . '</pre>';
}
/**
* Returns headers in HTML output format.
*
* @return string
* HTML output headers.
*/
protected function getHtmlOutputHeaders() {
return $this->formatHtmlOutputHeaders($this->getSession()->getResponseHeaders());
}
/**
* Logs a HTML output message in a text file.
*
* The link to the HTML output message will be printed by the results printer.
*
* @param string|null $message
* (optional) The HTML output message to be stored. If not supplied the
* current page content is used.
*
* @see \Drupal\Tests\Listeners\VerbosePrinter::printResult()
*/
protected function htmlOutput($message = NULL) {
if (!$this->htmlOutputEnabled) {
return;
}
$message = $message ?: $this->getSession()->getPage()->getContent();
$message = '<hr />ID #' . $this->htmlOutputCounter . ' (<a href="' . $this->htmlOutputClassName . '-' . ($this->htmlOutputCounter - 1) . '-' . $this->htmlOutputTestId . '.html">Previous</a> | <a href="' . $this->htmlOutputClassName . '-' . ($this->htmlOutputCounter + 1) . '-' . $this->htmlOutputTestId . '.html">Next</a>)<hr />' . $message;
$html_output_filename = $this->htmlOutputClassName . '-' . $this->htmlOutputCounter . '-' . $this->htmlOutputTestId . '.html';
file_put_contents($this->htmlOutputDirectory . '/' . $html_output_filename, $message);
file_put_contents($this->htmlOutputCounterStorage, $this->htmlOutputCounter++);
// Do not use file_create_url() as the module_handler service might not be
// available.
$uri = $GLOBALS['base_url'] . '/sites/simpletest/browser_output/' . $html_output_filename;
file_put_contents($this->htmlOutputFile, $uri . "\n", FILE_APPEND);
}
/**
* Creates the directory to store browser output.
*
* Creates the directory to store browser output in if a file to write
* URLs to has been created by \Drupal\Tests\Listeners\HtmlOutputPrinter.
*/
protected function initBrowserOutputFile() {
$browser_output_file = getenv('BROWSERTEST_OUTPUT_FILE');
$this->htmlOutputEnabled = is_file($browser_output_file);
if ($this->htmlOutputEnabled) {
$this->htmlOutputFile = $browser_output_file;
$this->htmlOutputClassName = str_replace("\\", "_", get_called_class());
$this->htmlOutputDirectory = DRUPAL_ROOT . '/sites/simpletest/browser_output';
// Do not use the file_system service so this method can be called before
// it is available.
if (!is_dir($this->htmlOutputDirectory)) {
mkdir($this->htmlOutputDirectory, 0775, TRUE);
}
if (!file_exists($this->htmlOutputDirectory . '/.htaccess')) {
file_put_contents($this->htmlOutputDirectory . '/.htaccess', "<IfModule mod_expires.c>\nExpiresActive Off\n</IfModule>\n");
}
$this->htmlOutputCounterStorage = $this->htmlOutputDirectory . '/' . $this->htmlOutputClassName . '.counter';
$this->htmlOutputTestId = str_replace('sites/simpletest/', '', $this->siteDirectory);
if (is_file($this->htmlOutputCounterStorage)) {
$this->htmlOutputCounter = max(1, (int) file_get_contents($this->htmlOutputCounterStorage)) + 1;
}
}
}
/**
* Provides a Guzzle middleware handler to log every response received.
*
* @return callable
* The callable handler that will do the logging.
*/
protected function getResponseLogHandler() {
return function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
return $handler($request, $options)
->then(function (ResponseInterface $response) use ($request) {
if ($this->htmlOutputEnabled) {
$caller = $this->getTestMethodCaller();
$html_output = 'Called from ' . $caller['function'] . ' line ' . $caller['line'];
$html_output .= '<hr />' . $request->getMethod() . ' request to: ' . $request->getUri();
// On redirect responses (status code starting with '3') we need
// to remove the meta tag that would do a browser refresh. We
// don't want to redirect developers away when they look at the
// debug output file in their browser.
$body = $response->getBody();
$status_code = (string) $response->getStatusCode();
if ($status_code[0] === '3') {
$body = preg_replace('#<meta http-equiv="refresh" content=.+/>#', '', $body, 1);
}
$html_output .= '<hr />' . $body;
$html_output .= $this->formatHtmlOutputHeaders($response->getHeaders());
$this->htmlOutput($html_output);
}
return $response;
});
};
};
}
/**
* Retrieves the current calling line in the class under test.
*
* @return array
* An associative array with keys 'file', 'line' and 'function'.
*/
protected function getTestMethodCaller() {
$backtrace = debug_backtrace();
// Find the test class that has the test method.
while ($caller = Error::getLastCaller($backtrace)) {
if (isset($caller['class']) && $caller['class'] === get_class($this)) {
break;
}
// If the test method is implemented by a test class's parent then the
// class name of $this will not be part of the backtrace.
// In that case we process the backtrace until the caller is not a
// subclass of $this and return the previous caller.
if (isset($last_caller) && (!isset($caller['class']) || !is_subclass_of($this, $caller['class']))) {
// Return the last caller since that has to be the test class.
$caller = $last_caller;
break;
}
// Otherwise we have not reached our test class yet: save the last caller
// and remove an element from to backtrace to process the next call.
$last_caller = $caller;
array_shift($backtrace);
}
return $caller;
}
}
+69 -649
View File
@@ -7,22 +7,17 @@ use Behat\Mink\Element\Element;
use Behat\Mink\Mink;
use Behat\Mink\Selector\SelectorsHandler;
use Behat\Mink\Session;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Database\Database;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AnonymousUserSession;
use Drupal\Core\Test\FunctionalTestSetupTrait;
use Drupal\Core\Test\TestSetupTrait;
use Drupal\Core\Url;
use Drupal\Core\Utility\Error;
use Drupal\FunctionalTests\AssertLegacyTrait;
use Drupal\Tests\block\Traits\BlockCreationTrait;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\Tests\user\Traits\UserCreationTrait;
use GuzzleHttp\Cookie\CookieJar;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
@@ -44,14 +39,15 @@ use Symfony\Component\CssSelector\CssSelectorConverter;
abstract class BrowserTestBase extends TestCase {
use FunctionalTestSetupTrait;
use UiHelperTrait {
FunctionalTestSetupTrait::refreshVariables insteadof UiHelperTrait;
}
use TestSetupTrait;
use AssertHelperTrait;
use BlockCreationTrait {
placeBlock as drupalPlaceBlock;
}
use AssertLegacyTrait;
use RandomGeneratorTrait;
use SessionTestTrait;
use NodeCreationTrait {
getNodeByTitle as drupalGetNodeByTitle;
createNode as drupalCreateNode;
@@ -118,13 +114,6 @@ abstract class BrowserTestBase extends TestCase {
*/
protected $profile = 'testing';
/**
* The current user logged in using the Mink controlled browser.
*
* @var \Drupal\user\UserInterface
*/
protected $loggedInUser = FALSE;
/**
* An array of custom translations suitable for drupal_rewrite_settings().
*
@@ -140,7 +129,7 @@ abstract class BrowserTestBase extends TestCase {
*
* Value can be overridden using the environment variable MINK_DRIVER_CLASS.
*
* @var string.
* @var string
*/
protected $minkDefaultDriverClass = GoutteDriver::class;
@@ -181,59 +170,6 @@ abstract class BrowserTestBase extends TestCase {
*/
protected $preserveGlobalState = FALSE;
/**
* Class name for HTML output logging.
*
* @var string
*/
protected $htmlOutputClassName;
/**
* Directory name for HTML output logging.
*
* @var string
*/
protected $htmlOutputDirectory;
/**
* Counter storage for HTML output logging.
*
* @var string
*/
protected $htmlOutputCounterStorage;
/**
* Counter for HTML output logging.
*
* @var int
*/
protected $htmlOutputCounter = 1;
/**
* HTML output output enabled.
*
* @var bool
*/
protected $htmlOutputEnabled = FALSE;
/**
* The file name to write the list of URLs to.
*
* This file is read by the PHPUnit result printer.
*
* @var string
*
* @see \Drupal\Tests\Listeners\HtmlOutputPrinter
*/
protected $htmlOutputFile;
/**
* HTML output test ID.
*
* @var int
*/
protected $htmlOutputTestId;
/**
* The base URL.
*
@@ -248,20 +184,6 @@ abstract class BrowserTestBase extends TestCase {
*/
protected $originalShutdownCallbacks = [];
/**
* The number of meta refresh redirects to follow, or NULL if unlimited.
*
* @var null|int
*/
protected $maximumMetaRefreshCount = NULL;
/**
* The number of meta refresh redirects followed during ::drupalGet().
*
* @var int
*/
protected $metaRefreshCount = 0;
/**
* The app root.
*
@@ -313,7 +235,7 @@ abstract class BrowserTestBase extends TestCase {
}
$selectors_handler = new SelectorsHandler([
'hidden_field_selector' => new HiddenFieldSelector()
'hidden_field_selector' => new HiddenFieldSelector(),
]);
$session = new Session($driver, $selectors_handler);
$this->mink = new Mink();
@@ -321,20 +243,29 @@ abstract class BrowserTestBase extends TestCase {
$this->mink->setDefaultSessionName('default');
$this->registerSessions();
// According to the W3C WebDriver specification a cookie can only be set if
// the cookie domain is equal to the domain of the active document. When the
// browser starts up the active document is not our domain but 'about:blank'
// or similar. To be able to set our User-Agent and Xdebug cookies at the
// start of the test we now do a request to the front page so the active
// document matches the domain.
// @see https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie
// @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=20975
$session = $this->getSession();
$session->visit($this->baseUrl);
$this->initFrontPage();
return $session;
}
/**
* Visits the front page when initializing Mink.
*
* According to the W3C WebDriver specification a cookie can only be set if
* the cookie domain is equal to the domain of the active document. When the
* browser starts up the active document is not our domain but 'about:blank'
* or similar. To be able to set our User-Agent and Xdebug cookies at the
* start of the test we now do a request to the front page so the active
* document matches the domain.
*
* @see https://w3c.github.io/webdriver/webdriver-spec.html#add-cookie
* @see https://www.w3.org/Bugs/Public/show_bug.cgi?id=20975
*/
protected function initFrontPage() {
$session = $this->getSession();
$session->visit($this->baseUrl);
}
/**
* Gets an instance of the default Mink driver.
*
@@ -371,30 +302,6 @@ abstract class BrowserTestBase extends TestCase {
return $driver;
}
/**
* Creates the directory to store browser output.
*
* Creates the directory to store browser output in if a file to write
* URLs to has been created by \Drupal\Tests\Listeners\HtmlOutputPrinter.
*/
protected function initBrowserOutputFile() {
$browser_output_file = getenv('BROWSERTEST_OUTPUT_FILE');
$this->htmlOutputEnabled = is_file($browser_output_file);
if ($this->htmlOutputEnabled) {
$this->htmlOutputFile = $browser_output_file;
$this->htmlOutputClassName = str_replace("\\", "_", get_called_class());
$this->htmlOutputDirectory = DRUPAL_ROOT . '/sites/simpletest/browser_output';
if (file_prepare_directory($this->htmlOutputDirectory, FILE_CREATE_DIRECTORY) && !file_exists($this->htmlOutputDirectory . '/.htaccess')) {
file_put_contents($this->htmlOutputDirectory . '/.htaccess', "<IfModule mod_expires.c>\nExpiresActive Off\n</IfModule>\n");
}
$this->htmlOutputCounterStorage = $this->htmlOutputDirectory . '/' . $this->htmlOutputClassName . '.counter';
$this->htmlOutputTestId = str_replace('sites/simpletest/', '', $this->siteDirectory);
if (is_file($this->htmlOutputCounterStorage)) {
$this->htmlOutputCounter = max(1, (int) file_get_contents($this->htmlOutputCounterStorage)) + 1;
}
}
}
/**
* Get the Mink driver args from an environment variable, if it is set. Can
* be overridden in a derived class so it is possible to use a different
@@ -584,398 +491,44 @@ abstract class BrowserTestBase extends TestCase {
}
/**
* Returns WebAssert object.
* Get session cookies from current session.
*
* @param string $name
* (optional) Name of the session. Defaults to the active session.
*
* @return \Drupal\Tests\WebAssert
* A new web-assert option for asserting the presence of elements with.
* @return \GuzzleHttp\Cookie\CookieJar
* A cookie jar with the current session.
*/
public function assertSession($name = NULL) {
return new WebAssert($this->getSession($name), $this->baseUrl);
protected function getSessionCookies() {
$domain = parse_url($this->getUrl(), PHP_URL_HOST);
$session_id = $this->getSession()->getCookie($this->getSessionName());
$cookies = CookieJar::fromArray([$this->getSessionName() => $session_id], $domain);
return $cookies;
}
/**
* Prepare for a request to testing site.
* Obtain the HTTP client for the system under test.
*
* The testing site is protected via a SIMPLETEST_USER_AGENT cookie that is
* checked by drupal_valid_test_ua().
* Use this method for arbitrary HTTP requests to the site under test. For
* most tests, you should not get the HTTP client and instead use navigation
* methods such as drupalGet() and clickLink() in order to benefit from
* assertions.
*
* @see drupal_valid_test_ua()
* Subclasses which substitute a different Mink driver should override this
* method and provide a Guzzle client if the Mink driver provides one.
*
* @return \GuzzleHttp\ClientInterface
* The client with BrowserTestBase configuration.
*
* @throws \RuntimeException
* If the Mink driver does not support a Guzzle HTTP client, throw an
* exception.
*/
protected function prepareRequest() {
$session = $this->getSession();
$session->setCookie('SIMPLETEST_USER_AGENT', drupal_generate_test_ua($this->databasePrefix));
}
/**
* Builds an a absolute URL from a system path or a URL object.
*
* @param string|\Drupal\Core\Url $path
* A system path or a URL.
* @param array $options
* Options to be passed to Url::fromUri().
*
* @return string
* An absolute URL stsring.
*/
protected function buildUrl($path, array $options = []) {
if ($path instanceof Url) {
$url_options = $path->getOptions();
$options = $url_options + $options;
$path->setOptions($options);
return $path->setAbsolute()->toString();
protected function getHttpClient() {
/* @var $mink_driver \Behat\Mink\Driver\DriverInterface */
$mink_driver = $this->getSession()->getDriver();
if ($mink_driver instanceof GoutteDriver) {
return $mink_driver->getClient()->getClient();
}
// The URL generator service is not necessarily available yet; e.g., in
// interactive installer tests.
elseif ($this->container->has('url_generator')) {
$force_internal = isset($options['external']) && $options['external'] == FALSE;
if (!$force_internal && UrlHelper::isExternal($path)) {
return Url::fromUri($path, $options)->toString();
}
else {
$uri = $path === '<front>' ? 'base:/' : 'base:/' . $path;
// Path processing is needed for language prefixing. Skip it when a
// path that may look like an external URL is being used as internal.
$options['path_processing'] = !$force_internal;
return Url::fromUri($uri, $options)
->setAbsolute()
->toString();
}
}
else {
return $this->getAbsoluteUrl($path);
}
}
/**
* Retrieves a Drupal path or an absolute path.
*
* @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
* An array containing additional HTTP request headers, the array keys are
* the header names and the array values the header values. This is useful
* to set for example the "Accept-Language" header for requesting the page
* in a different language. Note that not all headers are supported, for
* example the "Accept" header is always overridden by the browser. For
* testing REST APIs it is recommended to directly use an HTTP client such
* as Guzzle instead.
*
* @return string
* The retrieved HTML string, also available as $this->getRawContent()
*/
protected function drupalGet($path, array $options = [], array $headers = []) {
$options['absolute'] = TRUE;
$url = $this->buildUrl($path, $options);
$session = $this->getSession();
$this->prepareRequest();
foreach ($headers as $header_name => $header_value) {
$session->setRequestHeader($header_name, $header_value);
}
$session->visit($url);
$out = $session->getPage()->getContent();
// Ensure that any changes to variables in the other thread are picked up.
$this->refreshVariables();
// Replace original page output with new output from redirected page(s).
if ($new = $this->checkForMetaRefresh()) {
$out = $new;
// We are finished with all meta refresh redirects, so reset the counter.
$this->metaRefreshCount = 0;
}
// Log only for JavascriptTestBase tests because for Goutte we log with
// ::getResponseLogHandler.
if ($this->htmlOutputEnabled && !($this->getSession()->getDriver() instanceof GoutteDriver)) {
$html_output = 'GET request to: ' . $url .
'<hr />Ending URL: ' . $this->getSession()->getCurrentUrl();
$html_output .= '<hr />' . $out;
$html_output .= $this->getHtmlOutputHeaders();
$this->htmlOutput($html_output);
}
return $out;
}
/**
* Takes a path and returns an absolute path.
*
* @param string $path
* A path from the Mink controlled browser content.
*
* @return string
* The $path with $base_url prepended, if necessary.
*/
protected function getAbsoluteUrl($path) {
global $base_url, $base_path;
$parts = parse_url($path);
if (empty($parts['host'])) {
// Ensure that we have a string (and no xpath object).
$path = (string) $path;
// Strip $base_path, if existent.
$length = strlen($base_path);
if (substr($path, 0, $length) === $base_path) {
$path = substr($path, $length);
}
// Ensure that we have an absolute path.
if (empty($path) || $path[0] !== '/') {
$path = '/' . $path;
}
// Finally, prepend the $base_url.
$path = $base_url . $path;
}
return $path;
}
/**
* Logs in a user using the Mink controlled browser.
*
* If a user is already logged in, then the current user is logged out before
* logging in the specified user.
*
* Please note that neither the current user nor the passed-in user object is
* populated with data of the logged in user. If you need full access to the
* user object after logging in, it must be updated manually. If you also need
* access to the plain-text password of the user (set by drupalCreateUser()),
* e.g. to log in the same user again, then it must be re-assigned manually.
* For example:
* @code
* // Create a user.
* $account = $this->drupalCreateUser(array());
* $this->drupalLogin($account);
* // Load real user object.
* $pass_raw = $account->passRaw;
* $account = User::load($account->id());
* $account->passRaw = $pass_raw;
* @endcode
*
* @param \Drupal\Core\Session\AccountInterface $account
* User object representing the user to log in.
*
* @see drupalCreateUser()
*/
protected function drupalLogin(AccountInterface $account) {
if ($this->loggedInUser) {
$this->drupalLogout();
}
$this->drupalGet('user/login');
$this->submitForm([
'name' => $account->getUsername(),
'pass' => $account->passRaw,
], t('Log in'));
// @see BrowserTestBase::drupalUserIsLoggedIn()
$account->sessionId = $this->getSession()->getCookie($this->getSessionName());
$this->assertTrue($this->drupalUserIsLoggedIn($account), new FormattableMarkup('User %name successfully logged in.', ['%name' => $account->getAccountName()]));
$this->loggedInUser = $account;
$this->container->get('current_user')->setAccount($account);
}
/**
* Logs a user out of the Mink controlled browser and confirms.
*
* Confirms logout by checking the login page.
*/
protected function drupalLogout() {
// Make a request to the logout page, and redirect to the user page, the
// idea being if you were properly logged out you should be seeing a login
// screen.
$assert_session = $this->assertSession();
$this->drupalGet('user/logout', ['query' => ['destination' => 'user']]);
$assert_session->fieldExists('name');
$assert_session->fieldExists('pass');
// @see BrowserTestBase::drupalUserIsLoggedIn()
unset($this->loggedInUser->sessionId);
$this->loggedInUser = FALSE;
$this->container->get('current_user')->setAccount(new AnonymousUserSession());
}
/**
* Fills and submits a form.
*
* @param array $edit
* Field data in an associative array. Changes the current input fields
* (where possible) to the values indicated.
*
* A checkbox can be set to TRUE to be checked and should be set to FALSE to
* be unchecked.
* @param string $submit
* Value of the submit button whose click is to be emulated. For example,
* 'Save'. The processing of the request depends on this value. For example,
* a form may have one button with the value 'Save' and another button with
* the value 'Delete', and execute different code depending on which one is
* clicked.
* @param string $form_html_id
* (optional) HTML ID of the form to be submitted. On some pages
* there are many identical forms, so just using the value of the submit
* button is not enough. For example: 'trigger-node-presave-assign-form'.
* Note that this is not the Drupal $form_id, but rather the HTML ID of the
* form, which is typically the same thing but with hyphens replacing the
* underscores.
*/
protected function submitForm(array $edit, $submit, $form_html_id = NULL) {
$assert_session = $this->assertSession();
// Get the form.
if (isset($form_html_id)) {
$form = $assert_session->elementExists('xpath', "//form[@id='$form_html_id']");
$submit_button = $assert_session->buttonExists($submit, $form);
$action = $form->getAttribute('action');
}
else {
$submit_button = $assert_session->buttonExists($submit);
$form = $assert_session->elementExists('xpath', './ancestor::form', $submit_button);
$action = $form->getAttribute('action');
}
// Edit the form values.
foreach ($edit as $name => $value) {
$field = $assert_session->fieldExists($name, $form);
// Provide support for the values '1' and '0' for checkboxes instead of
// TRUE and FALSE.
// @todo Get rid of supporting 1/0 by converting all tests cases using
// this to boolean values.
$field_type = $field->getAttribute('type');
if ($field_type === 'checkbox') {
$value = (bool) $value;
}
$field->setValue($value);
}
// Submit form.
$this->prepareRequest();
$submit_button->press();
// Ensure that any changes to variables in the other thread are picked up.
$this->refreshVariables();
// Check if there are any meta refresh redirects (like Batch API pages).
if ($this->checkForMetaRefresh()) {
// We are finished with all meta refresh redirects, so reset the counter.
$this->metaRefreshCount = 0;
}
// Log only for JavascriptTestBase tests because for Goutte we log with
// ::getResponseLogHandler.
if ($this->htmlOutputEnabled && !($this->getSession()->getDriver() instanceof GoutteDriver)) {
$out = $this->getSession()->getPage()->getContent();
$html_output = 'POST request to: ' . $action .
'<hr />Ending URL: ' . $this->getSession()->getCurrentUrl();
$html_output .= '<hr />' . $out;
$html_output .= $this->getHtmlOutputHeaders();
$this->htmlOutput($html_output);
}
}
/**
* Executes a form submission.
*
* It will be done as usual POST request with Mink.
*
* @param \Drupal\Core\Url|string $path
* Location of the post form. Either a Drupal path or an absolute path or
* NULL to post to the current page. For multi-stage forms you can set the
* path to NULL and have it post to the last received page. Example:
*
* @code
* // First step in form.
* $edit = array(...);
* $this->drupalPostForm('some_url', $edit, 'Save');
*
* // Second step in form.
* $edit = array(...);
* $this->drupalPostForm(NULL, $edit, 'Save');
* @endcode
* @param array $edit
* Field data in an associative array. Changes the current input fields
* (where possible) to the values indicated.
*
* When working with form tests, the keys for an $edit element should match
* the 'name' parameter of the HTML of the form. For example, the 'body'
* field for a node has the following HTML:
* @code
* <textarea id="edit-body-und-0-value" class="text-full form-textarea
* resize-vertical" placeholder="" cols="60" rows="9"
* name="body[0][value]"></textarea>
* @endcode
* When testing this field using an $edit parameter, the code becomes:
* @code
* $edit["body[0][value]"] = 'My test value';
* @endcode
*
* A checkbox can be set to TRUE to be checked and should be set to FALSE to
* be unchecked. Multiple select fields can be tested using 'name[]' and
* setting each of the desired values in an array:
* @code
* $edit = array();
* $edit['name[]'] = array('value1', 'value2');
* @endcode
* @todo change $edit to disallow NULL as a value for Drupal 9.
* https://www.drupal.org/node/2802401
* @param string $submit
* Value of the submit button whose click is to be emulated. For example,
* 'Save'. The processing of the request depends on this value. For example,
* a form may have one button with the value 'Save' and another button with
* the value 'Delete', and execute different code depending on which one is
* clicked.
*
* This function can also be called to emulate an Ajax submission. In this
* case, this value needs to be an array with the following keys:
* - path: A path to submit the form values to for Ajax-specific processing.
* - triggering_element: If the value for the 'path' key is a generic Ajax
* processing path, this needs to be set to the name of the element. If
* the name doesn't identify the element uniquely, then this should
* instead be an array with a single key/value pair, corresponding to the
* element name and value. The \Drupal\Core\Form\FormAjaxResponseBuilder
* uses this to find the #ajax information for the element, including
* which specific callback to use for processing the request.
*
* This can also be set to NULL in order to emulate an Internet Explorer
* submission of a form with a single text field, and pressing ENTER in that
* textfield: under these conditions, no button information is added to the
* POST data.
* @param array $options
* Options to be forwarded to the url generator.
*
* @return string
* (deprecated) The response content after submit form. It is necessary for
* backwards compatibility and will be removed before Drupal 9.0. You should
* just use the webAssert object for your assertions.
*/
protected function drupalPostForm($path, $edit, $submit, array $options = []) {
if (is_object($submit)) {
// Cast MarkupInterface objects to string.
$submit = (string) $submit;
}
if ($edit === NULL) {
$edit = [];
}
if (is_array($edit)) {
$edit = $this->castSafeStrings($edit);
}
if (isset($path)) {
$this->drupalGet($path, $options);
}
$this->submitForm($edit, $submit);
return $this->getSession()->getPage()->getContent();
throw new \RuntimeException('The Mink client type ' . get_class($mink_driver) . ' does not support getHttpClient().');
}
/**
@@ -1017,36 +570,6 @@ abstract class BrowserTestBase extends TestCase {
$this->rebuildAll();
}
/**
* Returns whether a given user account is logged in.
*
* @param \Drupal\Core\Session\AccountInterface $account
* The user account object to check.
*
* @return bool
* Return TRUE if the user is logged in, FALSE otherwise.
*/
protected function drupalUserIsLoggedIn(AccountInterface $account) {
$logged_in = FALSE;
if (isset($account->sessionId)) {
$session_handler = $this->container->get('session_handler.storage');
$logged_in = (bool) $session_handler->read($account->sessionId);
}
return $logged_in;
}
/**
* Clicks the element with the given CSS selector.
*
* @param string $css_selector
* The CSS selector identifying the element to click.
*/
protected function click($css_selector) {
$this->getSession()->getDriver()->click($this->cssSelectToXpath($css_selector));
}
/**
* Prevents serializing any properties.
*
@@ -1065,58 +588,6 @@ abstract class BrowserTestBase extends TestCase {
return [];
}
/**
* Logs a HTML output message in a text file.
*
* The link to the HTML output message will be printed by the results printer.
*
* @param string $message
* The HTML output message to be stored.
*
* @see \Drupal\Tests\Listeners\VerbosePrinter::printResult()
*/
protected function htmlOutput($message) {
if (!$this->htmlOutputEnabled) {
return;
}
$message = '<hr />ID #' . $this->htmlOutputCounter . ' (<a href="' . $this->htmlOutputClassName . '-' . ($this->htmlOutputCounter - 1) . '-' . $this->htmlOutputTestId . '.html">Previous</a> | <a href="' . $this->htmlOutputClassName . '-' . ($this->htmlOutputCounter + 1) . '-' . $this->htmlOutputTestId . '.html">Next</a>)<hr />' . $message;
$html_output_filename = $this->htmlOutputClassName . '-' . $this->htmlOutputCounter . '-' . $this->htmlOutputTestId . '.html';
file_put_contents($this->htmlOutputDirectory . '/' . $html_output_filename, $message);
file_put_contents($this->htmlOutputCounterStorage, $this->htmlOutputCounter++);
file_put_contents($this->htmlOutputFile, file_create_url('sites/simpletest/browser_output/' . $html_output_filename) . "\n", FILE_APPEND);
}
/**
* Returns headers in HTML output format.
*
* @return string
* HTML output headers.
*/
protected function getHtmlOutputHeaders() {
return $this->formatHtmlOutputHeaders($this->getSession()->getResponseHeaders());
}
/**
* Formats HTTP headers as string for HTML output logging.
*
* @param array[] $headers
* Headers that should be formatted.
*
* @return string
* The formatted HTML string.
*/
protected function formatHtmlOutputHeaders(array $headers) {
$flattened_headers = array_map(function ($header) {
if (is_array($header)) {
return implode(';', array_map('trim', $header));
}
else {
return $header;
}
}, $headers);
return '<hr />Headers: <pre>' . Html::escape(var_export($flattened_headers, TRUE)) . '</pre>';
}
/**
* Translates a CSS expression to its XPath equivalent.
*
@@ -1136,47 +607,6 @@ abstract class BrowserTestBase extends TestCase {
return (new CssSelectorConverter($html))->toXPath($selector, $prefix);
}
/**
* Searches elements using a CSS selector in the raw content.
*
* The search is relative to the root element (HTML tag normally) of the page.
*
* @param string $selector
* CSS selector to use in the search.
*
* @return \Behat\Mink\Element\NodeElement[]
* The list of elements on the page that match the selector.
*/
protected function cssSelect($selector) {
return $this->getSession()->getPage()->findAll('css', $selector);
}
/**
* Follows a link by complete name.
*
* Will click the first link found with this link text.
*
* If the link is discovered and clicked, the test passes. Fail otherwise.
*
* @param string|\Drupal\Component\Render\MarkupInterface $label
* Text between the anchor tags.
* @param int $index
* (optional) The index number for cases where multiple links have the same
* text. Defaults to 0.
*/
protected function clickLink($label, $index = 0) {
$label = (string) $label;
$links = $this->getSession()->getPage()->findAll('named', ['link', $label]);
$links[$index]->click();
}
/**
* Retrieves the plain-text content from the current page.
*/
protected function getTextContent() {
return $this->getSession()->getPage()->getText();
}
/**
* Performs an xpath search on the contents of the internal browser.
*
@@ -1240,16 +670,6 @@ abstract class BrowserTestBase extends TestCase {
return $this->getSession()->getResponseHeader($name);
}
/**
* Get the current URL from the browser.
*
* @return string
* The current URL.
*/
protected function getUrl() {
return $this->getSession()->getCurrentUrl();
}
/**
* Gets the JavaScript drupalSettings variable for the currently-loaded page.
*
@@ -1308,25 +728,25 @@ abstract class BrowserTestBase extends TestCase {
}
/**
* Checks for meta refresh tag and if found call drupalGet() recursively.
* Transforms a nested array into a flat array suitable for drupalPostForm().
*
* This function looks for the http-equiv attribute to be set to "Refresh" and
* is case-insensitive.
* @param array $values
* A multi-dimensional form values array to convert.
*
* @return string|false
* Either the new page content or FALSE.
* @return array
* The flattened $edit array suitable for BrowserTestBase::drupalPostForm().
*/
protected function checkForMetaRefresh() {
$refresh = $this->cssSelect('meta[http-equiv="Refresh"], meta[http-equiv="refresh"]');
if (!empty($refresh) && (!isset($this->maximumMetaRefreshCount) || $this->metaRefreshCount < $this->maximumMetaRefreshCount)) {
// Parse the content attribute of the meta tag for the format:
// "[delay]: URL=[page_to_redirect_to]".
if (preg_match('/\d+;\s*URL=(?<url>.*)/i', $refresh[0]->getAttribute('content'), $match)) {
$this->metaRefreshCount++;
return $this->drupalGet($this->getAbsoluteUrl(Html::decodeEntities($match['url'])));
}
protected function translatePostValues(array $values) {
$edit = [];
// The easiest and most straightforward way to translate values suitable for
// BrowserTestBase::drupalPostForm() is to actually build the POST data
// string and convert the resulting key/value pairs back into a flat array.
$query = http_build_query($values);
foreach (explode('&', $query) as $item) {
list($key, $value) = explode('=', $item);
$edit[urldecode($key)] = urldecode($value);
}
return FALSE;
return $edit;
}
}
@@ -31,7 +31,7 @@ class AnnotatedClassDiscoveryCachedTest extends TestCase {
*/
public function testGetDefinitions() {
// Path to the classes which we'll discover and parse annotation.
$discovery_path = __DIR__ . '/Fixtures';
$discovery_path = __DIR__ . '/Fixtures';
// File path that should be discovered within that directory.
$file_path = $discovery_path . '/PluginNamespace/DiscoveryTest1.php';
@@ -159,7 +159,7 @@ class InspectorTest extends TestCase {
[__CLASS__, 'callMeStatic'],
function () {
return TRUE;
}
},
]));
$this->assertFalse(Inspector::assertAllCallable([
@@ -169,7 +169,7 @@ class InspectorTest extends TestCase {
function () {
return TRUE;
},
"I'm not callable"
"I'm not callable",
]));
}
@@ -256,6 +256,7 @@ class InspectorTest extends TestCase {
* Quick class for testing for objects with __toString.
*/
class StringObject {
/**
* {@inheritdoc}
*/
@@ -5,6 +5,9 @@ namespace Drupal\Tests\Component\Bridge;
use Drupal\Component\Bridge\ZfExtensionManagerSfContainer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Zend\Feed\Reader\Extension\Atom\Entry;
use Zend\Feed\Reader\StandaloneExtensionManager;
/**
* @coversDefaultClass \Drupal\Component\Bridge\ZfExtensionManagerSfContainer
@@ -14,6 +17,7 @@ class ZfExtensionManagerSfContainerTest extends TestCase {
/**
* @covers ::setContainer
* @covers ::setStandalone
* @covers ::get
*/
public function testGet() {
@@ -24,10 +28,16 @@ class ZfExtensionManagerSfContainerTest extends TestCase {
$bridge = new ZfExtensionManagerSfContainer();
$bridge->setContainer($container);
$this->assertEquals($service, $bridge->get('foo'));
$bridge->setStandalone(StandaloneExtensionManager::class);
$this->assertInstanceOf(Entry::class, $bridge->get('Atom\Entry'));
// Ensure that the container is checked first.
$container->set('atomentry', $service);
$this->assertEquals($service, $bridge->get('Atom\Entry'));
}
/**
* @covers ::setContainer
* @covers ::setStandalone
* @covers ::has
*/
public function testHas() {
@@ -39,6 +49,42 @@ class ZfExtensionManagerSfContainerTest extends TestCase {
$bridge->setContainer($container);
$this->assertTrue($bridge->has('foo'));
$this->assertFalse($bridge->has('bar'));
$this->assertFalse($bridge->has('Atom\Entry'));
$bridge->setStandalone(StandaloneExtensionManager::class);
$this->assertTrue($bridge->has('Atom\Entry'));
}
/**
* @covers ::setStandalone
*/
public function testSetStandaloneException() {
if (method_exists($this, 'expectException')) {
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Drupal\Tests\Component\Bridge\ZfExtensionManagerSfContainerTest must implement Zend\Feed\Reader\ExtensionManagerInterface or Zend\Feed\Writer\ExtensionManagerInterface');
}
else {
$this->setExpectedException(\RuntimeException::class, 'Drupal\Tests\Component\Bridge\ZfExtensionManagerSfContainerTest must implement Zend\Feed\Reader\ExtensionManagerInterface or Zend\Feed\Writer\ExtensionManagerInterface');
}
$bridge = new ZfExtensionManagerSfContainer();
$bridge->setStandalone(static::class);
}
/**
* @covers ::get
*/
public function testGetContainerException() {
if (method_exists($this, 'expectException')) {
$this->expectException(ServiceNotFoundException::class);
$this->expectExceptionMessage('You have requested a non-existent service "test.foo".');
}
else {
$this->setExpectedException(ServiceNotFoundException::class, 'You have requested a non-existent service "test.foo".');
}
$container = new ContainerBuilder();
$bridge = new ZfExtensionManagerSfContainer('test.');
$bridge->setContainer($container);
$bridge->setStandalone(StandaloneExtensionManager::class);
$bridge->get('foo');
}
/**
@@ -891,4 +891,29 @@ class DateTimePlusTest extends TestCase {
$date->setTimezone(new \DateTimeZone('America/New_York'))->nonexistent();
}
/**
* @covers ::getPhpDateTime
*/
public function testGetPhpDateTime() {
$new_york = new \DateTimeZone('America/New_York');
$berlin = new \DateTimeZone('Europe/Berlin');
// Test retrieving a cloned copy of the wrapped \DateTime object, and that
// altering it does not change the DateTimePlus object.
$datetimeplus = DateTimePlus::createFromFormat('Y-m-d H:i:s', '2017-07-13 22:40:00', $new_york, ['langcode' => 'en']);
$this->assertEquals(1500000000, $datetimeplus->getTimestamp());
$this->assertEquals('America/New_York', $datetimeplus->getTimezone()->getName());
$datetime = $datetimeplus->getPhpDateTime();
$this->assertInstanceOf('DateTime', $datetime);
$this->assertEquals(1500000000, $datetime->getTimestamp());
$this->assertEquals('America/New_York', $datetime->getTimezone()->getName());
$datetime->setTimestamp(1400000000)->setTimezone($berlin);
$this->assertEquals(1400000000, $datetime->getTimestamp());
$this->assertEquals('Europe/Berlin', $datetime->getTimezone()->getName());
$this->assertEquals(1500000000, $datetimeplus->getTimestamp());
$this->assertEquals('America/New_York', $datetimeplus->getTimezone()->getName());
}
}
@@ -993,7 +993,7 @@ class ContainerTest extends TestCase {
'arguments' => [],
'configurator' => [
$this->getServiceCall('configurator'),
'configureService'
'configureService',
],
];
$services['configurable_service_exception'] = [
@@ -91,7 +91,7 @@ class RegexDirectoryIteratorTest extends TestCase {
[
'1.yml',
'2.yml',
'3.txt'
'3.txt',
],
],
[
@@ -63,7 +63,6 @@ class PluginBaseTest extends TestCase {
];
}
/**
* @dataProvider providerTestGetDerivativeId
* @covers ::getDerivativeId
@@ -3,7 +3,7 @@
namespace Drupal\Tests\Component\Render;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Render\MarkupInterface;
use PHPUnit\Framework\TestCase;
@@ -28,7 +28,7 @@ class PlainTextOutputTest extends TestCase {
* @dataProvider providerRenderFromHtml
*/
public function testRenderFromHtml($expected, $string, $args = []) {
$markup = SafeMarkup::format($string, $args);
$markup = new FormattableMarkup($string, $args);
$output = PlainTextOutput::renderFromHtml($markup);
$this->assertSame($expected, $output);
}
@@ -32,7 +32,6 @@ class JsonTest extends TestCase {
*/
protected $htmlUnsafeEscaped;
/**
* {@inheritdoc}
*/
@@ -37,7 +37,7 @@ abstract class YamlTestBase extends TestCase {
[10],
[0 => '123456'],
],
[NULL]
[NULL],
];
}
@@ -61,7 +61,7 @@ class ArgumentsResolverTest extends TestCase {
// Test with a raw value that overrides the provided upcast value, since
// it is not typehinted.
$scalars = ['foo' => 'baz'];
$scalars = ['foo' => 'baz'];
$objects = ['foo' => new \stdClass()];
$data[] = [
function ($foo) {}, $scalars, $objects, [], ['baz'],
@@ -206,6 +206,7 @@ class ArgumentsResolverTest extends TestCase {
* Provides a test class.
*/
class TestClass {
public function access($foo) {
}
@@ -61,7 +61,7 @@ class ColorTest extends TestCase {
// Add invalid data types (hex value must be a string).
foreach ([
1, 12, 1234, 12345, 123456, 1234567, 12345678, 123456789, 123456789,
-1, PHP_INT_MAX, PHP_INT_MAX + 1, -PHP_INT_MAX, 0x0, 0x010
-1, PHP_INT_MAX, PHP_INT_MAX + 1, -PHP_INT_MAX, 0x0, 0x010,
] as $value) {
$invalid[] = [$value, '', TRUE];
}
@@ -265,7 +265,7 @@ class NestedArrayTest extends TestCase {
public function providerTestFilter() {
$data = [];
$data['1d-array'] = [
[0, 1, '', TRUE], NULL, [1 => 1, 3 => TRUE]
[0, 1, '', TRUE], NULL, [1 => 1, 3 => TRUE],
];
$data['1d-array-callable'] = [
[0, 1, '', TRUE],
@@ -18,6 +18,7 @@ use PHPUnit\Framework\TestCase;
* Tests marking strings as safe.
*
* @group Utility
* @group legacy
* @coversDefaultClass \Drupal\Component\Utility\SafeMarkup
*/
class SafeMarkupTest extends TestCase {
@@ -35,6 +36,7 @@ class SafeMarkupTest extends TestCase {
* Tests SafeMarkup::isSafe() with different objects.
*
* @covers ::isSafe
* @expectedDeprecation SafeMarkup::isSafe() is scheduled for removal in Drupal 9.0.0. Instead, you should just check if a variable is an instance of \Drupal\Component\Render\MarkupInterface. See https://www.drupal.org/node/2549395.
*/
public function testIsSafe() {
$safe_string = $this->getMockBuilder('\Drupal\Component\Render\MarkupInterface')->getMock();
@@ -48,6 +50,7 @@ class SafeMarkupTest extends TestCase {
*
* @dataProvider providerCheckPlain
* @covers ::checkPlain
* @expectedDeprecation SafeMarkup::checkPlain() is scheduled for removal in Drupal 9.0.0. Rely on Twig's auto-escaping feature, or use the @link theme_render #plain_text @endlink key when constructing a render array that contains plain text in order to use the renderer's auto-escaping feature. If neither of these are possible, \Drupal\Component\Utility\Html::escape() can be used in places where explicit escaping is needed. See https://www.drupal.org/node/2549395.
*
* @param string $text
* The text to provide to SafeMarkup::checkPlain().
@@ -107,6 +110,7 @@ class SafeMarkupTest extends TestCase {
*
* @dataProvider providerFormat
* @covers ::format
* @expectedDeprecation SafeMarkup::format() is scheduled for removal in Drupal 9.0.0. Use \Drupal\Component\Render\FormattableMarkup. See https://www.drupal.org/node/2549395.
*
* @param string $string
* The string to run through SafeMarkup::format().
@@ -125,10 +129,6 @@ class SafeMarkupTest extends TestCase {
$result = SafeMarkup::format($string, $args);
$this->assertEquals($expected, (string) $result, $message);
$this->assertEquals($expected_is_safe, $result instanceof MarkupInterface, 'SafeMarkup::format correctly sets the result as safe or not safe.');
foreach ($args as $arg) {
$this->assertSame($arg instanceof SafeMarkupTestMarkup, SafeMarkup::isSafe($arg));
}
}
/**
@@ -49,42 +49,42 @@ class SortArrayTest extends TestCase {
$tests[] = [
['weight' => 1],
['weight' => 1],
0
0,
];
// Weights set and $a is less (lighter) than $b.
$tests[] = [
['weight' => 1],
['weight' => 2],
-1
-1,
];
// Weights set and $a is greater (heavier) than $b.
$tests[] = [
['weight' => 2],
['weight' => 1],
1
1,
];
// Weights not set.
$tests[] = [
[],
[],
0
0,
];
// Weights for $b not set.
$tests[] = [
['weight' => 1],
[],
1
1,
];
// Weights for $a not set.
$tests[] = [
[],
['weight' => 1],
-1
-1,
];
return $tests;
@@ -125,42 +125,42 @@ class SortArrayTest extends TestCase {
$tests[] = [
['#weight' => 1],
['#weight' => 1],
0
0,
];
// Weights set and $a is less (lighter) than $b.
$tests[] = [
['#weight' => 1],
['#weight' => 2],
-1
-1,
];
// Weights set and $a is greater (heavier) than $b.
$tests[] = [
['#weight' => 2],
['#weight' => 1],
1
1,
];
// Weights not set.
$tests[] = [
[],
[],
0
0,
];
// Weights for $b not set.
$tests[] = [
['#weight' => 1],
[],
1
1,
];
// Weights for $a not set.
$tests[] = [
[],
['#weight' => 1],
-1
-1,
];
return $tests;
@@ -201,35 +201,35 @@ class SortArrayTest extends TestCase {
$tests[] = [
['title' => 'test'],
['title' => 'test'],
0
0,
];
// Title $a not set.
$tests[] = [
[],
['title' => 'test'],
-4
-4,
];
// Title $b not set.
$tests[] = [
['title' => 'test'],
[],
4
4,
];
// Titles set but not equal.
$tests[] = [
['title' => 'test'],
['title' => 'testing'],
-1
-1,
];
// Titles set but not equal.
$tests[] = [
['title' => 'testing'],
['title' => 'test'],
1
1,
];
return $tests;
@@ -270,35 +270,35 @@ class SortArrayTest extends TestCase {
$tests[] = [
['#title' => 'test'],
['#title' => 'test'],
0
0,
];
// Title $a not set.
$tests[] = [
[],
['#title' => 'test'],
-4
-4,
];
// Title $b not set.
$tests[] = [
['#title' => 'test'],
[],
4
4,
];
// Titles set but not equal.
$tests[] = [
['#title' => 'test'],
['#title' => 'testing'],
-1
-1,
];
// Titles set but not equal.
$tests[] = [
['#title' => 'testing'],
['#title' => 'test'],
1
1,
];
return $tests;
@@ -15,56 +15,11 @@ use PHPUnit\Framework\TestCase;
class UnicodeTest extends TestCase {
/**
* {@inheritdoc}
*
* @covers ::check
* @group legacy
* @expectedDeprecation \Drupal\Component\Utility\Unicode::setStatus() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. In Drupal 9 there will be no way to set the status and in Drupal 8 this ability has been removed because mb_*() functions are supplied using Symfony's polyfill. See https://www.drupal.org/node/2850048.
*/
protected function setUp() {
// Initialize unicode component.
Unicode::check();
}
/**
* Getting and settings the multibyte environment status.
*
* @dataProvider providerTestStatus
* @covers ::getStatus
* @covers ::setStatus
*/
public function testStatus($value, $expected, $invalid = FALSE) {
if ($invalid) {
if (method_exists($this, 'expectException')) {
$this->expectException('InvalidArgumentException');
}
else {
$this->setExpectedException('InvalidArgumentException');
}
}
Unicode::setStatus($value);
$this->assertEquals($expected, Unicode::getStatus());
}
/**
* Data provider for testStatus().
*
* @see testStatus()
*
* @return array
* An array containing:
* - The status value to set.
* - The status value to expect after setting the new value.
* - (optional) Boolean indicating invalid status. Defaults to FALSE.
*/
public function providerTestStatus() {
return [
[Unicode::STATUS_SINGLEBYTE, Unicode::STATUS_SINGLEBYTE],
[rand(10, 100), Unicode::STATUS_SINGLEBYTE, TRUE],
[rand(10, 100), Unicode::STATUS_SINGLEBYTE, TRUE],
[Unicode::STATUS_MULTIBYTE, Unicode::STATUS_MULTIBYTE],
[rand(10, 100), Unicode::STATUS_MULTIBYTE, TRUE],
[Unicode::STATUS_ERROR, Unicode::STATUS_ERROR],
[Unicode::STATUS_MULTIBYTE, Unicode::STATUS_MULTIBYTE],
];
public function testSetStatus() {
Unicode::setStatus(Unicode::STATUS_SINGLEBYTE);
}
/**
@@ -101,10 +56,10 @@ class UnicodeTest extends TestCase {
* @dataProvider providerStrtolower
* @covers ::strtolower
* @covers ::caseFlip
* @group legacy
* @expectedDeprecation \Drupal\Component\Utility\Unicode::strtolower() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtolower() instead. See https://www.drupal.org/node/2850048.
*/
public function testStrtolower($text, $expected, $multibyte = FALSE) {
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
Unicode::setStatus($status);
public function testStrtolower($text, $expected) {
$this->assertEquals($expected, Unicode::strtolower($text));
}
@@ -114,22 +69,14 @@ class UnicodeTest extends TestCase {
* @see testStrtolower()
*
* @return array
* An array containing a string, its lowercase version and whether it should
* be processed as multibyte.
* An array containing a string and its lowercase version.
*/
public function providerStrtolower() {
$cases = [
return [
['tHe QUIcK bRoWn', 'the quick brown'],
['FrançAIS is ÜBER-åwesome', 'français is über-åwesome'],
['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αβγδεζηθικλμνξοσὠ'],
];
foreach ($cases as $case) {
// Test the same string both in multibyte and singlebyte conditions.
array_push($case, TRUE);
$cases[] = $case;
}
// Add a multibyte string.
$cases[] = ['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αβγδεζηθικλμνξοσὠ', TRUE];
return $cases;
}
/**
@@ -138,10 +85,10 @@ class UnicodeTest extends TestCase {
* @dataProvider providerStrtoupper
* @covers ::strtoupper
* @covers ::caseFlip
* @group legacy
* @expectedDeprecation \Drupal\Component\Utility\Unicode::strtoupper() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strtoupper() instead. See https://www.drupal.org/node/2850048.
*/
public function testStrtoupper($text, $expected, $multibyte = FALSE) {
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
Unicode::setStatus($status);
public function testStrtoupper($text, $expected) {
$this->assertEquals($expected, Unicode::strtoupper($text));
}
@@ -151,22 +98,14 @@ class UnicodeTest extends TestCase {
* @see testStrtoupper()
*
* @return array
* An array containing a string, its uppercase version and whether it should
* be processed as multibyte.
* An array containing a string and its uppercase version.
*/
public function providerStrtoupper() {
$cases = [
return [
['tHe QUIcK bRoWn', 'THE QUICK BROWN'],
['FrançAIS is ÜBER-åwesome', 'FRANÇAIS IS ÜBER-ÅWESOME'],
['αβγδεζηθικλμνξοσὠ', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ'],
];
foreach ($cases as $case) {
// Test the same string both in multibyte and singlebyte conditions.
array_push($case, TRUE);
$cases[] = $case;
}
// Add a multibyte string.
$cases[] = ['αβγδεζηθικλμνξοσὠ', 'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', TRUE];
return $cases;
}
/**
@@ -204,9 +143,7 @@ class UnicodeTest extends TestCase {
* @dataProvider providerLcfirst
* @covers ::lcfirst
*/
public function testLcfirst($text, $expected, $multibyte = FALSE) {
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
Unicode::setStatus($status);
public function testLcfirst($text, $expected) {
$this->assertEquals($expected, Unicode::lcfirst($text));
}
@@ -216,8 +153,7 @@ class UnicodeTest extends TestCase {
* @see testLcfirst()
*
* @return array
* An array containing a string, its lowercase version and whether it should
* be processed as multibyte.
* An array containing a string and its lowercase version.
*/
public function providerLcfirst() {
return [
@@ -226,7 +162,7 @@ class UnicodeTest extends TestCase {
['Über', 'über'],
['Åwesome', 'åwesome'],
// Add a multibyte string.
['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', TRUE],
['ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ', 'αΒΓΔΕΖΗΘΙΚΛΜΝΞΟΣὨ'],
];
}
@@ -236,9 +172,7 @@ class UnicodeTest extends TestCase {
* @dataProvider providerUcwords
* @covers ::ucwords
*/
public function testUcwords($text, $expected, $multibyte = FALSE) {
$status = $multibyte ? Unicode::STATUS_MULTIBYTE : Unicode::STATUS_SINGLEBYTE;
Unicode::setStatus($status);
public function testUcwords($text, $expected) {
$this->assertEquals($expected, Unicode::ucwords($text));
}
@@ -248,8 +182,7 @@ class UnicodeTest extends TestCase {
* @see testUcwords()
*
* @return array
* An array containing a string, its capitalized version and whether it should
* be processed as multibyte.
* An array containing a string and its capitalized version.
*/
public function providerUcwords() {
return [
@@ -260,7 +193,7 @@ class UnicodeTest extends TestCase {
// Make sure we don't mangle extra spaces.
['frànçAIS is über-åwesome', 'FrànçAIS Is Über-Åwesome'],
// Add a multibyte string.
['σion', 'Σion', TRUE],
['σion', 'Σion'],
];
}
@@ -269,13 +202,10 @@ class UnicodeTest extends TestCase {
*
* @dataProvider providerStrlen
* @covers ::strlen
* @group legacy
* @expectedDeprecation \Drupal\Component\Utility\Unicode::strlen() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strlen() instead. See https://www.drupal.org/node/2850048.
*/
public function testStrlen($text, $expected) {
// Run through multibyte code path.
Unicode::setStatus(Unicode::STATUS_MULTIBYTE);
$this->assertEquals($expected, Unicode::strlen($text));
// Run through singlebyte code path.
Unicode::setStatus(Unicode::STATUS_SINGLEBYTE);
$this->assertEquals($expected, Unicode::strlen($text));
}
@@ -300,13 +230,10 @@ class UnicodeTest extends TestCase {
*
* @dataProvider providerSubstr
* @covers ::substr
* @group legacy
* @expectedDeprecation \Drupal\Component\Utility\Unicode::substr() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_substr() instead. See https://www.drupal.org/node/2850048.
*/
public function testSubstr($text, $start, $length, $expected) {
// Run through multibyte code path.
Unicode::setStatus(Unicode::STATUS_MULTIBYTE);
$this->assertEquals($expected, Unicode::substr($text, $start, $length));
// Run through singlebyte code path.
Unicode::setStatus(Unicode::STATUS_SINGLEBYTE);
$this->assertEquals($expected, Unicode::substr($text, $start, $length));
}
@@ -553,13 +480,10 @@ EOF;
*
* @dataProvider providerStrpos
* @covers ::strpos
* @group legacy
* @expectedDeprecation \Drupal\Component\Utility\Unicode::strpos() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Use mb_strpos() instead. See https://www.drupal.org/node/2850048.
*/
public function testStrpos($haystack, $needle, $offset, $expected) {
// Run through multibyte code path.
Unicode::setStatus(Unicode::STATUS_MULTIBYTE);
$this->assertEquals($expected, Unicode::strpos($haystack, $needle, $offset));
// Run through singlebyte code path.
Unicode::setStatus(Unicode::STATUS_SINGLEBYTE);
$this->assertEquals($expected, Unicode::strpos($haystack, $needle, $offset));
}
@@ -503,31 +503,31 @@ class XssTest extends TestCase {
'<img src="http://example.com/foo.jpg" title="Example: title" alt="Example: alt">',
'<img src="http://example.com/foo.jpg" title="Example: title" alt="Example: alt">',
'Image tag with alt and title attribute',
['img']
['img'],
],
[
'<a href="https://www.drupal.org/" rel="dc:publisher">Drupal</a>',
'<a href="https://www.drupal.org/" rel="dc:publisher">Drupal</a>',
'Link tag with rel attribute',
['a']
['a'],
],
[
'<span property="dc:subject">Drupal 8: The best release ever.</span>',
'<span property="dc:subject">Drupal 8: The best release ever.</span>',
'Span tag with property attribute',
['span']
['span'],
],
[
'<img src="http://example.com/foo.jpg" data-caption="Drupal 8: The best release ever.">',
'<img src="http://example.com/foo.jpg" data-caption="Drupal 8: The best release ever.">',
'Image tag with data attribute',
['img']
['img'],
],
[
'<a data-a2a-url="foo"></a>',
'<a data-a2a-url="foo"></a>',
'Link tag with numeric data attribute',
['a']
['a'],
],
];
}
@@ -567,6 +567,7 @@ class AccessManagerTest extends UnitTestCase {
* Defines an interface with a defined access() method for mocking.
*/
interface TestAccessCheckInterface extends AccessCheckInterface {
public function access();
}
@@ -269,8 +269,12 @@ class AccessResultTest extends UnitTestCase {
*/
public function testOrIf() {
$neutral = AccessResult::neutral('neutral message');
$neutral_other = AccessResult::neutral('other neutral message');
$neutral_reasonless = AccessResult::neutral();
$allowed = AccessResult::allowed();
$forbidden = AccessResult::forbidden('forbidden message');
$forbidden_other = AccessResult::forbidden('other forbidden message');
$forbidden_reasonless = AccessResult::forbidden();
$unused_access_result_due_to_lazy_evaluation = $this->getMock('\Drupal\Core\Access\AccessResultInterface');
$unused_access_result_due_to_lazy_evaluation->expects($this->never())
->method($this->anything());
@@ -304,6 +308,18 @@ class AccessResultTest extends UnitTestCase {
$this->assertTrue($access->isNeutral());
$this->assertEquals('neutral message', $access->getReason());
$this->assertDefaultCacheability($access);
// Reason inheritance edge case: first reason is kept.
$access = $neutral->orIf($neutral_other);
$this->assertEquals('neutral message', $access->getReason());
$access = $neutral_other->orIf($neutral);
$this->assertEquals('other neutral message', $access->getReason());
// Reason inheritance edge case: one of the operands is reasonless.
$access = $neutral->orIf($neutral_reasonless);
$this->assertEquals('neutral message', $access->getReason());
$access = $neutral_reasonless->orIf($neutral);
$this->assertEquals('neutral message', $access->getReason());
$access = $neutral_reasonless->orIf($neutral_reasonless);
$this->assertNull($access->getReason());
// NEUTRAL || ALLOWED === ALLOWED.
$access = $neutral->orIf($allowed);
@@ -329,7 +345,7 @@ class AccessResultTest extends UnitTestCase {
$this->assertDefaultCacheability($access);
// FORBIDDEN || NEUTRAL === FORBIDDEN.
$access = $forbidden->orIf($allowed);
$access = $forbidden->orIf($neutral);
$this->assertFalse($access->isAllowed());
$this->assertTrue($access->isForbidden());
$this->assertFalse($access->isNeutral());
@@ -337,12 +353,24 @@ class AccessResultTest extends UnitTestCase {
$this->assertDefaultCacheability($access);
// FORBIDDEN || FORBIDDEN === FORBIDDEN.
$access = $forbidden->orIf($allowed);
$access = $forbidden->orIf($forbidden);
$this->assertFalse($access->isAllowed());
$this->assertTrue($access->isForbidden());
$this->assertFalse($access->isNeutral());
$this->assertEquals('forbidden message', $access->getReason());
$this->assertDefaultCacheability($access);
// Reason inheritance edge case: first reason is kept.
$access = $forbidden->orIf($forbidden_other);
$this->assertEquals('forbidden message', $access->getReason());
$access = $forbidden_other->orIf($forbidden);
$this->assertEquals('other forbidden message', $access->getReason());
// Reason inheritance edge case: one of the operands is reasonless.
$access = $forbidden->orIf($forbidden_reasonless);
$this->assertEquals('forbidden message', $access->getReason());
$access = $forbidden_reasonless->orIf($forbidden);
$this->assertEquals('forbidden message', $access->getReason());
$access = $forbidden_reasonless->orIf($forbidden_reasonless);
$this->assertNull($access->getReason());
// FORBIDDEN || * === FORBIDDEN.
$access = $forbidden->orIf($unused_access_result_due_to_lazy_evaluation);
@@ -957,6 +985,7 @@ class UncacheableTestAccessResult implements AccessResultInterface {
public function __construct($value) {
$this->value = $value;
}
/**
* {@inheritdoc}
*/
@@ -9,8 +9,13 @@ namespace Drupal\Tests\Core\Access;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\CustomAccessCheck;
use Drupal\Core\Controller\ControllerResolver;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\Routing\Route;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
/**
* @coversDefaultClass \Drupal\Core\Access\CustomAccessCheck
@@ -106,6 +111,34 @@ class CustomAccessCheckTest extends UnitTestCase {
$this->assertEquals(AccessResult::allowed(), $this->accessChecker->access($route, $route_match, $account));
}
/**
* Tests the access method exception for invalid access callbacks.
*/
public function testAccessException() {
// Create two mocks for the ControllerResolver constructor.
$httpMessageFactory = $this->getMockBuilder(HttpMessageFactoryInterface::class)->getMock();
$controllerResolver = $this->getMockBuilder(ClassResolverInterface::class)->getMock();
// Re-create the controllerResolver mock with proxy to original methods.
$this->controllerResolver = $this->getMockBuilder(ControllerResolver::class)
->setConstructorArgs([$httpMessageFactory, $controllerResolver])
->enableProxyingToOriginalMethods()
->getMock();
// Overwrite the access checker using the newly mocked controller resolve.
$this->accessChecker = new CustomAccessCheck($this->controllerResolver, $this->argumentsResolverFactory);
// Add a route with a _custom_access route that doesn't exist.
$route = new Route('/test-route', [], ['_custom_access' => '\Drupal\Tests\Core\Access\NonExistentController::nonExistentMethod']);
$route_match = $this->getMock(RouteMatchInterface::class);
$account = $this->getMock(AccountInterface::class);
$this->setExpectedException(\BadMethodCallException::class, 'The "\Drupal\Tests\Core\Access\NonExistentController::nonExistentMethod" method is not callable as a _custom_access callback in route "/test-route"');
// Run the access check.
$this->accessChecker->access($route, $route_match, $account);
}
}
class TestController {
@@ -13,9 +13,11 @@ class OpenOffCanvasDialogCommandTest extends UnitTestCase {
/**
* @covers ::render
*
* @dataProvider dialogPosition
*/
public function testRender() {
$command = new OpenOffCanvasDialogCommand('Title', '<p>Text!</p>', ['url' => 'example']);
public function testRender($position) {
$command = new OpenOffCanvasDialogCommand('Title', '<p>Text!</p>', ['url' => 'example'], NULL, $position);
$expected = [
'command' => 'openDialog',
@@ -31,8 +33,9 @@ class OpenOffCanvasDialogCommandTest extends UnitTestCase {
'draggable' => FALSE,
'drupalAutoButtons' => FALSE,
'buttons' => [],
'dialogClass' => 'ui-dialog-off-canvas',
'dialogClass' => 'ui-dialog-off-canvas ui-dialog-position-' . $position,
'width' => 300,
'drupalOffCanvasPosition' => $position,
],
'effect' => 'fade',
'speed' => 1000,
@@ -40,4 +43,16 @@ class OpenOffCanvasDialogCommandTest extends UnitTestCase {
$this->assertEquals($expected, $command->render());
}
/**
* The data provider for potential dialog positions.
*
* @return array
*/
public static function dialogPosition() {
return [
['side'],
['top'],
];
}
}
@@ -55,7 +55,7 @@ class TranslationTest extends UnitTestCase {
[
'value' => 'Foo',
],
'Foo'
'Foo',
];
$random = $this->randomMachineName();
$random_html_entity = '&' . $random;
@@ -167,6 +167,7 @@ class AssertLegacyTraitTest extends UnitTestCase {
/**
* @covers ::assertNoCacheTag
* @expectedDeprecation assertNoCacheTag() is deprecated and scheduled for removal in Drupal 9.0.0. Use $this->assertSession()->responseHeaderNotContains() instead. See https://www.drupal.org/node/2864029.
*/
public function testAssertNoCacheTag() {
$this->webAssert
@@ -114,6 +114,12 @@ class AssetResolverTest extends UnitTestCase {
/**
* @covers ::getCssAssets
* @dataProvider providerAttachedAssets
* @group legacy
*
* Note the legacy group is used here because
* ActiveTheme::getStyleSheetsRemove() is called and is deprecated. As this
* code path will still be triggered until Drupal 9 we have to add the group.
* We do not trigger a silenced deprecation.
*/
public function testGetCssAssets(AttachedAssetsInterface $assets_a, AttachedAssetsInterface $assets_b, $expected_cache_item_count) {
$this->assetResolver->getCssAssets($assets_a, FALSE);
@@ -141,12 +147,12 @@ class AssetResolverTest extends UnitTestCase {
'same libraries, different timestamps' => [
(new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal'])->setSettings(['currentTime' => $time]),
(new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal'])->setSettings(['currentTime' => $time + 100]),
1
1,
],
'different libraries, same timestamps' => [
(new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal'])->setSettings(['currenttime' => $time]),
(new AttachedAssets())->setAlreadyLoadedLibraries([])->setLibraries(['core/drupal', 'core/jquery'])->setSettings(['currentTime' => $time]),
2
2,
],
];
}
@@ -162,6 +168,7 @@ if (!defined('JS_DEFAULT')) {
}
class TestMemoryBackend extends MemoryBackend {
public function getAllCids() {
return array_keys($this->cache);
}
@@ -15,7 +15,7 @@ class CssCollectionGrouperUnitTest extends UnitTestCase {
/**
* A CSS asset grouper.
*
* @var \Drupal\Core\Asset\CssCollectionGrouper object.
* @var \Drupal\Core\Asset\CssCollectionGrouper
*/
protected $grouper;
@@ -15,7 +15,7 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
/**
* A CSS asset renderer.
*
* @var \Drupal\Core\Asset\CssRenderer object.
* @var \Drupal\Core\Asset\CssCollectionRenderer
*/
protected $renderer;
@@ -94,7 +94,7 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
'#tag' => 'style',
'#value' => $value,
'#attributes' => [
'media' => $media
'media' => $media,
],
'#browsers' => $browsers,
];
@@ -461,7 +461,7 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
'media' => 'all',
'preprocess' => TRUE,
'browsers' => [],
'data' => 'http://example.com/popular.js'
'data' => 'http://example.com/popular.js',
];
$this->renderer->render($css_group);
}
@@ -473,9 +473,11 @@ class CssCollectionRendererUnitTest extends UnitTestCase {
* Component/Utility.
*/
if (!function_exists('Drupal\Tests\Core\Asset\file_create_url')) {
function file_create_url($uri) {
return 'file_create_url:' . $uri;
}
}
/**
@@ -483,9 +485,11 @@ if (!function_exists('Drupal\Tests\Core\Asset\file_create_url')) {
* Component/Utility.
*/
if (!function_exists('Drupal\Tests\Core\Asset\file_url_transform_relative')) {
function file_url_transform_relative($uri) {
return 'file_url_transform_relative:' . $uri;
}
}
/**
@@ -20,7 +20,7 @@ class CssOptimizerUnitTest extends UnitTestCase {
/**
* A CSS asset optimizer.
*
* @var \Drupal\Core\Asset\CssOptimizer object.
* @var \Drupal\Core\Asset\CssOptimizer
*/
protected $optimizer;
@@ -269,9 +269,11 @@ class CssOptimizerUnitTest extends UnitTestCase {
* Component/Utility.
*/
if (!function_exists('Drupal\Tests\Core\Asset\file_create_url')) {
function file_create_url($uri) {
return 'file_create_url:' . $uri;
}
}
/**
@@ -279,9 +281,11 @@ if (!function_exists('Drupal\Tests\Core\Asset\file_create_url')) {
* Component/Utility.
*/
if (!function_exists('Drupal\Tests\Core\Asset\file_url_transform_relative')) {
function file_url_transform_relative($uri) {
return 'file_url_transform_relative:' . $uri;
}
}
/**
@@ -15,7 +15,7 @@ class JsOptimizerUnitTest extends UnitTestCase {
/**
* A JS asset optimizer.
*
* @var \Drupal\Core\Asset\JsOptimizer object.
* @var \Drupal\Core\Asset\JsOptimizer
*/
protected $optimizer;
@@ -64,7 +64,6 @@ class LibraryDependencyResolverTest extends UnitTestCase {
$this->libraryDependencyResolver = new LibraryDependencyResolver($this->libraryDiscovery);
}
/**
* Provides test data for ::testGetLibrariesWithDependencies().
*/
@@ -169,4 +168,12 @@ class LibraryDependencyResolverTest extends UnitTestCase {
$this->assertEquals($expected, $this->libraryDependencyResolver->getMinimalRepresentativeSubset($libraries));
}
/**
* @covers ::getMinimalRepresentativeSubset
*/
public function testGetMinimalRepresentativeSubsetInvalidInput() {
$this->setExpectedException(\AssertionError::class, '$libraries can\'t contain duplicate items.');
$this->libraryDependencyResolver->getMinimalRepresentativeSubset(['test/no_deps_a', 'test/no_deps_a']);
}
}
@@ -211,7 +211,6 @@ class LibraryDiscoveryParserTest extends UnitTestCase {
$this->assertEquals(\Drupal::VERSION, $libraries['core-versioned']['js'][0]['version']);
}
/**
* Tests that the version property of external libraries is handled.
*
@@ -399,6 +398,7 @@ class LibraryDiscoveryParserTest extends UnitTestCase {
$this->assertEquals(FALSE, $library['js'][0]['minified']);
$this->assertEquals(TRUE, $library['js'][1]['minified']);
}
/**
* Tests that an exception is thrown when license is missing when 3rd party.
*
@@ -0,0 +1,254 @@
<?php
namespace Drupal\Tests\Core\Batch;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Tests\UnitTestCase;
/**
* Tests for the batch builder class.
*
* @coversDefaultClass \Drupal\Core\Batch\BatchBuilder
*
* @group system
*/
class BatchBuilderTest extends UnitTestCase {
/**
* Tests the default values.
*
* @covers ::toArray
*/
public function testDefaultValues() {
$batch = (new BatchBuilder())->toArray();
$this->assertInternalType('array', $batch);
$this->assertArrayHasKey('operations', $batch);
$this->assertInternalType('array', $batch['operations']);
$this->assertEmpty($batch['operations'], 'Operations array is empty.');
$this->assertEquals(new TranslatableMarkup('Processing'), $batch['title']);
$this->assertEquals(new TranslatableMarkup('Initializing.'), $batch['init_message']);
$this->assertEquals(new TranslatableMarkup('Completed @current of @total.'), $batch['progress_message']);
$this->assertEquals(new TranslatableMarkup('An error has occurred.'), $batch['error_message']);
$this->assertNull($batch['finished']);
$this->assertNull($batch['file']);
$this->assertArrayHasKey('library', $batch);
$this->assertInternalType('array', $batch['library']);
$this->assertEmpty($batch['library']);
$this->assertArrayHasKey('url_options', $batch);
$this->assertInternalType('array', $batch['url_options']);
$this->assertEmpty($batch['url_options']);
$this->assertArrayHasKey('progressive', $batch);
$this->assertTrue($batch['progressive']);
$this->assertArrayNotHasKey('queue', $batch);
}
/**
* Tests setTitle().
*
* @covers ::setTitle
*/
public function testSetTitle() {
$batch = (new BatchBuilder())
->setTitle(new TranslatableMarkup('New Title'))
->toArray();
$this->assertEquals(new TranslatableMarkup('New Title'), $batch['title']);
}
/**
* Tests setFinishCallback().
*
* @covers ::setFinishCallback
*/
public function testSetFinishCallback() {
$batch = (new BatchBuilder())
->setFinishCallback('\Drupal\Tests\Core\Batch\BatchBuilderTest::finishedCallback')
->toArray();
$this->assertEquals('\Drupal\Tests\Core\Batch\BatchBuilderTest::finishedCallback', $batch['finished']);
}
/**
* Tests setInitMessage().
*
* @covers ::setInitMessage
*/
public function testSetInitMessage() {
$batch = (new BatchBuilder())
->setInitMessage(new TranslatableMarkup('New initialization message.'))
->toArray();
$this->assertEquals(new TranslatableMarkup('New initialization message.'), $batch['init_message']);
}
/**
* Tests setProgressMessage().
*
* @covers ::setProgressMessage
*/
public function testSetProgressMessage() {
$batch = (new BatchBuilder())
->setProgressMessage(new TranslatableMarkup('Batch in progress...'))
->toArray();
$this->assertEquals(new TranslatableMarkup('Batch in progress...'), $batch['progress_message']);
}
/**
* Tests setErrorMessage().
*/
public function testSetErrorMessage() {
$batch = (new BatchBuilder())
->setErrorMessage(new TranslatableMarkup('Oops. An error has occurred :('))
->toArray();
$this->assertEquals(new TranslatableMarkup('Oops. An error has occurred :('), $batch['error_message']);
}
/**
* Tests setFile().
*
* @covers ::setFile
*/
public function testSetFile() {
$batch = (new BatchBuilder())
->setFile('filename.php')
->toArray();
$this->assertEquals('filename.php', $batch['file']);
}
/**
* Tests setting and adding libraries.
*
* @covers ::setLibraries
*/
public function testAddingLibraries() {
$batch = (new BatchBuilder())
->setLibraries(['only/library'])
->toArray();
$this->assertEquals(['only/library'], $batch['library']);
}
/**
* Tests setProgressive().
*
* @covers ::setProgressive
*/
public function testSetProgressive() {
$batch_builder = new BatchBuilder();
$batch = $batch_builder
->setProgressive(FALSE)
->toArray();
$this->assertFalse($batch['progressive']);
$batch = $batch_builder
->setProgressive(TRUE)
->toArray();
$this->assertTrue($batch['progressive']);
}
/**
* Tests setQueue().
*
* @covers ::setQueue
*/
public function testSetQueue() {
$batch = (new BatchBuilder())
->setQueue('BatchName', '\Drupal\Core\Queue\Batch')
->toArray();
$this->assertArrayEquals([
'name' => 'BatchName',
'class' => '\Drupal\Core\Queue\Batch',
], $batch['queue'], 'Batch queue has been set.');
}
/**
* Tests queue class exists.
*
* @covers ::setQueue
*/
public function testQueueExists() {
$batch_builder = (new BatchBuilder());
$this->setExpectedException(\InvalidArgumentException::class, 'Class \ThisIsNotAClass does not exist.');
$batch_builder->setQueue('BatchName', '\ThisIsNotAClass');
}
/**
* Tests queue class implements \Drupal\Core\Queue\QueueInterface.
*
* @covers ::setQueue
*/
public function testQueueImplements() {
$batch_builder = (new BatchBuilder());
$this->setExpectedException(\InvalidArgumentException::class, 'Class Exception does not implement \Drupal\Core\Queue\QueueInterface.');
$batch_builder->setQueue('BatchName', \Exception::class);
}
/**
* Tests setUrlOptions().
*
* @covers ::setUrlOptions
*/
public function testSetUrlOptions() {
$options = [
'absolute' => TRUE,
'language' => 'de',
];
$batch = (new BatchBuilder())
->setUrlOptions($options)
->toArray();
$this->assertEquals($options, $batch['url_options']);
}
/**
* Tests addOperation().
*
* @covers ::addOperation
*/
public function testAddOperation() {
$batch_builder = new BatchBuilder();
$batch = $batch_builder
->addOperation('\Drupal\Tests\Core\Batch\BatchBuilderTest::operationCallback')
->toArray();
$this->assertEquals([
['\Drupal\Tests\Core\Batch\BatchBuilderTest::operationCallback', []],
], $batch['operations']);
$batch = $batch_builder
->addOperation('\Drupal\Tests\Core\Batch\BatchBuilderTest::operationCallback', [2])
->addOperation('\Drupal\Tests\Core\Batch\BatchBuilderTest::operationCallback', [3])
->toArray();
$this->assertEquals([
['\Drupal\Tests\Core\Batch\BatchBuilderTest::operationCallback', []],
['\Drupal\Tests\Core\Batch\BatchBuilderTest::operationCallback', [2]],
['\Drupal\Tests\Core\Batch\BatchBuilderTest::operationCallback', [3]],
], $batch['operations']);
}
/**
* Empty callback for the tests.
*
* @internal
*/
public static function finishedCallback() {
}
/**
* Empty callback for the tests.
*
* @internal
*/
public static function operationCallback() {
}
}
@@ -23,6 +23,7 @@ class PercentagesTest extends UnitTestCase {
$actual_result = Percentage::format($total, $current);
$this->assertEquals($actual_result, $expected_result, sprintf('The expected the batch api percentage at the state %s/%s is %s%% and got %s%%.', $current, $total, $expected_result, $actual_result));
}
/**
* Provide data for batch unit tests.
*
@@ -4,9 +4,11 @@ namespace Drupal\Tests\Core\Block;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Core\Block\BlockManager;
use Drupal\Core\Block\Plugin\Block\Broken;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Tests\UnitTestCase;
use Psr\Log\LoggerInterface;
/**
* @coversDefaultClass \Drupal\Core\Block\BlockManager
@@ -22,6 +24,13 @@ class BlockManagerTest extends UnitTestCase {
*/
protected $blockManager;
/**
* The logger.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* {@inheritdoc}
*/
@@ -30,7 +39,8 @@ class BlockManagerTest extends UnitTestCase {
$cache_backend = $this->prophesize(CacheBackendInterface::class);
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
$this->blockManager = new BlockManager(new \ArrayObject(), $cache_backend->reveal(), $module_handler->reveal());
$this->logger = $this->prophesize(LoggerInterface::class);
$this->blockManager = new BlockManager(new \ArrayObject(), $cache_backend->reveal(), $module_handler->reveal(), $this->logger->reveal());
$this->blockManager->setStringTranslation($this->getStringTranslationStub());
$discovery = $this->prophesize(DiscoveryInterface::class);
@@ -40,6 +50,8 @@ class BlockManagerTest extends UnitTestCase {
'broken' => [
'admin_label' => 'Broken/Missing',
'category' => 'Block',
'class' => Broken::class,
'provider' => 'core',
],
'block1' => [
'admin_label' => 'Coconut',
@@ -86,4 +98,13 @@ class BlockManagerTest extends UnitTestCase {
$this->assertSame(['block3', 'block1'], array_keys($definitions['Group 2']));
}
/**
* @covers ::handlePluginNotFound
*/
public function testHandlePluginNotFound() {
$this->logger->warning('The "%plugin_id" was not found', ['%plugin_id' => 'invalid'])->shouldBeCalled();
$plugin = $this->blockManager->createInstance('invalid');
$this->assertSame('broken', $plugin->getPluginId());
}
}
@@ -59,7 +59,6 @@ class CacheCollectorTest extends UnitTestCase {
$this->getContainerWithCacheTagsInvalidator($this->cacheTagsInvalidator);
}
/**
* Tests the resolve cache miss function.
*/
@@ -85,7 +84,6 @@ class CacheCollectorTest extends UnitTestCase {
$this->assertEquals($value, $this->collector->get($key));
}
/**
* Makes sure that NULL is a valid value and is collected.
*/
@@ -192,7 +190,6 @@ class CacheCollectorTest extends UnitTestCase {
$this->collector->destruct();
}
/**
* Tests updating the cache when the lock acquire fails.
*/
@@ -53,7 +53,6 @@ class CacheTest extends UnitTestCase {
$this->assertNull(Cache::validateTags($tags));
}
/**
* Provides a list of pairs of cache tags arrays to be merged.
*
@@ -102,7 +101,6 @@ class CacheTest extends UnitTestCase {
];
}
/**
* @covers ::mergeMaxAges
*
@@ -128,7 +128,7 @@ class CacheableMetadataTest extends UnitTestCase {
[new \stdClass(), TRUE],
[300, FALSE],
[[], TRUE],
[8.0, TRUE]
[8.0, TRUE],
];
}
@@ -0,0 +1,256 @@
<?php
namespace Drupal\Tests\Core\Command;
use Drupal\Core\Test\TestDatabase;
use Drupal\Tests\BrowserTestBase;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
/**
* Tests the quick-start commands.
*
* These tests are run in a separate process because they load Drupal code via
* an include.
*
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
*
* @group Command
*/
class QuickStartTest extends TestCase {
/**
* The PHP executable path.
*
* @var string
*/
protected $php;
/**
* A test database object.
*
* @var \Drupal\Core\Test\TestDatabase
*/
protected $testDb;
/**
* The Drupal root directory.
*
* @var string
*/
protected $root;
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$php_executable_finder = new PhpExecutableFinder();
$this->php = $php_executable_finder->find();
$this->root = dirname(dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__))));
chdir($this->root);
if (!is_writable("{$this->root}/sites/simpletest")) {
$this->markTestSkipped('This test requires a writable sites/simpletest directory');
}
// Get a lock and a valid site path.
$this->testDb = new TestDatabase();
}
/**
* {@inheritdoc}
*/
public function tearDown() {
if ($this->testDb) {
$test_site_directory = $this->root . DIRECTORY_SEPARATOR . $this->testDb->getTestSitePath();
if (file_exists($test_site_directory)) {
// @todo use the tear down command from
// https://www.drupal.org/project/drupal/issues/2926633
// Delete test site directory.
$this->fileUnmanagedDeleteRecursive($test_site_directory, [
BrowserTestBase::class,
'filePreDeleteCallback',
]);
}
}
parent::tearDown();
}
/**
* Tests the quick-start command.
*/
public function testQuickStartCommand() {
// Install a site using the standard profile to ensure the one time login
// link generation works.
$install_command = "{$this->php} core/scripts/drupal quick-start standard --site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login";
$process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$process->inheritEnvironmentVariables();
$process->setTimeout(500);
$process->start();
$guzzle = new Client();
$port = FALSE;
while ($process->isRunning()) {
if (preg_match('/127.0.0.1:(\d+)/', $process->getOutput(), $match)) {
$port = $match[1];
break;
}
// Wait for more output.
sleep(1);
}
// The progress bar uses STDERR to write messages.
$this->assertContains('Congratulations, you installed Drupal!', $process->getErrorOutput());
$this->assertNotFalse($port, "Web server running on port $port");
// Give the server a couple of seconds to be ready.
sleep(2);
$this->assertContains("127.0.0.1:$port/user/reset/1/", $process->getOutput());
// Generate a cookie so we can make a request against the installed site.
include $this->root . '/core/includes/bootstrap.inc';
define('DRUPAL_TEST_IN_CHILD_SITE', FALSE);
chmod($this->testDb->getTestSitePath(), 0755);
$cookieJar = CookieJar::fromArray([
'SIMPLETEST_USER_AGENT' => drupal_generate_test_ua($this->testDb->getDatabasePrefix()),
], '127.0.0.1');
$response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
$content = (string) $response->getBody();
$this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
// Stop the web server.
$process->stop();
}
/**
* Tests the quick-start commands.
*/
public function testQuickStartInstallAndServerCommands() {
// Install a site.
$install_command = "{$this->php} core/scripts/drupal install testing --site-name='Test site {$this->testDb->getDatabasePrefix()}'";
$install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$install_process->inheritEnvironmentVariables();
$install_process->setTimeout(500);
$result = $install_process->run();
// The progress bar uses STDERR to write messages.
$this->assertContains('Congratulations, you installed Drupal!', $install_process->getErrorOutput());
$this->assertSame(0, $result);
// Run the PHP built-in webserver.
$server_command = "{$this->php} core/scripts/drupal server --suppress-login";
$server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$server_process->inheritEnvironmentVariables();
$server_process->start();
$guzzle = new Client();
$port = FALSE;
while ($server_process->isRunning()) {
if (preg_match('/127.0.0.1:(\d+)/', $server_process->getOutput(), $match)) {
$port = $match[1];
break;
}
// Wait for more output.
sleep(1);
}
$this->assertEquals('', $server_process->getErrorOutput());
$this->assertContains("127.0.0.1:$port/user/reset/1/", $server_process->getOutput());
$this->assertNotFalse($port, "Web server running on port $port");
// Give the server a couple of seconds to be ready.
sleep(2);
// Generate a cookie so we can make a request against the installed site.
include $this->root . '/core/includes/bootstrap.inc';
define('DRUPAL_TEST_IN_CHILD_SITE', FALSE);
chmod($this->testDb->getTestSitePath(), 0755);
$cookieJar = CookieJar::fromArray([
'SIMPLETEST_USER_AGENT' => drupal_generate_test_ua($this->testDb->getDatabasePrefix()),
], '127.0.0.1');
$response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
$content = (string) $response->getBody();
$this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
// Try to re-install over the top of an existing site.
$install_command = "{$this->php} core/scripts/drupal install testing --site-name='Test another site {$this->testDb->getDatabasePrefix()}'";
$install_process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$install_process->inheritEnvironmentVariables();
$install_process->setTimeout(500);
$result = $install_process->run();
$this->assertContains('Drupal is already installed.', $install_process->getOutput());
$this->assertSame(0, $result);
// Ensure the site name has not changed.
$response = $guzzle->get('http://127.0.0.1:' . $port, ['cookies' => $cookieJar]);
$content = (string) $response->getBody();
$this->assertContains('Test site ' . $this->testDb->getDatabasePrefix(), $content);
// Stop the web server.
$server_process->stop();
}
/**
* Tests the install command with an invalid profile.
*/
public function testQuickStartCommandProfileValidation() {
// Install a site using the standard profile to ensure the one time login
// link generation works.
$install_command = "{$this->php} core/scripts/drupal quick-start umami --site-name='Test site {$this->testDb->getDatabasePrefix()}' --suppress-login";
$process = new Process($install_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$process->inheritEnvironmentVariables();
$process->run();
$this->assertContains('\'umami\' is not a valid install profile. Did you mean \'demo_umami\'?', $process->getErrorOutput());
}
/**
* Tests the server command when there is no installation.
*/
public function testServerWithNoInstall() {
$server_command = "{$this->php} core/scripts/drupal server --suppress-login";
$server_process = new Process($server_command, NULL, ['DRUPAL_DEV_SITE_PATH' => $this->testDb->getTestSitePath()]);
$server_process->inheritEnvironmentVariables();
$server_process->run();
$this->assertContains('No installation found. Use the \'install\' command.', $server_process->getErrorOutput());
}
/**
* Deletes all files and directories in the specified path recursively.
*
* Note this method has no dependencies on Drupal core to ensure that the
* test site can be torn down even if something in the test site is broken.
*
* @param string $path
* A string containing either an URI or a file or directory path.
* @param callable $callback
* (optional) Callback function to run on each file prior to deleting it and
* on each directory prior to traversing it. For example, can be used to
* modify permissions.
*
* @return bool
* TRUE for success or if path does not exist, FALSE in the event of an
* error.
*
* @see file_unmanaged_delete_recursive()
*/
protected function fileUnmanagedDeleteRecursive($path, $callback = NULL) {
if (isset($callback)) {
call_user_func($callback, $path);
}
if (is_dir($path)) {
$dir = dir($path);
while (($entry = $dir->read()) !== FALSE) {
if ($entry == '.' || $entry == '..') {
continue;
}
$entry_path = $path . '/' . $entry;
$this->fileUnmanagedDeleteRecursive($entry_path, $callback);
}
$dir->close();
return rmdir($path);
}
return unlink($path);
}
}
@@ -38,7 +38,7 @@ class AttributesTest extends UnitTestCase {
'alt' => 'Alternate',
],
' id="id-test" class="first last" alt="Alternate"',
'Multiple attributes.'
'Multiple attributes.',
],
// Verify empty attributes array is rendered.
[[], '', 'Empty attributes array.'],
@@ -283,13 +283,13 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
'config_dependencies' => [
'config' => [$instance_dependency_1],
'module' => [$instance_dependency_2],
]
],
],
[
'config' => [$instance_dependency_1],
'module' => [$instance_dependency_2, 'test']
]
]
'module' => [$instance_dependency_2, 'test'],
],
],
];
}
@@ -552,32 +552,6 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
$this->assertEquals(['configId' => $entity->id(), 'dependencies' => []], $properties);
}
/**
* @covers ::toArray
*/
public function testToArraySchemaFallback() {
$this->typedConfigManager->expects($this->once())
->method('getDefinition')
->will($this->returnValue(['mapping' => ['id' => '', 'dependencies' => '']]));
$this->entityType->expects($this->any())
->method('getPropertiesToExport')
->willReturn([]);
$properties = $this->entity->toArray();
$this->assertInternalType('array', $properties);
$this->assertEquals(['id' => $this->entity->id(), 'dependencies' => []], $properties);
}
/**
* @covers ::toArray
*/
public function testToArrayFallback() {
$this->entityType->expects($this->any())
->method('getPropertiesToExport')
->willReturn([]);
$this->setExpectedException(SchemaIncompleteException::class);
$this->entity->toArray();
}
/**
* @covers ::getThirdPartySetting
* @covers ::setThirdPartySetting
@@ -612,6 +586,17 @@ class ConfigEntityBaseUnitTest extends UnitTestCase {
$this->assertEquals([$third_party], $this->entity->getThirdPartyProviders());
}
/**
* @covers ::toArray
*/
public function testToArraySchemaException() {
$this->entityType->expects($this->any())
->method('getPropertiesToExport')
->willReturn(NULL);
$this->setExpectedException(SchemaIncompleteException::class, 'Incomplete or missing schema for test_provider.');
$this->entity->toArray();
}
}
class TestConfigEntityWithPluginCollections extends ConfigEntityBaseWithPluginCollections {
@@ -29,7 +29,7 @@ class ConfigEntityDependencyTest extends UnitTestCase {
'dependencies' => [
'module' => [
'node',
'views'
'views',
],
'config' => [
'config_test.dynamic.entity_id:745b0ce0-aece-42dd-a800-ade5b8455e84',
@@ -5,6 +5,7 @@ namespace Drupal\Tests\Core\Config\Entity;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Cache\MemoryCache\MemoryCache;
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigDuplicateUUIDException;
use Drupal\Core\Config\ConfigFactoryInterface;
@@ -133,7 +134,7 @@ class ConfigEntityStorageTest extends UnitTestCase {
$entity_query_factory = $this->prophesize(QueryFactoryInterface::class);
$entity_query_factory->get($entity_type, 'AND')->willReturn($this->entityQuery->reveal());
$this->entityStorage = new ConfigEntityStorage($entity_type, $this->configFactory->reveal(), $this->uuidService->reveal(), $this->languageManager->reveal());
$this->entityStorage = new ConfigEntityStorage($entity_type, $this->configFactory->reveal(), $this->uuidService->reveal(), $this->languageManager->reveal(), new MemoryCache());
$this->entityStorage->setModuleHandler($this->moduleHandler->reveal());
$entity_type_manager = $this->prophesize(EntityTypeManagerInterface::class);
@@ -2,6 +2,8 @@
namespace Drupal\Tests\Core\Config\Entity;
use Drupal\Core\Config\TypedConfigManagerInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Tests\UnitTestCase;
use Drupal\Core\Config\Entity\ConfigEntityType;
use Drupal\Core\Config\Entity\Exception\ConfigEntityStorageClassException;
@@ -12,6 +14,23 @@ use Drupal\Core\Config\Entity\Exception\ConfigEntityStorageClassException;
*/
class ConfigEntityTypeTest extends UnitTestCase {
/**
* The mocked typed config manager.
*
* @var \Drupal\Core\Config\TypedConfigManagerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $typedConfigManager;
/**
* {@inheritdoc}
*/
protected function setUp() {
$this->typedConfigManager = $this->getMock(TypedConfigManagerInterface::class);
$container = new ContainerBuilder();
$container->set('config.typed', $this->typedConfigManager);
\Drupal::setContainer($container);
}
/**
* Sets up a ConfigEntityType object for a given set of values.
*
@@ -85,7 +104,7 @@ class ConfigEntityTypeTest extends UnitTestCase {
$this->setExpectedException(ConfigEntityStorageClassException::class, '\Drupal\Core\Entity\KeyValueStore\KeyValueEntityStorage is not \Drupal\Core\Config\Entity\ConfigEntityStorage or it does not extend it');
new ConfigEntityType([
'id' => 'example_config_entity_type',
'handlers' => ['storage' => '\Drupal\Core\Entity\KeyValueStore\KeyValueEntityStorage']
'handlers' => ['storage' => '\Drupal\Core\Entity\KeyValueStore\KeyValueEntityStorage'],
]);
}
@@ -137,11 +156,6 @@ class ConfigEntityTypeTest extends UnitTestCase {
public function providerGetPropertiesToExport() {
$data = [];
$data[] = [
[],
NULL,
];
$data[] = [
[
'config_export' => [
@@ -177,4 +191,27 @@ class ConfigEntityTypeTest extends UnitTestCase {
return $data;
}
/**
* @covers ::getPropertiesToExport
*/
public function testGetPropertiesToExportSchemaFallback() {
$this->typedConfigManager->expects($this->once())
->method('getDefinition')
->will($this->returnValue(['mapping' => ['id' => '', 'dependencies' => '']]));
$config_entity_type = new ConfigEntityType([
'id' => 'example_config_entity_type',
]);
$this->assertEquals(['id' => 'id', 'dependencies' => 'dependencies'], $config_entity_type->getPropertiesToExport('test'));
}
/**
* @covers ::getPropertiesToExport
*/
public function testGetPropertiesToExportNoFallback() {
$config_entity_type = new ConfigEntityType([
'id' => 'example_config_entity_type',
]);
$this->assertNull($config_entity_type->getPropertiesToExport());
}
}
@@ -37,42 +37,42 @@ class QueryFactoryTest extends UnitTestCase {
$tests[] = [
['uuid:abc'],
'uuid',
$this->getConfigObject('test')->set('uuid', 'abc')
$this->getConfigObject('test')->set('uuid', 'abc'),
];
// Tests a lookup being set to a top level key when sub-keys exist.
$tests[] = [
[],
'uuid',
$this->getConfigObject('test')->set('uuid.blah', 'abc')
$this->getConfigObject('test')->set('uuid.blah', 'abc'),
];
// Tests a non existent key.
$tests[] = [
[],
'uuid',
$this->getConfigObject('test')
$this->getConfigObject('test'),
];
// Tests a non existent sub key.
$tests[] = [
[],
'uuid.blah',
$this->getConfigObject('test')->set('uuid', 'abc')
$this->getConfigObject('test')->set('uuid', 'abc'),
];
// Tests a existent sub key.
$tests[] = [
['uuid.blah:abc'],
'uuid.blah',
$this->getConfigObject('test')->set('uuid.blah', 'abc')
$this->getConfigObject('test')->set('uuid.blah', 'abc'),
];
// One wildcard.
$tests[] = [
['test.*.value:a', 'test.*.value:b'],
'test.*.value',
$this->getConfigObject('test')->set('test.a.value', 'a')->set('test.b.value', 'b')
$this->getConfigObject('test')->set('test.a.value', 'a')->set('test.b.value', 'b'),
];
// Three wildcards.
@@ -82,14 +82,14 @@ class QueryFactoryTest extends UnitTestCase {
$this->getConfigObject('test')
->set('test.a.sub2.a.sub4.a.value', 'aaa')
->set('test.a.sub2.a.sub4.b.value', 'aab')
->set('test.b.sub2.a.sub4.b.value', 'bab')
->set('test.b.sub2.a.sub4.b.value', 'bab'),
];
// Three wildcards in a row.
$tests[] = [
['test.*.*.*.value:abc', 'test.*.*.*.value:abd'],
'test.*.*.*.value',
$this->getConfigObject('test')->set('test.a.b.c.value', 'abc')->set('test.a.b.d.value', 'abd')
$this->getConfigObject('test')->set('test.a.b.c.value', 'abc')->set('test.a.b.d.value', 'abd'),
];
return $tests;
@@ -63,7 +63,7 @@ class StorageComparerTest extends UnitTestCase {
'uuid' => $uuid->generate(),
'dependencies' => [
'config' => [
'field.storage.node.body'
'field.storage.node.body',
],
],
],
@@ -89,7 +89,7 @@ class StorageComparerTest extends UnitTestCase {
],
// Simple config.
'system.performance' => [
'stale_file_threshold' => 2592000
'stale_file_threshold' => 2592000,
],
];
@@ -72,6 +72,7 @@ class ControllerResolverTest extends UnitTestCase {
* @see \Drupal\Core\Controller\ControllerResolver::doGetArguments()
*
* @group legacy
* @expectedDeprecation Drupal\Core\Controller\ControllerResolver::doGetArguments is deprecated as of 8.6.0 and will be removed in 9.0. Inject the "http_kernel.controller.argument_resolver" service instead.
*/
public function testGetArguments() {
$controller = function (EntityInterface $entity, $user, RouteMatchInterface $route_match, ServerRequestInterface $psr_7) {
@@ -160,7 +161,7 @@ class ControllerResolverTest extends UnitTestCase {
// Tests passing a controller via the request.
[['_controller' => 'Drupal\Tests\Core\Controller\MockContainerAware::getResult'], 'Drupal\Tests\Core\Controller\MockContainerAware', 'This is container aware.'],
// Tests a request with no controller specified.
[[], FALSE]
[[], FALSE],
];
}
@@ -189,6 +190,7 @@ class ControllerResolverTest extends UnitTestCase {
['Drupal\Tests\Core\Controller\MockInvokeController', 'This used __invoke().'],
];
}
/**
* Tests getControllerFromDefinition() without a callable.
*/
@@ -251,6 +253,7 @@ class ControllerResolverTest extends UnitTestCase {
}
class MockController {
public function getResult() {
return 'This is a regular controller.';
}
@@ -261,6 +264,7 @@ class MockController {
}
class MockControllerPsr7 {
public function getResult() {
return ['#markup' => 'This is a regular controller'];
}
@@ -273,12 +277,15 @@ class MockControllerPsr7 {
class MockContainerInjection implements ContainerInjectionInterface {
protected $result;
public function __construct($result) {
$this->result = $result;
}
public static function create(ContainerInterface $container) {
return new static('This used injection.');
}
public function getResult() {
return $this->result;
}
@@ -286,12 +293,14 @@ class MockContainerInjection implements ContainerInjectionInterface {
}
class MockContainerAware implements ContainerAwareInterface {
use ContainerAwareTrait;
public function getResult() {
return 'This is container aware.';
}
}
class MockInvokeController {
public function __invoke() {
return 'This used __invoke().';
}
@@ -0,0 +1,30 @@
<?php
namespace Drupal\Tests\Core\Controller;
use Drupal\Core\Controller\ControllerResolver;
use Drupal\Core\Controller\HtmlFormController;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Tests\UnitTestCase;
/**
* Tests the FormController class.
*
* @group Controller
*/
class FormControllerTest extends UnitTestCase {
/**
* @expectedDeprecation Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.
* @group legacy
*/
public function testControllerResolverDeprecation() {
$controller_resolver = $this->getMockBuilder(ControllerResolver::class)->disableOriginalConstructor()->getMock();
$form_builder = $this->getMockBuilder(FormBuilderInterface::class)->getMock();
$class_resolver = $this->getMockBuilder(ClassResolverInterface::class)->getMock();
// Use the HtmlFormController as FormController is abstract.
new HtmlFormController($controller_resolver, $form_builder, $class_resolver);
}
}
@@ -34,6 +34,13 @@ class TitleResolverTest extends UnitTestCase {
*/
protected $translationManager;
/**
* The mocked argument resolver.
*
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $argumentResolver;
/**
* The actual tested title resolver.
*
@@ -44,8 +51,9 @@ class TitleResolverTest extends UnitTestCase {
protected function setUp() {
$this->controllerResolver = $this->getMock('\Drupal\Core\Controller\ControllerResolverInterface');
$this->translationManager = $this->getMock('\Drupal\Core\StringTranslation\TranslationInterface');
$this->argumentResolver = $this->getMock('\Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
$this->titleResolver = new TitleResolver($this->controllerResolver, $this->translationManager);
$this->titleResolver = new TitleResolver($this->controllerResolver, $this->translationManager, $this->argumentResolver);
}
/**
@@ -108,7 +116,7 @@ class TitleResolverTest extends UnitTestCase {
->method('getControllerFromDefinition')
->with('Drupal\Tests\Core\Controller\TitleCallback::example')
->will($this->returnValue($callable));
$this->controllerResolver->expects($this->once())
$this->argumentResolver->expects($this->once())
->method('getArguments')
->with($request, $callable)
->will($this->returnValue(['example']));
@@ -12,6 +12,7 @@ use Drupal\Tests\UnitTestCase;
* @group Database
*/
class EmptyStatementTest extends UnitTestCase {
/**
* Tests that the empty result set behaves as empty.
*/
@@ -2,16 +2,35 @@
namespace Drupal\Tests\Core\Database;
use Composer\Autoload\ClassLoader;
use Drupal\Core\Database\Database;
use Drupal\Tests\UnitTestCase;
/**
* Tests for database URL to/from database connection array coversions.
*
* These tests run in isolation since we don't want the database static to
* affect other tests.
*
* @coversDefaultClass \Drupal\Core\Database\Database
*
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
*
* @group Database
*/
class UrlConversionTest extends UnitTestCase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$additional_class_loader = new ClassLoader();
$additional_class_loader->addPsr4("Drupal\\Driver\\Database\\fake\\", __DIR__ . "/fixtures/driver/fake");
$additional_class_loader->register(TRUE);
}
/**
* @covers ::convertDbUrlToConnectionInfo
*
@@ -32,30 +51,82 @@ class UrlConversionTest extends UnitTestCase {
* - database_array: An array containing the expected results.
*/
public function providerConvertDbUrlToConnectionInfo() {
// Some valid datasets.
$root1 = '';
$url1 = 'mysql://test_user:test_pass@test_host:3306/test_database';
$database_array1 = [
'driver' => 'mysql',
'username' => 'test_user',
'password' => 'test_pass',
'host' => 'test_host',
'database' => 'test_database',
'port' => '3306',
];
$root2 = '/var/www/d8';
$url2 = 'sqlite://test_user:test_pass@test_host:3306/test_database';
$database_array2 = [
'driver' => 'sqlite',
'username' => 'test_user',
'password' => 'test_pass',
'host' => 'test_host',
'database' => $root2 . '/test_database',
'port' => 3306,
];
return [
[$root1, $url1, $database_array1],
[$root2, $url2, $database_array2],
'MySql without prefix' => [
'',
'mysql://test_user:test_pass@test_host:3306/test_database',
[
'driver' => 'mysql',
'username' => 'test_user',
'password' => 'test_pass',
'host' => 'test_host',
'database' => 'test_database',
'port' => 3306,
'namespace' => 'Drupal\Core\Database\Driver\mysql',
],
],
'SQLite, relative to root, without prefix' => [
'/var/www/d8',
'sqlite://localhost/test_database',
[
'driver' => 'sqlite',
'host' => 'localhost',
'database' => '/var/www/d8/test_database',
'namespace' => 'Drupal\Core\Database\Driver\sqlite',
],
],
'MySql with prefix' => [
'',
'mysql://test_user:test_pass@test_host:3306/test_database#bar',
[
'driver' => 'mysql',
'username' => 'test_user',
'password' => 'test_pass',
'host' => 'test_host',
'database' => 'test_database',
'prefix' => [
'default' => 'bar',
],
'port' => 3306,
'namespace' => 'Drupal\Core\Database\Driver\mysql',
],
],
'SQLite, relative to root, with prefix' => [
'/var/www/d8',
'sqlite://localhost/test_database#foo',
[
'driver' => 'sqlite',
'host' => 'localhost',
'database' => '/var/www/d8/test_database',
'prefix' => [
'default' => 'foo',
],
'namespace' => 'Drupal\Core\Database\Driver\sqlite',
],
],
'SQLite, absolute path, without prefix' => [
'/var/www/d8',
'sqlite://localhost//baz/test_database',
[
'driver' => 'sqlite',
'host' => 'localhost',
'database' => '/baz/test_database',
'namespace' => 'Drupal\Core\Database\Driver\sqlite',
],
],
'Fake custom database driver, without prefix' => [
'',
'fake://fake_user:fake_pass@fake_host:3456/fake_database',
[
'driver' => 'fake',
'username' => 'fake_user',
'password' => 'fake_pass',
'host' => 'fake_host',
'database' => 'fake_database',
'port' => 3456,
'namespace' => 'Drupal\Driver\Database\fake',
],
],
];
}
@@ -64,8 +135,8 @@ class UrlConversionTest extends UnitTestCase {
*
* @dataProvider providerInvalidArgumentsUrlConversion
*/
public function testGetInvalidArgumentExceptionInUrlConversion($url, $root) {
$this->setExpectedException(\InvalidArgumentException::class);
public function testGetInvalidArgumentExceptionInUrlConversion($url, $root, $expected_exception_message) {
$this->setExpectedException(\InvalidArgumentException::class, $expected_exception_message);
Database::convertDbUrlToConnectionInfo($url, $root);
}
@@ -76,32 +147,28 @@ class UrlConversionTest extends UnitTestCase {
* Array of arrays with the following elements:
* - An invalid Url string.
* - Drupal root string.
* - The expected exception message.
*/
public function providerInvalidArgumentsUrlConversion() {
return [
['foo', ''],
['foo', 'bar'],
['foo://', 'bar'],
['foo://bar', 'baz'],
['foo://bar:port', 'baz'],
['foo/bar/baz', 'bar2'],
['foo://bar:baz@test1', 'test2'],
['foo', '', "Missing scheme in URL 'foo'"],
['foo', 'bar', "Missing scheme in URL 'foo'"],
['foo://', 'bar', "Can not convert 'foo://' to a database connection, class 'Drupal\\Driver\\Database\\foo\\Connection' does not exist"],
['foo://bar', 'baz', "Can not convert 'foo://bar' to a database connection, class 'Drupal\\Driver\\Database\\foo\\Connection' does not exist"],
['foo://bar:port', 'baz', "Can not convert 'foo://bar:port' to a database connection, class 'Drupal\\Driver\\Database\\foo\\Connection' does not exist"],
['foo/bar/baz', 'bar2', "Missing scheme in URL 'foo/bar/baz'"],
['foo://bar:baz@test1', 'test2', "Can not convert 'foo://bar:baz@test1' to a database connection, class 'Drupal\\Driver\\Database\\foo\\Connection' does not exist"],
];
}
/**
* @covers ::convertDbUrlToConnectionInfo
* @covers ::getConnectionInfoAsUrl
*
* @dataProvider providerGetConnectionInfoAsUrl
*/
public function testGetConnectionInfoAsUrl(array $info, $expected_url) {
Database::addConnectionInfo('default', 'default', $info);
$url = Database::getConnectionInfoAsUrl();
// Remove the connection to not pollute subsequent datasets being tested.
Database::removeConnection('default');
$this->assertEquals($expected_url, $url);
}
@@ -122,7 +189,6 @@ class UrlConversionTest extends UnitTestCase {
'prefix' => '',
'host' => 'test_host',
'port' => '3306',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
];
$expected_url1 = 'mysql://test_user:test_pass@test_host:3306/test_database';
@@ -144,10 +210,58 @@ class UrlConversionTest extends UnitTestCase {
];
$expected_url3 = 'sqlite://localhost/test_database';
$info4 = [
'database' => 'test_database',
'driver' => 'sqlite',
'prefix' => 'pre',
];
$expected_url4 = 'sqlite://localhost/test_database#pre';
return [
[$info1, $expected_url1],
[$info2, $expected_url2],
[$info3, $expected_url3],
[$info4, $expected_url4],
];
}
/**
* Test ::getConnectionInfoAsUrl() exception for invalid arguments.
*
* @covers ::getConnectionInfoAsUrl
*
* @param array $connection_options
* The database connection information.
* @param string $expected_exception_message
* The expected exception message.
*
* @dataProvider providerInvalidArgumentGetConnectionInfoAsUrl
*/
public function testGetInvalidArgumentGetConnectionInfoAsUrl(array $connection_options, $expected_exception_message) {
Database::addConnectionInfo('default', 'default', $connection_options);
$this->setExpectedException(\InvalidArgumentException::class, $expected_exception_message);
$url = Database::getConnectionInfoAsUrl();
}
/**
* Dataprovider for testGetInvalidArgumentGetConnectionInfoAsUrl().
*
* @return array
* Array of arrays with the following elements:
* - An array mocking the database connection info. Possible keys are
* database, username, password, prefix, host, port, namespace and driver.
* - The expected exception message.
*/
public function providerInvalidArgumentGetConnectionInfoAsUrl() {
return [
'Missing database key' => [
[
'driver' => 'sqlite',
'host' => 'localhost',
'namespace' => 'Drupal\Core\Database\Driver\sqlite',
],
"As a minimum, the connection options array must contain at least the 'driver' and 'database' keys",
],
];
}
@@ -0,0 +1,70 @@
<?php
namespace Drupal\Driver\Database\fake;
use Drupal\Core\Database\Connection as CoreConnection;
use Drupal\Core\Database\StatementEmpty;
/**
* A fake Connection class for testing purposes.
*/
class Connection extends CoreConnection {
/**
* Public property so we can test driver loading mechanism.
*
* @var string
* @see driver().
*/
public $driver = 'fake';
/**
* {@inheritdoc}
*/
public function queryRange($query, $from, $count, array $args = [], array $options = []) {
return new StatementEmpty();
}
/**
* {@inheritdoc}
*/
public function queryTemporary($query, array $args = [], array $options = []) {
return '';
}
/**
* {@inheritdoc}
*/
public function driver() {
return $this->driver;
}
/**
* {@inheritdoc}
*/
public function databaseType() {
return 'fake';
}
/**
* {@inheritdoc}
*/
public function createDatabase($database) {
return;
}
/**
* {@inheritdoc}
*/
public function mapConditionOperator($operator) {
return NULL;
}
/**
* {@inheritdoc}
*/
public function nextId($existing_id = 0) {
return 0;
}
}
@@ -51,7 +51,7 @@ class DateHelperTest extends UnitTestCase {
5 => 'Friday',
6 => 'Saturday',
0 => 'Sunday',
]
],
];
$data[] = [
2,
@@ -212,4 +212,29 @@ class DrupalDateTimeTest extends UnitTestCase {
$date->setTimezone(new \DateTimeZone('America/New_York'))->nonexistent();
}
/**
* @covers ::getPhpDateTime
*/
public function testGetPhpDateTime() {
$new_york = new \DateTimeZone('America/New_York');
$berlin = new \DateTimeZone('Europe/Berlin');
// Test retrieving a cloned copy of the wrapped \DateTime object, and that
// altering it does not change the DrupalDateTime object.
$drupaldatetime = DrupalDateTime::createFromFormat('Y-m-d H:i:s', '2017-07-13 22:40:00', $new_york, ['langcode' => 'en']);
$this->assertEquals(1500000000, $drupaldatetime->getTimestamp());
$this->assertEquals('America/New_York', $drupaldatetime->getTimezone()->getName());
$datetime = $drupaldatetime->getPhpDateTime();
$this->assertInstanceOf('DateTime', $datetime);
$this->assertEquals(1500000000, $datetime->getTimestamp());
$this->assertEquals('America/New_York', $datetime->getTimezone()->getName());
$datetime->setTimestamp(1400000000)->setTimezone($berlin);
$this->assertEquals(1400000000, $datetime->getTimestamp());
$this->assertEquals('Europe/Berlin', $datetime->getTimezone()->getName());
$this->assertEquals(1500000000, $drupaldatetime->getTimestamp());
$this->assertEquals('America/New_York', $drupaldatetime->getTimezone()->getName());
}
}
@@ -29,7 +29,6 @@ class ProxyServicesPassTest extends UnitTestCase {
$this->proxyServicesPass = new ProxyServicesPass();
}
/**
* @covers ::process
*/
@@ -347,7 +347,7 @@ class TaggedHandlersPassTest extends UnitTestCase {
$container
->register('consumer_id', __NAMESPACE__ . '\ValidConsumerWithExtraArguments')
->addTag('service_collector', [
'call' => 'addNoPriority'
'call' => 'addNoPriority',
]);
$container
@@ -376,7 +376,7 @@ class TaggedHandlersPassTest extends UnitTestCase {
$container
->register('consumer_id', __NAMESPACE__ . '\ValidConsumerWithExtraArguments')
->addTag('service_collector', [
'call' => 'addWithId'
'call' => 'addWithId',
]);
$container
@@ -408,7 +408,7 @@ class TaggedHandlersPassTest extends UnitTestCase {
$container
->register('consumer_id', __NAMESPACE__ . '\ValidConsumerWithExtraArguments')
->addTag('service_collector', [
'call' => 'addWithDifferentOrder'
'call' => 'addWithDifferentOrder',
]);
$container
@@ -416,7 +416,7 @@ class TaggedHandlersPassTest extends UnitTestCase {
->addTag('consumer_id', [
'priority' => 0,
'extra1' => 'extra1',
'extra3' => 'extra3'
'extra3' => 'extra3',
]);
$handler_pass = new TaggedHandlersPass();
@@ -433,26 +433,34 @@ class TaggedHandlersPassTest extends UnitTestCase {
interface HandlerInterface {
}
class ValidConsumer {
public function addHandler(HandlerInterface $instance, $priority = 0) {
}
public function addNoPriority(HandlerInterface $instance) {
}
public function addWithId(HandlerInterface $instance, $id, $priority = 0) {
}
}
class InvalidConsumer {
public function addHandler($instance, $priority = 0) {
}
}
class ValidConsumerWithExtraArguments {
public function addHandler(HandlerInterface $instance, $priority = 0, $extra1 = '', $extra2 = '') {
}
public function addNoPriority(HandlerInterface $instance, $extra) {
}
public function addWithId(HandlerInterface $instance, $id, $priority = 0, $extra1 = '', $extra2 = NULL) {
}
public function addWithDifferentOrder(HandlerInterface $instance, $extra1, $priority = 0, $extra2 = 'default2', $extra3 = 'default3') {
}
@@ -21,7 +21,7 @@ class DiscoverServiceProvidersTest extends UnitTestCase {
public function testDiscoverServiceCustom() {
new Settings([
'container_yamls' => [
__DIR__ . '/fixtures/custom.yml'
__DIR__ . '/fixtures/custom.yml',
],
]);
@@ -116,7 +116,7 @@ namespace Drupal\Tests\Core\DrupalKernel {
'www.example.com',
'www.example.com',
'canonical URL is trusted',
TRUE
TRUE,
];
// Tests missing hostname for HTTP/1.0 compatibility where the Host
@@ -128,25 +128,25 @@ namespace Drupal\Tests\Core\DrupalKernel {
'example.com',
'www.example.com',
'host from settings is trusted',
TRUE
TRUE,
];
$data[] = [
'subdomain.example.com',
'www.example.com',
'host from settings is trusted',
TRUE
TRUE,
];
$data[] = [
'www.example.org',
'www.example.com',
'host from settings is trusted',
TRUE
TRUE,
];
$data[] = [
'example.org',
'www.example.com',
'host from settings is trusted',
TRUE
TRUE,
];
// Tests mismatch.
@@ -154,7 +154,7 @@ namespace Drupal\Tests\Core\DrupalKernel {
'www.blackhat.com',
'www.example.com',
'unspecified host is untrusted',
FALSE
FALSE,
];
return $data;
@@ -245,8 +245,10 @@ EOD;
namespace {
if (!function_exists('drupal_valid_test_ua')) {
function drupal_valid_test_ua($new_prefix = NULL) {
return FALSE;
}
}
}
+16 -2
View File
@@ -2,6 +2,7 @@
namespace Drupal\Tests\Core;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\DependencyInjection\ContainerNotInitializedException;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
@@ -120,8 +121,21 @@ class DrupalTest extends UnitTestCase {
* @covers ::classResolver
*/
public function testClassResolver() {
$this->setMockContainerService('class_resolver');
$this->assertNotNull(\Drupal::classResolver());
$class_resolver = $this->prophesize(ClassResolverInterface::class);
$this->setMockContainerService('class_resolver', $class_resolver->reveal());
$this->assertInstanceOf(ClassResolverInterface::class, \Drupal::classResolver());
}
/**
* Tests the classResolver method when called with a class.
*
* @covers ::classResolver
*/
public function testClassResolverWithClass() {
$class_resolver = $this->prophesize(ClassResolverInterface::class);
$class_resolver->getInstanceFromDefinition(static::class)->willReturn($this);
$this->setMockContainerService('class_resolver', $class_resolver->reveal());
$this->assertSame($this, \Drupal::classResolver(static::class));
}
/**
@@ -69,7 +69,6 @@ class EntityFormDisplayAccessControlHandlerTest extends UnitTestCase {
*/
protected $entity;
/**
* Returns a mock Entity Type Manager.
*
@@ -4,7 +4,9 @@ namespace Drupal\Tests\Core\Entity;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Tests\UnitTestCase;
/**
@@ -29,7 +31,6 @@ class BaseFieldDefinitionTest extends UnitTestCase {
*/
protected $fieldTypeDefinition;
/**
* {@inheritdoc}
*/
@@ -41,7 +42,7 @@ class BaseFieldDefinitionTest extends UnitTestCase {
$this->fieldTypeDefinition = [
'id' => $this->fieldType,
'storage_settings' => [
'some_setting' => 'value 1'
'some_setting' => 'value 1',
],
'field_settings' => [
'some_instance_setting' => 'value 2',
@@ -167,6 +168,7 @@ class BaseFieldDefinitionTest extends UnitTestCase {
// Set the field item list class to be used to avoid requiring the typed
// data manager to retrieve it.
$definition->setClass('Drupal\Core\Field\FieldItemList');
$definition->setItemDefinition(DataDefinition::createFromDataType('string')->setClass(FieldItemBase::class));
$this->assertEquals($expected_default_value, $definition->getDefaultValue($entity));
$data_definition = $this->getMockBuilder('Drupal\Core\TypedData\DataDefinition')
@@ -202,6 +204,7 @@ class BaseFieldDefinitionTest extends UnitTestCase {
*/
public function testFieldInitialValue() {
$definition = BaseFieldDefinition::create($this->fieldType);
$definition->setItemDefinition(DataDefinition::createFromDataType('string')->setClass(FieldItemBase::class));
$default_value = [
'value' => $this->randomMachineName(),
];
@@ -483,6 +483,8 @@ class ContentEntityBaseUnitTest extends UnitTestCase {
/**
* @covers ::label
*
* @group legacy
*/
public function testLabel() {
// Make a mock with one method that we use as the entity's label callback.
@@ -0,0 +1,33 @@
<?php
namespace Drupal\Tests\Core\Entity;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Entity\ContentEntityForm
* @group Entity
*/
class ContentEntityFormTest extends UnitTestCase {
/**
* @group legacy
* @expectedDeprecation Passing the entity.manager service to ContentEntityForm::__construct() is deprecated in Drupal 8.6.0 and will be removed before Drupal 9.0.0. Pass the entity.repository service instead. See https://www.drupal.org/node/2549139.
*/
public function testEntityManagerDeprecation() {
$entity_manager = $this->prophesize(EntityManagerInterface::class)->reveal();
$entity_type_bundle_info = $this->prophesize(EntityTypeBundleInfoInterface::class)->reveal();
$time = $this->prophesize(TimeInterface::class)->reveal();
$form = new ContentEntityForm($entity_manager, $entity_type_bundle_info, $time);
$reflected_form = new \ReflectionClass($form);
$entity_manager_property = $reflected_form->getProperty('entityManager');
$entity_manager_property->setAccessible(TRUE);
$this->assertTrue($entity_manager_property->getValue($form) === $entity_manager);
}
}
@@ -74,6 +74,9 @@ class EntityCreateAccessCheckTest extends UnitTestCase {
if ($expect_permission_context) {
$expected_access_result->cachePerPermissions();
}
if (!$entity_bundle && !$expect_permission_context) {
$expected_access_result->setReason("Could not find '{bundle_argument}' request argument, therefore cannot check create access.");
}
$entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
@@ -676,7 +676,7 @@ class EntityFieldManagerTest extends UnitTestCase {
'type' => 'string',
'bundles' => ['second_bundle' => 'second_bundle'],
],
]
],
];
$this->assertEquals($expected, $this->entityFieldManager->getFieldMap());
}
@@ -695,7 +695,7 @@ class EntityFieldManagerTest extends UnitTestCase {
'type' => 'string',
'bundles' => ['second_bundle' => 'second_bundle'],
],
]
],
];
$this->setUpEntityTypeDefinitions();
$this->cacheBackend->get('entity_field_map')->willReturn((object) ['data' => $expected]);
@@ -58,6 +58,13 @@ class EntityLinkTest extends UnitTestCase {
* @covers ::link
*
* @dataProvider providerTestLink
*
* @group legacy
*
* Note this is only a legacy test because it triggers a call to
* \Drupal\Core\Entity\EntityTypeInterface::getLabelCallback() which is mocked
* and triggers a deprecation error. Remove when ::getLabelCallback() is
* removed.
*/
public function testLink($entity_label, $link_text, $expected_text, $link_rel = 'canonical', array $link_options = []) {
$language = new Language(['id' => 'es']);
@@ -120,6 +127,13 @@ class EntityLinkTest extends UnitTestCase {
* @covers ::toLink
*
* @dataProvider providerTestLink
*
* @group legacy
*
* Note this is only a legacy test because it triggers a call to
* \Drupal\Core\Entity\EntityTypeInterface::getLabelCallback() which is mocked
* and triggers a deprecation error. Remove when ::getLabelCallback() is
* removed.
*/
public function testToLink($entity_label, $link_text, $expected_text, $link_rel = 'canonical', array $link_options = []) {
$language = new Language(['id' => 'es']);
@@ -154,6 +154,7 @@ class EntityListBuilderTest extends UnitTestCase {
}
class TestEntityListBuilder extends EntityTestListBuilder {
public function buildOperations(EntityInterface $entity) {
return [];
}
@@ -5,6 +5,7 @@ namespace Drupal\Tests\Core\Entity;
use Drupal\Core\Entity\EntityType;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Tests\UnitTestCase;
/**
@@ -476,4 +477,22 @@ class EntityTypeTest extends UnitTestCase {
$this->assertEmpty($reflection->getProperties(\ReflectionProperty::IS_PUBLIC));
}
/**
* Tests that the EntityType object can be serialized.
*/
public function testIsSerializable() {
$entity_type = $this->setUpEntityType([]);
$translation = $this->prophesize(TranslationInterface::class);
$translation->willImplement(\Serializable::class);
$translation->serialize()->willThrow(\Exception::class);
$translation_service = $translation->reveal();
$translation_service->_serviceId = 'string_translation';
$entity_type->setStringTranslation($translation_service);
$entity_type = unserialize(serialize($entity_type));
$this->assertEquals('example_entity_type', $entity_type->id());
}
}
@@ -168,6 +168,7 @@ class EntityUnitTest extends UnitTestCase {
/**
* @covers ::label
* @group legacy
*/
public function testLabel() {
// Make a mock with one method that we use as the entity's uri_callback. We
@@ -2,14 +2,18 @@
namespace Drupal\Tests\Core\Entity;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Entity\Entity;
use Drupal\Core\Entity\EntityMalformedException;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Exception\UndefinedLinkTemplateException;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\Core\GeneratedUrl;
use Drupal\Core\Routing\UrlGeneratorInterface;
use Drupal\Core\Url;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
/**
* Tests URL handling of the \Drupal\Core\Entity\Entity class.
@@ -496,6 +500,38 @@ class EntityUrlTest extends UnitTestCase {
return $test_cases;
}
/**
* Tests the uriRelationships() method.
*
* @covers ::uriRelationships
*/
public function testUriRelationships() {
$entity = $this->getEntity(Entity::class, ['id' => $this->entityId]);
$container_builder = new ContainerBuilder();
$url_generator = $this->createMock(UrlGeneratorInterface::class);
$container_builder->set('url_generator', $url_generator);
\Drupal::setContainer($container_builder);
// Test route with no mandatory parameters.
$this->registerLinkTemplate('canonical');
$route_name_0 = 'entity.' . $this->entityTypeId . '.canonical';
$url_generator->expects($this->at(0))
->method('generateFromRoute')
->with($route_name_0)
->willReturn((new GeneratedUrl())->setGeneratedUrl('/entity_test'));
$this->assertEquals(['canonical'], $entity->uriRelationships());
// Test route with non-default mandatory parameters.
$this->registerLinkTemplate('{non_default_parameter}');
$route_name_1 = 'entity.' . $this->entityTypeId . '.{non_default_parameter}';
$url_generator->expects($this->at(0))
->method('generateFromRoute')
->with($route_name_1)
->willThrowException(new MissingMandatoryParametersException());
$this->assertEquals([], $entity->uriRelationships());
}
/**
* Returns a mock entity for testing.
*
@@ -2,6 +2,7 @@
namespace Drupal\Tests\Core\Entity\KeyValueStore;
use Drupal\Core\Cache\MemoryCache\MemoryCache;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Entity\EntityFieldManagerInterface;
@@ -143,7 +144,7 @@ class KeyValueEntityStorageTest extends UnitTestCase {
->method('getCurrentLanguage')
->will($this->returnValue($language));
$this->entityStorage = new KeyValueEntityStorage($this->entityType, $this->keyValueStore, $this->uuidService, $this->languageManager);
$this->entityStorage = new KeyValueEntityStorage($this->entityType, $this->keyValueStore, $this->uuidService, $this->languageManager, new MemoryCache());
$this->entityStorage->setModuleHandler($this->moduleHandler);
$container = new ContainerBuilder();
@@ -356,15 +356,19 @@ class TestDefaultHtmlRouteProvider extends DefaultHtmlRouteProvider {
public function getEntityTypeIdKeyType(EntityTypeInterface $entity_type) {
return parent::getEntityTypeIdKeyType($entity_type);
}
public function getAddPageRoute(EntityTypeInterface $entity_type) {
return parent::getAddPageRoute($entity_type);
}
public function getAddFormRoute(EntityTypeInterface $entity_type) {
return parent::getAddFormRoute($entity_type);
}
public function getCanonicalRoute(EntityTypeInterface $entity_type) {
return parent::getCanonicalRoute($entity_type);
}
public function getCollectionRoute(EntityTypeInterface $entity_type) {
return parent::getCollectionRoute($entity_type);
}
@@ -362,38 +362,35 @@ class DefaultTableMappingTest extends UnitTestCase {
->method('getColumns')
->willReturn($columns);
$storage = $this->getMockBuilder('\Drupal\Core\Entity\Sql\SqlContentEntityStorage')
->disableOriginalConstructor()
->getMock();
$storage
$this->entityType
->expects($this->any())
->method('getBaseTable')
->willReturn(isset($table_names['base']) ? $table_names['base'] : 'base_table');
->willReturn(isset($table_names['base']) ? $table_names['base'] : 'entity_test');
$storage
$this->entityType
->expects($this->any())
->method('getDataTable')
->willReturn(isset($table_names['data']) ? $table_names['data'] : NULL);
->willReturn(isset($table_names['data']) ? $table_names['data'] : FALSE);
$storage
$this->entityType
->expects($this->any())
->method('getRevisionTable')
->willReturn(isset($table_names['revision']) ? $table_names['revision'] : NULL);
->willReturn(isset($table_names['revision']) ? $table_names['revision'] : FALSE);
$entity_manager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface');
$entity_manager
$this->entityType
->expects($this->any())
->method('getStorage')
->willReturn($storage);
->method('isTranslatable')
->willReturn(isset($table_names['data']));
$container = $this->getMock('\Symfony\Component\DependencyInjection\ContainerInterface');
$container
$this->entityType
->expects($this->any())
->method('get')
->willReturn($entity_manager);
->method('isRevisionable')
->willReturn(isset($table_names['revision']));
\Drupal::setContainer($container);
$this->entityType
->expects($this->any())
->method('getRevisionMetadataKeys')
->willReturn([]);
$table_mapping = new DefaultTableMapping($this->entityType, [$field_name => $definition]);
@@ -51,7 +51,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
/**
* The storage schema handler used in this test.
*
* @var \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema|\PHPUnit_Framework_MockObject_MockObject.
* @var \Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema|\PHPUnit_Framework_MockObject_MockObject
*/
protected $storageSchema;
@@ -155,7 +155,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
],
'domain' => [
'type' => 'varchar',
]
],
],
'unique keys' => [
'email' => ['username', 'hostname', ['domain', 3]],
@@ -194,7 +194,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
],
'city' => [
'type' => 'varchar',
]
],
],
'indexes' => [
'country_state_city' => ['country', 'state', ['city', 10]],
@@ -370,6 +370,9 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
$this->storage->expects($this->any())
->method('getTableMapping')
->will($this->returnValue($table_mapping));
$this->storage->expects($this->any())
->method('getCustomTableMapping')
->will($this->returnValue($table_mapping));
$this->assertNull(
$this->storageSchema->onEntityTypeCreate($this->entityType)
@@ -389,13 +392,22 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
* @covers ::processIdentifierSchema
*/
public function testGetSchemaRevisionable() {
$this->entityType = new ContentEntityType([
'id' => 'entity_test',
'entity_keys' => [
'id' => 'id',
'revision' => 'revision_id',
],
]);
$this->entityType = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityType')
->setConstructorArgs([
[
'id' => 'entity_test',
'entity_keys' => [
'id' => 'id',
'revision' => 'revision_id',
],
],
])
->setMethods(['getRevisionMetadataKeys'])
->getMock();
$this->entityType->expects($this->any())
->method('getRevisionMetadataKeys')
->will($this->returnValue([]));
$this->storage->expects($this->exactly(2))
->method('getRevisionTable')
@@ -420,7 +432,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
'revision_id' => [
'type' => 'int',
'not null' => FALSE,
]
],
],
'primary key' => ['id'],
'unique keys' => [
@@ -431,7 +443,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
'entity_test__revision' => [
'table' => 'entity_test_revision',
'columns' => ['revision_id' => 'revision_id'],
]
],
],
],
'entity_test_revision' => [
@@ -469,6 +481,9 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
$this->storage->expects($this->any())
->method('getTableMapping')
->will($this->returnValue($table_mapping));
$this->storage->expects($this->any())
->method('getCustomTableMapping')
->will($this->returnValue($table_mapping));
$this->storageSchema->onEntityTypeCreate($this->entityType);
}
@@ -524,7 +539,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
'langcode' => [
'type' => 'varchar',
'not null' => TRUE,
]
],
],
'primary key' => ['id'],
'unique keys' => [],
@@ -577,6 +592,9 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
$this->storage->expects($this->any())
->method('getTableMapping')
->will($this->returnValue($table_mapping));
$this->storage->expects($this->any())
->method('getCustomTableMapping')
->will($this->returnValue($table_mapping));
$this->assertNull(
$this->storageSchema->onEntityTypeCreate($this->entityType)
@@ -595,14 +613,23 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
* @covers ::processRevisionDataTable
*/
public function testGetSchemaRevisionableTranslatable() {
$this->entityType = new ContentEntityType([
'id' => 'entity_test',
'entity_keys' => [
'id' => 'id',
'revision' => 'revision_id',
'langcode' => 'langcode',
],
]);
$this->entityType = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityType')
->setConstructorArgs([
[
'id' => 'entity_test',
'entity_keys' => [
'id' => 'id',
'revision' => 'revision_id',
'langcode' => 'langcode',
],
],
])
->setMethods(['getRevisionMetadataKeys'])
->getMock();
$this->entityType->expects($this->any())
->method('getRevisionMetadataKeys')
->will($this->returnValue([]));
$this->storage->expects($this->exactly(3))
->method('getRevisionTable')
@@ -652,7 +679,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
'langcode' => [
'type' => 'varchar',
'not null' => TRUE,
]
],
],
'primary key' => ['id'],
'unique keys' => [
@@ -788,6 +815,9 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
$this->storage->expects($this->any())
->method('getTableMapping')
->will($this->returnValue($table_mapping));
$this->storage->expects($this->any())
->method('getCustomTableMapping')
->will($this->returnValue($table_mapping));
$this->storageSchema->onEntityTypeCreate($this->entityType);
}
@@ -835,7 +865,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
'color' => [
'table' => 'color',
'columns' => [
'color' => 'id'
'color' => 'id',
],
],
],
@@ -1002,7 +1032,7 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
'color' => [
'table' => 'color',
'columns' => [
'color' => 'id'
'color' => 'id',
],
],
],
@@ -1285,6 +1315,9 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
$this->storage->expects($this->any())
->method('getTableMapping')
->will($this->returnValue($table_mapping));
$this->storage->expects($this->any())
->method('getCustomTableMapping')
->will($this->returnValue($table_mapping));
// Setup storage schema.
if ($change_schema) {
@@ -1469,6 +1502,9 @@ class SqlContentEntityStorageSchemaTest extends UnitTestCase {
$this->storage->expects($this->any())
->method('getTableMapping')
->will($this->returnValue($table_mapping));
$this->storage->expects($this->any())
->method('getCustomTableMapping')
->will($this->returnValue($table_mapping));
$this->storageSchema->expects($this->any())
->method('loadEntitySchemaData')
@@ -8,12 +8,14 @@
namespace Drupal\Tests\Core\Entity\Sql;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\MemoryCache\MemoryCache;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryFactoryInterface;
use Drupal\Core\Entity\Sql\DefaultTableMapping;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Language\Language;
use Drupal\Tests\UnitTestCase;
@@ -199,12 +201,15 @@ class SqlContentEntityStorageTest extends UnitTestCase {
* @dataProvider providerTestGetRevisionTable
*/
public function testGetRevisionTable($revision_table, $expected) {
$this->entityType->expects($this->once())
$this->entityType->expects($this->any())
->method('isRevisionable')
->will($this->returnValue(TRUE));
$this->entityType->expects($this->once())
->method('getRevisionTable')
->will($this->returnValue($revision_table));
$this->entityType->expects($this->any())
->method('getRevisionMetadataKeys')
->willReturn([]);
$this->setUpEntityStorage();
@@ -237,12 +242,15 @@ class SqlContentEntityStorageTest extends UnitTestCase {
* @covers ::getDataTable
*/
public function testGetDataTable() {
$this->entityType->expects($this->once())
$this->entityType->expects($this->any())
->method('isTranslatable')
->will($this->returnValue(TRUE));
$this->entityType->expects($this->exactly(1))
->method('getDataTable')
->will($this->returnValue('entity_test_field_data'));
$this->entityType->expects($this->any())
->method('getRevisionMetadataKeys')
->willReturn([]);
$this->setUpEntityStorage();
@@ -264,10 +272,10 @@ class SqlContentEntityStorageTest extends UnitTestCase {
* @dataProvider providerTestGetRevisionDataTable
*/
public function testGetRevisionDataTable($revision_data_table, $expected) {
$this->entityType->expects($this->once())
$this->entityType->expects($this->any())
->method('isRevisionable')
->will($this->returnValue(TRUE));
$this->entityType->expects($this->once())
$this->entityType->expects($this->any())
->method('isTranslatable')
->will($this->returnValue(TRUE));
$this->entityType->expects($this->exactly(1))
@@ -276,6 +284,9 @@ class SqlContentEntityStorageTest extends UnitTestCase {
$this->entityType->expects($this->once())
->method('getRevisionDataTable')
->will($this->returnValue($revision_data_table));
$this->entityType->expects($this->any())
->method('getRevisionMetadataKeys')
->willReturn([]);
$this->setUpEntityStorage();
@@ -302,6 +313,51 @@ class SqlContentEntityStorageTest extends UnitTestCase {
];
}
/**
* Tests that setting a new table mapping also updates the table names.
*
* @covers ::setTableMapping
*/
public function testSetTableMapping() {
$this->entityType->expects($this->any())
->method('isRevisionable')
->will($this->returnValue(FALSE));
$this->entityType->expects($this->any())
->method('isTranslatable')
->will($this->returnValue(FALSE));
$this->entityType->expects($this->any())
->method('getRevisionMetadataKeys')
->willReturn([]);
$this->setUpEntityStorage();
$this->assertSame('entity_test', $this->entityStorage->getBaseTable());
$this->assertNull($this->entityStorage->getRevisionTable());
$this->assertNull($this->entityStorage->getDataTable());
$this->assertNull($this->entityStorage->getRevisionDataTable());
// Change the entity type definition and instantiate a new table mapping
// with it.
$updated_entity_type = $this->createMock('Drupal\Core\Entity\ContentEntityTypeInterface');
$updated_entity_type->expects($this->any())
->method('id')
->will($this->returnValue($this->entityTypeId));
$updated_entity_type->expects($this->any())
->method('isRevisionable')
->will($this->returnValue(TRUE));
$updated_entity_type->expects($this->any())
->method('isTranslatable')
->will($this->returnValue(TRUE));
$table_mapping = new DefaultTableMapping($updated_entity_type, []);
$this->entityStorage->setTableMapping($table_mapping);
$this->assertSame('entity_test', $this->entityStorage->getBaseTable());
$this->assertSame('entity_test_revision', $this->entityStorage->getRevisionTable());
$this->assertSame('entity_test_field_data', $this->entityStorage->getDataTable());
$this->assertSame('entity_test_field_revision', $this->entityStorage->getRevisionDataTable());
}
/**
* Tests ContentEntityDatabaseStorage::onEntityTypeCreate().
*
@@ -369,7 +425,7 @@ class SqlContentEntityStorageTest extends UnitTestCase {
->will($this->returnValue($schema_handler));
$storage = $this->getMockBuilder('Drupal\Core\Entity\Sql\SqlContentEntityStorage')
->setConstructorArgs([$this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager])
->setConstructorArgs([$this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager, new MemoryCache()])
->setMethods(['getStorageSchema'])
->getMock();
@@ -533,7 +589,7 @@ class SqlContentEntityStorageTest extends UnitTestCase {
'uuid' => $entity_keys['uuid'],
];
$this->entityType->expects($this->exactly(2))
$this->entityType->expects($this->exactly(4))
->method('isRevisionable')
->will($this->returnValue(TRUE));
$this->entityType->expects($this->any())
@@ -606,7 +662,7 @@ class SqlContentEntityStorageTest extends UnitTestCase {
$field_names = array_merge($field_names, $revisionable_field_names);
$this->fieldDefinitions += $this->mockFieldDefinitions(array_merge($revisionable_field_names, array_values($revision_metadata_field_names)), ['isRevisionable' => TRUE]);
$this->entityType->expects($this->exactly(2))
$this->entityType->expects($this->exactly(4))
->method('isRevisionable')
->will($this->returnValue(TRUE));
$this->entityType->expects($this->any())
@@ -781,7 +837,7 @@ class SqlContentEntityStorageTest extends UnitTestCase {
$revision_metadata_keys = [
'revision_created' => 'revision_timestamp',
'revision_user' => 'revision_uid',
'revision_log_message' => 'revision_log'
'revision_log_message' => 'revision_log',
];
$this->entityType->expects($this->atLeastOnce())
@@ -1114,7 +1170,7 @@ class SqlContentEntityStorageTest extends UnitTestCase {
->method('getBaseFieldDefinitions')
->will($this->returnValue($this->fieldDefinitions));
$this->entityStorage = new SqlContentEntityStorage($this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager);
$this->entityStorage = new SqlContentEntityStorage($this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager, new MemoryCache());
}
/**
@@ -1189,11 +1245,13 @@ class SqlContentEntityStorageTest extends UnitTestCase {
->method('set');
$entity_storage = $this->getMockBuilder('Drupal\Core\Entity\Sql\SqlContentEntityStorage')
->setConstructorArgs([$this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager])
->setMethods(['getFromStorage', 'invokeStorageLoadHook'])
->setConstructorArgs([$this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager, new MemoryCache()])
->setMethods(['getFromStorage', 'invokeStorageLoadHook', 'initTableLayout'])
->getMock();
$entity_storage->method('invokeStorageLoadHook')
->willReturn(NULL);
$entity_storage->method('initTableLayout')
->willReturn(NULL);
$entity_storage->expects($this->once())
->method('getFromStorage')
->with([$id])
@@ -1241,11 +1299,13 @@ class SqlContentEntityStorageTest extends UnitTestCase {
->with($key, $entity, CacheBackendInterface::CACHE_PERMANENT, [$this->entityTypeId . '_values', 'entity_field_info']);
$entity_storage = $this->getMockBuilder('Drupal\Core\Entity\Sql\SqlContentEntityStorage')
->setConstructorArgs([$this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager])
->setMethods(['getFromStorage', 'invokeStorageLoadHook'])
->setConstructorArgs([$this->entityType, $this->connection, $this->entityManager, $this->cache, $this->languageManager, new MemoryCache()])
->setMethods(['getFromStorage', 'invokeStorageLoadHook', 'initTableLayout'])
->getMock();
$entity_storage->method('invokeStorageLoadHook')
->willReturn(NULL);
$entity_storage->method('initTableLayout')
->willReturn(NULL);
$entity_storage->expects($this->once())
->method('getFromStorage')
->with([$id])
@@ -1296,7 +1356,7 @@ class SqlContentEntityStorageTest extends UnitTestCase {
->method('getBaseFieldDefinitions')
->will($this->returnValue($this->fieldDefinitions));
$this->entityStorage = new SqlContentEntityStorage($this->entityType, $database, $this->entityManager, $this->cache, $this->languageManager);
$this->entityStorage = new SqlContentEntityStorage($this->entityType, $database, $this->entityManager, $this->cache, $this->languageManager, new MemoryCache());
$result = $this->entityStorage->hasData();
@@ -1380,7 +1440,7 @@ class SqlContentEntityStorageTest extends UnitTestCase {
->method('getImplementations')
->will($this->returnValueMap([
['entity_load', []],
[$this->entityTypeId . '_load', []]
[$this->entityTypeId . '_load', []],
]));
$this->container->set('module_handler', $this->moduleHandler);
@@ -35,13 +35,6 @@ class EntityAdapterUnitTest extends UnitTestCase {
*/
protected $entity;
/**
* The config entity used for testing.
*
* @var \Drupal\Core\Entity\ConfigtEntityBase|\PHPUnit_Framework_MockObject_MockObject
*/
protected $configEntity;
/**
* The content entity adapter under test.
*
@@ -49,13 +42,6 @@ class EntityAdapterUnitTest extends UnitTestCase {
*/
protected $entityAdapter;
/**
* The config entity adapter under test.
*
* @var \Drupal\Core\Entity\Plugin\DataType\EntityAdapter
*/
protected $configEntityAdapter;
/**
* The entity type used for testing.
*
@@ -242,10 +228,6 @@ class EntityAdapterUnitTest extends UnitTestCase {
$this->entity = $this->getMockForAbstractClass('\Drupal\Core\Entity\ContentEntityBase', [$values, $this->entityTypeId, $this->bundle]);
$this->entityAdapter = EntityAdapter::createFromEntity($this->entity);
$this->configEntity = $this->getMockForAbstractClass('\Drupal\Core\Config\Entity\ConfigEntityBase', [$values, $this->entityTypeId, $this->bundle]);
$this->configEntityAdapter = EntityAdapter::createFromEntity($this->configEntity);
}
/**
@@ -455,11 +437,6 @@ class EntityAdapterUnitTest extends UnitTestCase {
$this->entityAdapter->setValue(NULL);
$this->assertEquals(new \ArrayIterator([]), $this->entityAdapter->getIterator());
// Config entity test.
$iterator = $this->configEntityAdapter->getIterator();
$this->configEntityAdapter->setValue(NULL);
$this->assertEquals(new \ArrayIterator([]), $this->entityAdapter->getIterator());
}
}
@@ -83,7 +83,7 @@ class EntityReferenceSelectionUnitTest extends UnitTestCase {
'bar' => 'bar value',
'baz' => 'baz value',
],
]
],
],
],
[
@@ -96,7 +96,7 @@ class EntityReferenceSelectionUnitTest extends UnitTestCase {
'handler_settings' => [
// Same setting from root level takes precedence.
'setting2' => 'this will be overwritten',
]
],
],
],
];
@@ -238,6 +238,19 @@ class ActiveLinkResponseFilterTest extends UnitTestCase {
$situations[] = ['context' => $context, 'is active' => FALSE, 'attributes' => $attributes + ['hreflang' => 'en', 'data-drupal-link-query' => ""]];
$situations[] = ['context' => $context, 'is active' => FALSE, 'attributes' => $attributes + ['hreflang' => 'en', 'data-drupal-link-query' => TRUE]];
// Query with unsorted keys must match when the attribute is in sorted form.
$context = [
'path' => 'myfrontpage',
'front' => TRUE,
'language' => 'en',
'query' => ['foo' => 'bar', 'baz' => 'qux'],
];
$attributes = [
'data-drupal-link-system-path' => 'myfrontpage',
'data-drupal-link-query' => Json::encode(['baz' => 'qux', 'foo' => 'bar']),
];
$situations[] = ['context' => $context, 'is active' => TRUE, 'attributes' => $attributes];
// Loop over the surrounding HTML variations.
$data = [];
for ($h = 0; $h < count($html); $h++) {
@@ -43,11 +43,11 @@ class ExceptionJsonSubscriberTest extends UnitTestCase {
return [
'uncacheable exception' => [
new MethodNotAllowedHttpException(['POST', 'PUT'], 'test message'),
JsonResponse::class
JsonResponse::class,
],
'cacheable exception' => [
new CacheableMethodNotAllowedHttpException((new CacheableMetadata())->setCacheContexts(['route']), ['POST', 'PUT'], 'test message'),
CacheableJsonResponse::class
CacheableJsonResponse::class,
],
];
}
@@ -54,7 +54,6 @@ class PsrResponseSubscriberTest extends UnitTestCase {
$this->psrResponseSubscriber->onKernelView($event);
}
/**
* Tests altering and finished event.
*
@@ -116,7 +116,7 @@ RSS;
Request::create('/'),
'foo',
new Response($content, 200, [
'Content-Type' => 'application/rss+xml'
'Content-Type' => 'application/rss+xml',
])
);
@@ -0,0 +1,291 @@
<?php
namespace Drupal\Tests\Core\Extension;
use Drupal\Component\Serialization\Yaml;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ExtensionDiscovery;
use Drupal\Core\Extension\ExtensionList;
use Drupal\Core\Extension\InfoParserInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\Exception\UnknownExtensionException;
use Drupal\Core\State\StateInterface;
use Drupal\Tests\UnitTestCase;
use org\bovigo\vfs\vfsStream;
use Prophecy\Argument;
/**
* @coversDefaultClass \Drupal\Core\Extension\ExtensionList
* @group Extension
*/
class ExtensionListTest extends UnitTestCase {
/**
* @covers ::getName
*/
public function testGetNameWithNonExistingExtension() {
list($cache, $info_parser, $module_handler, $state) = $this->getMocks();
$test_extension_list = new TestExtension($this->root, 'test_extension', $cache->reveal(), $info_parser->reveal(), $module_handler->reveal(), $state->reveal(), 'testing');
$extension_discovery = $this->prophesize(ExtensionDiscovery::class);
$extension_discovery->scan('test_extension')->willReturn([]);
$test_extension_list->setExtensionDiscovery($extension_discovery->reveal());
$this->setExpectedException(UnknownExtensionException::class);
$test_extension_list->getName('test_name');
}
/**
* @covers ::getName
*/
public function testGetName() {
$test_extension_list = $this->setupTestExtensionList();
$this->assertEquals('test name', $test_extension_list->getName('test_name'));
}
/**
* @covers ::get
*/
public function testGetWithNonExistingExtension() {
list($cache, $info_parser, $module_handler, $state) = $this->getMocks();
$test_extension_list = new TestExtension($this->root, 'test_extension', $cache->reveal(), $info_parser->reveal(), $module_handler->reveal(), $state->reveal(), 'testing');
$extension_discovery = $this->prophesize(ExtensionDiscovery::class);
$extension_discovery->scan('test_extension')->willReturn([]);
$test_extension_list->setExtensionDiscovery($extension_discovery->reveal());
$this->setExpectedException(UnknownExtensionException::class);
$test_extension_list->get('test_name');
}
/**
* @covers ::get
*/
public function testGet() {
$test_extension_list = $this->setupTestExtensionList();
$extension = $test_extension_list->get('test_name');
$this->assertInstanceOf(Extension::class, $extension);
$this->assertEquals('test_name', $extension->getName());
}
/**
* @covers ::getList
*/
public function testGetList() {
$test_extension_list = $this->setupTestExtensionList();
$extensions = $test_extension_list->getList();
$this->assertCount(1, $extensions);
$this->assertEquals('test_name', $extensions['test_name']->getName());
}
/**
* @covers ::getExtensionInfo
* @covers ::getAllInstalledInfo
*/
public function testGetExtensionInfo() {
$test_extension_list = $this->setupTestExtensionList();
$test_extension_list->setInstalledExtensions(['test_name']);
$info = $test_extension_list->getExtensionInfo('test_name');
$this->assertEquals([
'type' => 'test_extension',
'core' => '8.x',
'name' => 'test name',
'mtime' => 123456789,
], $info);
}
/**
* @covers ::getAllAvailableInfo
*/
public function testGetAllAvailableInfo() {
$test_extension_list = $this->setupTestExtensionList();
$infos = $test_extension_list->getAllAvailableInfo();
$this->assertEquals([
'test_name' => [
'type' => 'test_extension',
'core' => '8.x',
'name' => 'test name',
'mtime' => 123456789,
],
], $infos);
}
/**
* @covers ::getAllInstalledInfo
*/
public function testGetAllInstalledInfo() {
$test_extension_list = $this->setupTestExtensionList(['test_name', 'test_name_2']);
$test_extension_list->setInstalledExtensions(['test_name_2']);
$infos = $test_extension_list->getAllInstalledInfo();
$this->assertEquals([
'test_name_2' => [
'type' => 'test_extension',
'core' => '8.x',
'name' => 'test name',
'mtime' => 123456789,
],
], $infos);
}
/**
* @covers ::getPathnames
*/
public function testGetPathnames() {
$test_extension_list = $this->setupTestExtensionList();
$filenames = $test_extension_list->getPathnames();
$this->assertEquals([
'test_name' => 'vfs://drupal_root/example/test_name/test_name.info.yml',
], $filenames);
}
/**
* @covers ::getPathname
*/
public function testGetPathname() {
$test_extension_list = $this->setupTestExtensionList();
$pathname = $test_extension_list->getPathname('test_name');
$this->assertEquals('vfs://drupal_root/example/test_name/test_name.info.yml', $pathname);
}
/**
* @covers ::setPathname
* @covers ::getPathname
*/
public function testSetPathname() {
$test_extension_list = $this->setupTestExtensionList();
$test_extension_list->setPathname('test_name', 'vfs://drupal_root/example2/test_name/test_name.info.yml');
$this->assertEquals('vfs://drupal_root/example2/test_name/test_name.info.yml', $test_extension_list->getPathname('test_name'));
}
/**
* @covers ::getPath
*/
public function testGetPath() {
$test_extension_list = $this->setupTestExtensionList();
$path = $test_extension_list->getPath('test_name');
$this->assertEquals('vfs://drupal_root/example/test_name', $path);
}
/**
* @covers ::reset
*/
public function testReset() {
$test_extension_list = $this->setupTestExtensionList();
$path = $test_extension_list->getPath('test_name');
$this->assertEquals('vfs://drupal_root/example/test_name', $path);
$pathname = $test_extension_list->getPathname('test_name');
$this->assertEquals('vfs://drupal_root/example/test_name/test_name.info.yml', $pathname);
$filenames = $test_extension_list->getPathnames();
$this->assertEquals([
'test_name' => 'vfs://drupal_root/example/test_name/test_name.info.yml',
], $filenames);
$test_extension_list->reset();
// Ensure that everything is still usable after the resetting.
$path = $test_extension_list->getPath('test_name');
$this->assertEquals('vfs://drupal_root/example/test_name', $path);
$pathname = $test_extension_list->getPathname('test_name');
$this->assertEquals('vfs://drupal_root/example/test_name/test_name.info.yml', $pathname);
$filenames = $test_extension_list->getPathnames();
$this->assertEquals([
'test_name' => 'vfs://drupal_root/example/test_name/test_name.info.yml',
], $filenames);
}
/**
* @return \Drupal\Tests\Core\Extension\TestExtension
*/
protected function setupTestExtensionList($extension_names = ['test_name']) {
vfsStream::setup('drupal_root');
$folders = ['example' => []];
foreach ($extension_names as $extension_name) {
$folders['example'][$extension_name][$extension_name . '.info.yml'] = Yaml::encode([
'name' => 'test name',
'type' => 'test_extension',
'core' => '8.x',
]);
}
vfsStream::create($folders);
foreach ($extension_names as $extension_name) {
touch("vfs://drupal_root/example/$extension_name/$extension_name.info.yml", 123456789);
}
list($cache, $info_parser, $module_handler, $state) = $this->getMocks();
$info_parser->parse(Argument::any())->will(function ($args) {
return Yaml::decode(file_get_contents($args[0]));
});
$test_extension_list = new TestExtension('vfs://drupal_root', 'test_extension', $cache->reveal(), $info_parser->reveal(), $module_handler->reveal(), $state->reveal(), 'testing');
$extension_discovery = $this->prophesize(ExtensionDiscovery::class);
$extension_scan_result = [];
foreach ($extension_names as $extension_name) {
$extension_scan_result[$extension_name] = new Extension($this->root, 'test_extension', "vfs://drupal_root/example/$extension_name/$extension_name.info.yml");
}
$extension_discovery->scan('test_extension')->willReturn($extension_scan_result);
$test_extension_list->setExtensionDiscovery($extension_discovery->reveal());
return $test_extension_list;
}
protected function getMocks() {
$cache = $this->prophesize(CacheBackendInterface::class);
$info_parser = $this->prophesize(InfoParserInterface::class);
$module_handler = $this->prophesize(ModuleHandlerInterface::class);
$state = $this->prophesize(StateInterface::class);
return [$cache, $info_parser, $module_handler, $state];
}
}
class TestExtension extends ExtensionList {
/**
* @var string[]
*/
protected $installedExtensions = [];
/**
* @var \Drupal\Core\Extension\ExtensionDiscovery|null
*/
protected $extensionDiscovery;
/**
* @param \Drupal\Core\Extension\ExtensionDiscovery $extension_discovery
*/
public function setExtensionDiscovery(ExtensionDiscovery $extension_discovery) {
$this->extensionDiscovery = $extension_discovery;
}
public function setInstalledExtensions(array $extension_names) {
$this->installedExtensions = $extension_names;
}
/**
* {@inheritdoc}
*/
protected function getInstalledExtensionNames() {
return $this->installedExtensions;
}
/**
* {@inheritdoc}
*/
protected function getExtensionDiscovery() {
return $this->extensionDiscovery ?: parent::getExtensionDiscovery();
}
}
@@ -5,6 +5,7 @@ namespace Drupal\Tests\Core\Extension;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\Extension;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\Core\Extension\Exception\UnknownExtensionException;
use Drupal\Tests\UnitTestCase;
/**
@@ -52,7 +53,7 @@ class ModuleHandlerTest extends UnitTestCase {
'type' => 'module',
'pathname' => 'core/tests/Drupal/Tests/Core/Extension/modules/module_handler_test/module_handler_test.info.yml',
'filename' => 'module_handler_test.module',
]
],
], $this->cacheBackend);
return $module_handler;
}
@@ -107,8 +108,8 @@ class ModuleHandlerTest extends UnitTestCase {
'type' => 'module',
'pathname' => 'core/tests/Drupal/Tests/Core/Extension/modules/module_handler_test/module_handler_test.info.yml',
'filename' => 'module_handler_test.module',
]
], $this->cacheBackend
],
], $this->cacheBackend,
])
->setMethods(['load'])
->getMock();
@@ -164,7 +165,7 @@ class ModuleHandlerTest extends UnitTestCase {
* @covers ::getModule
*/
public function testGetModuleWithNonExistingModule() {
$this->setExpectedException(\InvalidArgumentException::class);
$this->setExpectedException(UnknownExtensionException::class);
$this->getModuleHandler()->getModule('claire_alice_watch_my_little_pony_module_that_does_not_exist');
}
@@ -177,7 +178,7 @@ class ModuleHandlerTest extends UnitTestCase {
$fixture_module_handler = $this->getModuleHandler();
$module_handler = $this->getMockBuilder(ModuleHandler::class)
->setConstructorArgs([
$this->root, [], $this->cacheBackend
$this->root, [], $this->cacheBackend,
])
->setMethods(['resetImplementations'])
->getMock();
@@ -205,7 +206,7 @@ class ModuleHandlerTest extends UnitTestCase {
$module_handler = $this->getMockBuilder(ModuleHandler::class)
->setConstructorArgs([
$this->root, [], $this->cacheBackend
$this->root, [], $this->cacheBackend,
])
->setMethods(['resetImplementations'])
->getMock();
@@ -227,7 +228,7 @@ class ModuleHandlerTest extends UnitTestCase {
$module_handler = $this->getMockBuilder(ModuleHandler::class)
->setConstructorArgs([
$this->root, [], $this->cacheBackend
$this->root, [], $this->cacheBackend,
])
->setMethods(['resetImplementations'])
->getMock();
@@ -264,8 +265,8 @@ class ModuleHandlerTest extends UnitTestCase {
'type' => 'module',
'pathname' => 'core/tests/Drupal/Tests/Core/Extension/modules/module_handler_test/module_handler_test.info.yml',
'filename' => 'module_handler_test.module',
]
], $this->cacheBackend
],
], $this->cacheBackend,
])
->setMethods(['loadInclude'])
->getMock();
@@ -353,8 +354,8 @@ class ModuleHandlerTest extends UnitTestCase {
'type' => 'module',
'pathname' => 'core/tests/Drupal/Tests/Core/Extension/modules/module_handler_test/module_handler_test.info.yml',
'filename' => 'module_handler_test.module',
]
], $this->cacheBackend
],
], $this->cacheBackend,
])
->setMethods(['buildImplementationInfo', 'loadInclude'])
->getMock();
@@ -391,8 +392,8 @@ class ModuleHandlerTest extends UnitTestCase {
'type' => 'module',
'pathname' => 'core/tests/Drupal/Tests/Core/Extension/modules/module_handler_test/module_handler_test.info.yml',
'filename' => 'module_handler_test.module',
]
], $this->cacheBackend
],
], $this->cacheBackend,
])
->setMethods(['buildImplementationInfo'])
->getMock();
@@ -65,8 +65,8 @@ abstract class BaseFieldDefinitionTestBase extends UnitTestCase {
/**
* Returns the module name and the module directory for the plugin.
*
* drupal_get_path() cannot be used here, because it is not available in
* Drupal PHPUnit tests.
* Function drupal_get_path() cannot be used here, because it is not available
* in Drupal PHPUnit tests.
*
* @return array
* A one-dimensional array containing the following strings:
@@ -232,7 +232,6 @@ class FieldDefinitionListenerTest extends UnitTestCase {
$this->fieldDefinitionListener->onFieldDefinitionDelete($field_definition->reveal());
}
/**
* @covers ::onFieldDefinitionDelete
*/
@@ -0,0 +1,100 @@
<?php
namespace Drupal\Tests\Core\Field;
use Drupal\Core\Field\FieldInputValueNormalizerTrait;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\Core\Field\FieldInputValueNormalizerTrait
* @group Field
*/
class FieldInputValueNormalizerTraitTest extends UnitTestCase {
use FieldInputValueNormalizerTrait;
/**
* @dataProvider keyValueByDeltaTestCases
* @covers ::normalizeValue
*/
public function testKeyValueByDelta($input_value, $expected_value, $main_property_name = 'value') {
$this->assertEquals($expected_value, $this->normalizeValue($input_value, $main_property_name));
}
/**
* Test cases for ::testKeyValueByDelta.
*/
public function keyValueByDeltaTestCases() {
return [
'Integer' => [
1,
[['value' => 1]],
],
'Falsey integer' => [
0,
[['value' => 0]],
],
'String' => [
'foo',
[['value' => 'foo']],
],
'Empty string' => [
'',
[['value' => '']],
],
'Null' => [
NULL,
[],
],
'Empty field value' => [
[],
[],
],
'Single delta' => [
['value' => 'foo'],
[['value' => 'foo']],
],
'Keyed delta' => [
[['value' => 'foo']],
[['value' => 'foo']],
],
'Multiple keyed deltas' => [
[['value' => 'foo'], ['value' => 'bar']],
[['value' => 'foo'], ['value' => 'bar']],
],
'No main property with keyed delta' => [
[['foo' => 'bar']],
[['foo' => 'bar']],
NULL,
],
'No main property with single delta' => [
['foo' => 'bar'],
[['foo' => 'bar']],
NULL,
],
'No main property with empty array' => [
[],
[],
NULL,
],
];
}
/**
* @covers ::normalizeValue
*/
public function testScalarWithNoMainProperty() {
$this->setExpectedException(\InvalidArgumentException::class, 'A main property is required when normalizing scalar field values.');
$value = 'foo';
$this->normalizeValue($value, NULL);
}
/**
* @covers ::normalizeValue
*/
public function testKeyValueByDeltaUndefinedVariables() {
$this->assertEquals([], $this->normalizeValue($undefined_variable, 'value'));
$this->assertEquals([], $this->normalizeValue($undefined_variable['undefined_key'], 'value'));
}
}
@@ -6,6 +6,8 @@ use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Field\FieldTypePluginManagerInterface;
use Drupal\Core\Form\FormState;
use Drupal\Tests\UnitTestCase;
@@ -136,6 +138,71 @@ class FieldItemListTest extends UnitTestCase {
return $datasets;
}
/**
* Tests identical behavior of ::hasAffectingChanges with ::equals.
*
* @covers ::hasAffectingChanges
*
* @dataProvider providerTestEquals
*/
public function testHasAffectingChanges($expected, FieldItemInterface $first_field_item = NULL, FieldItemInterface $second_field_item = NULL) {
// Mock the field type manager and place it in the container.
$field_type_manager = $this->createMock(FieldTypePluginManagerInterface::class);
$container = new ContainerBuilder();
$container->set('plugin.manager.field.field_type', $field_type_manager);
\Drupal::setContainer($container);
$field_storage_definition = $this->createMock(FieldStorageDefinitionInterface::class);
$field_storage_definition->expects($this->any())
->method('getColumns')
->willReturn([0 => '0', 1 => '1']);
// Set up three properties, one of them being computed.
$property_definitions['0'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['0']->expects($this->any())
->method('isComputed')
->willReturn(FALSE);
$property_definitions['1'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['1']->expects($this->any())
->method('isComputed')
->willReturn(FALSE);
$property_definitions['2'] = $this->getMock('Drupal\Core\TypedData\DataDefinitionInterface');
$property_definitions['2']->expects($this->any())
->method('isComputed')
->willReturn(TRUE);
$field_storage_definition = $this->getMock('Drupal\Core\Field\FieldStorageDefinitionInterface');
$field_storage_definition->expects($this->any())
->method('getPropertyDefinitions')
->will($this->returnValue($property_definitions));
$field_definition = $this->createMock(FieldDefinitionInterface::class);
$field_definition->expects($this->any())
->method('getFieldStorageDefinition')
->willReturn($field_storage_definition);
$field_definition->expects($this->any())
->method('isComputed')
->willReturn(FALSE);
$field_list_a = new FieldItemList($field_definition);
$field_list_b = new FieldItemList($field_definition);
// Set up the mocking necessary for creating field items.
$field_type_manager->expects($this->any())
->method('createFieldItem')
->willReturnOnConsecutiveCalls($first_field_item, $second_field_item);
// Set the field item values.
if ($first_field_item instanceof FieldItemInterface) {
$field_list_a->setValue($first_field_item);
}
if ($second_field_item instanceof FieldItemInterface) {
$field_list_b->setValue($second_field_item);
}
$this->assertEquals($expected, !$field_list_a->hasAffectingChanges($field_list_b, ''));
}
/**
* @covers ::equals
*/
@@ -15,7 +15,7 @@ use org\bovigo\vfs\vfsStream;
class FileSystemTest extends UnitTestCase {
/**
* @var \Drupal\Core\File\FileSystem
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
@@ -119,7 +119,7 @@ class FileSystemTest extends UnitTestCase {
$data[] = [
'public://dir/test.txt',
'test',
'.txt'
'.txt',
];
return $data;
}
@@ -19,7 +19,7 @@ class ConfigFormBaseTraitTest extends UnitTestCase {
// Set up some configuration in a mocked config factory.
$trait->configFactory = $this->getConfigFactoryStub([
'editable.config' => [],
'immutable.config' => []
'immutable.config' => [],
]);
$trait->expects($this->any())
@@ -8,6 +8,7 @@ use Drupal\Core\Form\Exception\BrokenPostRequestException;
use Drupal\Core\Form\FormAjaxException;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -43,6 +44,13 @@ class FormAjaxSubscriberTest extends UnitTestCase {
*/
protected $stringTranslation;
/**
* The mocked messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $messenger;
/**
* {@inheritdoc}
*/
@@ -52,7 +60,8 @@ class FormAjaxSubscriberTest extends UnitTestCase {
$this->httpKernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$this->formAjaxResponseBuilder = $this->getMock('Drupal\Core\Form\FormAjaxResponseBuilderInterface');
$this->stringTranslation = $this->getStringTranslationStub();
$this->subscriber = new FormAjaxSubscriber($this->formAjaxResponseBuilder, $this->stringTranslation);
$this->messenger = $this->createMock(MessengerInterface::class);
$this->subscriber = new FormAjaxSubscriber($this->formAjaxResponseBuilder, $this->stringTranslation, $this->messenger);
}
/**
@@ -147,13 +156,19 @@ class FormAjaxSubscriberTest extends UnitTestCase {
public function testOnExceptionBrokenPostRequest() {
$this->formAjaxResponseBuilder->expects($this->never())
->method('buildResponse');
$this->messenger->expects($this->once())
->method('addError');
$this->subscriber = $this->getMockBuilder('\Drupal\Core\Form\EventSubscriber\FormAjaxSubscriber')
->setConstructorArgs([$this->formAjaxResponseBuilder, $this->getStringTranslationStub()])
->setMethods(['drupalSetMessage', 'formatSize'])
->setConstructorArgs([
$this->formAjaxResponseBuilder,
$this->getStringTranslationStub(),
$this->messenger,
])
->setMethods(['formatSize'])
->getMock();
$this->subscriber->expects($this->once())
->method('drupalSetMessage')
->willReturn('asdf');
$this->subscriber->expects($this->once())
->method('formatSize')
->with(32 * 1e6)
@@ -86,7 +86,7 @@ class FormAjaxResponseBuilderTest extends UnitTestCase {
'#ajax' => [
'callback' => function (array $form, FormStateInterface $form_state) {
return $form['test'];
}
},
],
];
$request = new Request();
@@ -117,7 +117,7 @@ class FormAjaxResponseBuilderTest extends UnitTestCase {
'#ajax' => [
'callback' => function (array $form, FormStateInterface $form_state) {
return new AjaxResponse([]);
}
},
],
];
$request = new Request();
@@ -142,7 +142,7 @@ class FormAjaxResponseBuilderTest extends UnitTestCase {
'#ajax' => [
'callback' => function (array $form, FormStateInterface $form_state) {
return new AjaxResponse([]);
}
},
],
];
$request = new Request();
@@ -175,7 +175,7 @@ class FormAjaxResponseBuilderTest extends UnitTestCase {
'#ajax' => [
'callback' => function (array $form, FormStateInterface $form_state) {
return new AjaxResponse([]);
}
},
],
];
$request = new Request();
@@ -881,6 +881,7 @@ class FormBuilderTest extends FormTestBase {
}
class TestForm implements FormInterface {
public function getFormId() {
return 'test_form';
}
@@ -888,11 +889,14 @@ class TestForm implements FormInterface {
public function buildForm(array $form, FormStateInterface $form_state) {
return test_form_id();
}
public function validateForm(array &$form, FormStateInterface $form_state) {}
public function submitForm(array &$form, FormStateInterface $form_state) {}
}
class TestFormInjected extends TestForm implements ContainerInjectionInterface {
public static function create(ContainerInterface $container) {
return new static();
}
@@ -331,7 +331,7 @@ class FormCacheTest extends UnitTestCase {
public function testSetCacheWithForm() {
$form_build_id = 'the_form_build_id';
$form = [
'#form_id' => 'the_form_id'
'#form_id' => 'the_form_id',
];
$form_state = new FormState();
@@ -417,7 +417,6 @@ class FormCacheTest extends UnitTestCase {
$this->formCache->setCache($form_build_id, $form, $form_state);
}
/**
* @covers ::deleteCache
*/
@@ -3,6 +3,7 @@
namespace Drupal\Tests\Core\Form;
use Drupal\Core\Form\FormState;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Tests\UnitTestCase;
/**
@@ -11,32 +12,59 @@ use Drupal\Tests\UnitTestCase;
*/
class FormErrorHandlerTest extends UnitTestCase {
/**
* The form error handler.
*
* @var \Drupal\Core\Form\FormErrorHandler|\PHPUnit_Framework_MockObject_MockObject
*/
protected $formErrorHandler;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $messenger;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->messenger = $this->createMock(MessengerInterface::class);
$this->formErrorHandler = $this->getMockBuilder('Drupal\Core\Form\FormErrorHandler')
->setMethods(['messenger'])
->getMock();
$this->formErrorHandler->expects($this->atLeastOnce())
->method('messenger')
->willReturn($this->messenger);
}
/**
* @covers ::handleFormErrors
* @covers ::displayErrorMessages
*/
public function testDisplayErrorMessages() {
$form_error_handler = $this->getMockBuilder('Drupal\Core\Form\FormErrorHandler')
->setMethods(['drupalSetMessage'])
->getMock();
$form_error_handler->expects($this->at(0))
->method('drupalSetMessage')
$this->messenger->expects($this->at(0))
->method('addMessage')
->with('invalid', 'error');
$form_error_handler->expects($this->at(1))
->method('drupalSetMessage')
$this->messenger->expects($this->at(1))
->method('addMessage')
->with('invalid', 'error');
$form_error_handler->expects($this->at(2))
->method('drupalSetMessage')
$this->messenger->expects($this->at(2))
->method('addMessage')
->with('invalid', 'error');
$form_error_handler->expects($this->at(3))
->method('drupalSetMessage')
$this->messenger->expects($this->at(3))
->method('addMessage')
->with('no title given', 'error');
$form_error_handler->expects($this->at(4))
->method('drupalSetMessage')
$this->messenger->expects($this->at(4))
->method('addMessage')
->with('element is invisible', 'error');
$form_error_handler->expects($this->at(5))
->method('drupalSetMessage')
$this->messenger->expects($this->at(5))
->method('addMessage')
->with('this missing element is invalid', 'error');
$form = [
@@ -88,7 +116,7 @@ class FormErrorHandlerTest extends UnitTestCase {
$form_state->setErrorByName('test5', 'no title given');
$form_state->setErrorByName('test6', 'element is invisible');
$form_state->setErrorByName('missing_element', 'this missing element is invalid');
$form_error_handler->handleFormErrors($form, $form_state);
$this->formErrorHandler->handleFormErrors($form, $form_state);
$this->assertSame('invalid', $form['test1']['#errors']);
}
@@ -97,10 +125,6 @@ class FormErrorHandlerTest extends UnitTestCase {
* @covers ::setElementErrorsFromFormState
*/
public function testSetElementErrorsFromFormState() {
$form_error_handler = $this->getMockBuilder('Drupal\Core\Form\FormErrorHandler')
->setMethods(['drupalSetMessage'])
->getMock();
$form = [
'#parents' => [],
'#array_parents' => [],
@@ -176,7 +200,7 @@ class FormErrorHandlerTest extends UnitTestCase {
$form_state->setErrorByName('grouping_test2', 'invalid');
$form_state->setErrorByName('fieldset][nested_test', 'invalid');
$form_state->setErrorByName('fieldset][nested_test2', 'invalid2');
$form_error_handler->handleFormErrors($form, $form_state);
$this->formErrorHandler->handleFormErrors($form, $form_state);
$this->assertSame('invalid', $form['test']['#errors']);
$this->assertSame([
'grouping_test' => 'invalid',
@@ -1119,6 +1119,7 @@ class FormStateDecoratorBaseTest extends UnitTestCase {
$this->assertSame($values, $this->formStateDecoratorBase->getValues());
}
/**
* @covers ::getValue
*/
@@ -1253,7 +1254,7 @@ class FormStateDecoratorBaseTest extends UnitTestCase {
public function testSetRedirect() {
$route_name = 'foo';
$route_parameters = [
'bar' => 'baz'
'bar' => 'baz',
];
$options = [
'qux' => 'foo',
@@ -434,12 +434,15 @@ class FormStateTest extends UnitTestCase {
* A test form used for the prepareCallback() tests.
*/
class PrepareCallbackTestForm implements FormInterface {
public function getFormId() {
return 'test_form';
}
public function buildForm(array $form, FormStateInterface $form_state) {}
public function validateForm(array &$form, FormStateInterface $form_state) {}
public function submitForm(array &$form, FormStateInterface $form_state) {}
}
@@ -135,7 +135,6 @@ class MailManagerTest extends UnitTestCase {
$this->assertInstanceOf('Drupal\Core\Mail\Plugin\Mail\TestMailCollector', $instance);
}
/**
* Tests that mails are sent in a separate render context.
*
@@ -163,6 +162,7 @@ class MailManagerTest extends UnitTestCase {
* Provides a testing version of MailManager with an empty constructor.
*/
class TestMailManager extends MailManager {
/**
* Sets the discovery for the manager.
*
@@ -13,8 +13,11 @@ use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultForbidden;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Controller\ControllerResolver;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Menu\LocalActionManager;
use Drupal\Core\Menu\LocalTaskManager;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\Session\AccountInterface;
@@ -22,7 +25,7 @@ use Drupal\Core\Url;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
/**
* @coversDefaultClass \Drupal\Core\Menu\LocalActionManager
@@ -31,11 +34,11 @@ use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
class LocalActionManagerTest extends UnitTestCase {
/**
* The mocked controller resolver.
* The mocked argument resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
* @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $controllerResolver;
protected $argumentResolver;
/**
* The mocked request.
@@ -104,7 +107,7 @@ class LocalActionManagerTest extends UnitTestCase {
* {@inheritdoc}
*/
protected function setUp() {
$this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
$this->argumentResolver = $this->getMock('\Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
$this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
@@ -120,7 +123,7 @@ class LocalActionManagerTest extends UnitTestCase {
$this->factory = $this->getMock('Drupal\Component\Plugin\Factory\FactoryInterface');
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$this->localActionManager = new TestLocalActionManager($this->controllerResolver, $this->request, $route_match, $this->routeProvider, $this->moduleHandler, $this->cacheBackend, $this->accessManager, $this->account, $this->discovery, $this->factory);
$this->localActionManager = new TestLocalActionManager($this->argumentResolver, $this->request, $route_match, $this->routeProvider, $this->moduleHandler, $this->cacheBackend, $this->accessManager, $this->account, $this->discovery, $this->factory);
}
/**
@@ -132,7 +135,7 @@ class LocalActionManagerTest extends UnitTestCase {
->method('getTitle')
->with('test');
$this->controllerResolver->expects($this->once())
$this->argumentResolver->expects($this->once())
->method('getArguments')
->with($this->request, [$local_action, 'getTitle'])
->will($this->returnValue(['test']));
@@ -161,7 +164,7 @@ class LocalActionManagerTest extends UnitTestCase {
$plugin->expects($this->any())
->method('getTitle')
->will($this->returnValue($plugin_definition['title']));
$this->controllerResolver->expects($this->any())
$this->argumentResolver->expects($this->any())
->method('getArguments')
->with($this->request, [$plugin, 'getTitle'])
->will($this->returnValue([]));
@@ -169,7 +172,7 @@ class LocalActionManagerTest extends UnitTestCase {
$plugin->expects($this->any())
->method('getWeight')
->will($this->returnValue($plugin_definition['weight']));
$this->controllerResolver->expects($this->any())
$this->argumentResolver->expects($this->any())
->method('getArguments')
->with($this->request, [$plugin, 'getTitle'])
->will($this->returnValue([]));
@@ -381,17 +384,37 @@ class LocalActionManagerTest extends UnitTestCase {
return $data;
}
/**
* @expectedDeprecation Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.
* @group legacy
*/
public function testControllerResolverDeprecation() {
$controller_resolver = $this->getMockBuilder(ControllerResolver::class)->disableOriginalConstructor()->getMock();
$route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
$request_stack = new RequestStack();
$request_stack->push($this->request);
$module_handler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$module_handler->expects($this->any())
->method('getModuleDirectories')
->willReturn([]);
$language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
$language_manager->expects($this->any())
->method('getCurrentLanguage')
->will($this->returnValue(new Language(['id' => 'en'])));
new LocalTaskManager($controller_resolver, $request_stack, $route_match, $this->routeProvider, $this->moduleHandler, $this->cacheBackend, $language_manager, $this->accessManager, $this->account);
}
}
class TestLocalActionManager extends LocalActionManager {
public function __construct(ControllerResolverInterface $controller_resolver, Request $request, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, AccessManagerInterface $access_manager, AccountInterface $account, DiscoveryInterface $discovery, FactoryInterface $factory) {
public function __construct(ArgumentResolverInterface $argument_resolver, Request $request, RouteMatchInterface $route_match, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache_backend, AccessManagerInterface $access_manager, AccountInterface $account, DiscoveryInterface $discovery, FactoryInterface $factory) {
$this->discovery = $discovery;
$this->factory = $factory;
$this->routeProvider = $route_provider;
$this->accessManager = $access_manager;
$this->account = $account;
$this->controllerResolver = $controller_resolver;
$this->argumentResolver = $argument_resolver;
$this->requestStack = new RequestStack();
$this->requestStack->push($request);
$this->routeMatch = $route_match;
@@ -85,7 +85,7 @@ class LocalTaskDefaultTest extends UnitTestCase {
*/
public function testGetRouteParametersForStaticRoute() {
$this->pluginDefinition = [
'route_name' => 'test_route'
'route_name' => 'test_route',
];
$this->routeProvider->expects($this->once())
@@ -105,7 +105,7 @@ class LocalTaskDefaultTest extends UnitTestCase {
public function testGetRouteParametersInPluginDefinitions() {
$this->pluginDefinition = [
'route_name' => 'test_route',
'route_parameters' => ['parameter' => 'example']
'route_parameters' => ['parameter' => 'example'],
];
$this->routeProvider->expects($this->once())
@@ -124,7 +124,7 @@ class LocalTaskDefaultTest extends UnitTestCase {
*/
public function testGetRouteParametersForDynamicRouteWithNonUpcastedParameters() {
$this->pluginDefinition = [
'route_name' => 'test_route'
'route_name' => 'test_route',
];
$route = new Route('/test-route/{parameter}');
@@ -147,7 +147,7 @@ class LocalTaskDefaultTest extends UnitTestCase {
*/
public function testGetRouteParametersForDynamicRouteWithUpcastedParameters() {
$this->pluginDefinition = [
'route_name' => 'test_route'
'route_name' => 'test_route',
];
$route = new Route('/test-route/{parameter}');
@@ -177,17 +177,17 @@ class LocalTaskDefaultTest extends UnitTestCase {
[
'base_route' => 'local_task_default',
'route_name' => 'local_task_default',
'id' => 'local_task_default'
'id' => 'local_task_default',
],
'local_task_default',
-10
-10,
],
// If the base route is different from the route of the tab, ignore it.
[
[
'base_route' => 'local_task_example',
'route_name' => 'local_task_other',
'id' => 'local_task_default'
'id' => 'local_task_default',
],
'local_task_default',
0,
@@ -291,9 +291,9 @@ class LocalTaskDefaultTest extends UnitTestCase {
'attributes' => [
'class' => [
'example',
'is-active'
]
]
'is-active',
],
],
], $this->localTaskBase->getOptions($route_match));
}
@@ -317,6 +317,7 @@ class LocalTaskDefaultTest extends UnitTestCase {
}
class TestLocalTaskDefault extends LocalTaskDefault {
public function setRouteProvider(RouteProviderInterface $route_provider) {
$this->routeProvider = $route_provider;
return $this;
@@ -61,10 +61,10 @@ abstract class LocalTaskIntegrationTestBase extends UnitTestCase {
->setMethods(NULL)
->getMock();
$controllerResolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');
$property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'controllerResolver');
$argumentResolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
$property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'argumentResolver');
$property->setAccessible(TRUE);
$property->setValue($manager, $controllerResolver);
$property->setValue($manager, $argumentResolver);
// todo mock a request with a route.
$request_stack = new RequestStack();

Some files were not shown because too many files have changed in this diff Show More