entity_legal-4.0.x-dev/tests/src/Functional/RedirectMethodTest.php

tests/src/Functional/RedirectMethodTest.php
<?php

declare(strict_types=1);

namespace Drupal\Tests\entity_legal\Functional;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Test\AssertMailTrait;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\entity_legal\Traits\EntityLegalTestTrait;
use Drupal\user\Entity\User;

/**
 * Tests the 'redirect' plugin.
 *
 * @group entity_legal
 */
class RedirectMethodTest extends BrowserTestBase {

  use AssertMailTrait;
  use EntityLegalTestTrait;

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'system',
    'test_page_test',
    'block',
    'dynamic_page_cache',
    'entity_legal_test',
  ];

  /**
   * Redirection method test.
   */
  public function testRedirectMethod() {
    $this->drupalPlaceBlock('system_menu_block:account');
    $document = $this->createDocument(TRUE, TRUE, [
      'existing_users' => [
        'require_method' => 'redirect',
      ],
    ]);
    $this->createDocumentVersion($document, TRUE);

    $account = $this->createUserWithAcceptancePermissions($document);
    $this->drupalLogin($account);

    $document_path = $document->toUrl()->setAbsolute()->toString();

    /** @var \Drupal\user\UserInterface $user */
    $user = \Drupal::entityTypeManager()->getStorage('user')->load($account->id());

    $this->assertSession()->addressEquals($document_path);

    $this->drupalGet('');

    $this->assertSession()->addressEquals($document_path);

    // Check that users are able to logout even they don't accept the agreement.
    $this->clickLink('Log out');
    // Check that the user has been logged out.
    $this->assertSession()->linkExists('Log in');

    $this->submitForm([
      'name' => $account->getAccountName(),
      'pass' => $account->pass_raw,
    ], 'Log in');

    $this->assertSession()->pageTextContains('You must accept this agreement before continuing.');
    $this->assertSession()->pageTextContains('I agree to the document');

    // Agree with the terms.
    $this->submitForm(['agree' => TRUE], 'Submit');

    // Refresh the page.
    $this->drupalGet('');

    $this->assertSession()->addressEquals($user->toUrl()->setAbsolute()->toString());

    $this->clickLink('Log out');

    // Release a new document version.
    $this->createDocumentVersion($document, TRUE);

    $this->drupalGet(Url::fromRoute('user.pass'));
    $this->submitForm(['name' => $account->getAccountName()], 'Submit');
    $this->assertSession()->pageTextContains("If {$account->getAccountName()} is a valid account, an email will be sent with instructions to reset your password.");

    // Click the one-time login link received by mail and login.
    $this->clickMailOneTimeLoginLink();
    $this->assertSession()->pageTextContains("This is a one-time login for {$account->getAccountName()} and will expire on");
    $this->submitForm([], 'Log in');

    // The user has to accept the new document version.
    $this->assertSession()->pageTextContains('You must accept this agreement before continuing.');
    $this->assertSession()->pageTextContains('I agree to the document');

    // Agree with the terms.
    $this->submitForm(['agree' => TRUE], 'Submit');

    // Check that we're on the user account edit form page.
    $this->assertSession()->pageTextContains('You have used a one-time login link. You can set your new password now.');
    $this->assertSession()->fieldExists('mail');
    $this->assertSession()->fieldExists('pass[pass1]');
    $this->assertSession()->fieldExists('pass[pass2]');

    // Set a new password.
    $new_password = $this->randomString();
    $account->pass_raw = $new_password;
    $this->submitForm([
      'pass[pass1]' => $new_password,
      'pass[pass2]' => $new_password,
    ], 'Save');
    $this->assertSession()->pageTextContains('The changes have been saved.');

    // Release a new document version.
    $this->createDocumentVersion($document, TRUE);

    // Try to bypass by faking a user reset URL.
    $this->drupalGet("/user/{$account->id()}/edit", [
      'query' => [
        'pass-reset-token' => 'arbitrary-invalid-token',
      ],
    ]);
    // Check that the approval gate cannot be bypassed.
    $this->assertSession()->pageTextContains('You must accept this agreement before continuing.');
    $this->assertSession()->pageTextContains('I agree to the document');
  }

  /**
   * Tests redirect exclusion routes/conditions.
   *
   * @covers \Drupal\entity_legal\Plugin\EntityLegal\Redirect::isExcludedRoute
   * @covers \Drupal\entity_legal\Plugin\EntityLegal\Redirect::execute
   */
  public function testRedirectExclusions() {
    // Prepare document.
    $document = $this->createDocument(TRUE, TRUE, [
      'existing_users' => [
        'require_method' => 'redirect',
      ],
    ]);
    $this->createDocumentVersion($document, TRUE);

    $account = $this->createUserWithAcceptancePermissions($document);
    $this->drupalLogin($account);
    $document_path = $document->toUrl()->setAbsolute()->toString();
    $this->assertSession()->addressEquals($document_path);

    // Prepare CSS/JS files.
    \Drupal::service('file_system')->mkdir("$this->publicFilesDirectory/css");
    file_put_contents("$this->publicFilesDirectory/css/foo.css", $this->randomMachineName());
    \Drupal::service('file_system')->mkdir("$this->publicFilesDirectory/js");
    file_put_contents("$this->publicFilesDirectory/js/bar.js", $this->randomMachineName());

    // Test excluded routes.
    $urls = [
      Url::fromRoute('system.csrftoken'),
      Url::fromRoute('user.logout.confirm'),
      // Aggregated assets are usually created when accessing them for the first
      // time. Prefix with index.php to prevent apache from serving the files we
      // created directly.
      Url::fromRoute('system.css_asset', ['file_name' => 'foo.css'], ['prefix' => 'index.php/']),
      Url::fromRoute('system.js_asset', ['file_name' => 'bar.js'], ['prefix' => 'index.php/']),
    ];
    foreach ($urls as $url) {
      $this->drupalGet($url);
      $this->assertSession()->addressEquals($url);
    }

    // Non-HTML requests.
    \Drupal::service('module_installer')->install(['jsonapi']);
    $http_client = \Drupal::httpClient();
    $url = Url::fromRoute("jsonapi.entity_legal_document_version--{$document->id()}.collection")
      ->setAbsolute()
      ->toString();
    $response = $http_client->get($url, [
      'headers' => [
        'Accept' => 'application/vnd.api+json',
      ],
    ]);
    $jsonapi = Json::decode($response->getBody()->getContents());
    $this->assertTrue(isset($jsonapi['jsonapi']['version']) && isset($jsonapi['data']));
  }

  /**
   * Tests the case when the origin pages has set messages.
   *
   * An origin page might have set status, warning or error messages to be
   * displayed on the destination page. Test that such messages are not
   * shown on the entity legal acceptance page.
   */
  public function testMessageDisplay(): void {
    $document = $this->createDocument(TRUE, TRUE, [
      'existing_users' => [
        'require_method' => 'redirect',
      ],
    ]);
    $this->createDocumentVersion($document, TRUE);
    $this->drupalLogin($this->createUserWithAcceptancePermissions($document));

    // Check that the acceptance form doesn't contain the messages.
    $this->assertSession()->pageTextContains('You must accept this agreement before continuing.');
    $this->assertSession()->pageTextNotContains('A status message sample');
    $this->assertSession()->pageTextNotContains('A warning message sample');
    $this->assertSession()->pageTextNotContains('An error message sample');

    $this->submitForm(['agree' => TRUE], 'Submit');

    // Check that messages are shown on the destination page.
    $account = User::load(\Drupal::currentUser()->id());
    $this->assertSession()->addressEquals($account->toUrl());
    $this->assertSession()->pageTextContains('A status message sample');
    $this->assertSession()->pageTextContains('A warning message sample');
    $this->assertSession()->pageTextContains('An error message sample');
  }

  /**
   * Checks that the redirection works on cached pages.
   */
  public function testRedirectOnCachedPage(): void {
    $this->config('system.site')->set('page.front', '/test-page')->save();
    $document = $this->createDocument(TRUE, TRUE, [
      'existing_users' => [
        'require_method' => 'redirect',
      ],
    ]);
    $this->createDocumentVersion($document, TRUE);
    $this->drupalLogin($this->createUserWithAcceptancePermissions($document));

    $this->submitForm(['agree' => TRUE], 'Submit');
    $this->drupalGet('<front>');

    // Visit the front page again and ensure it is cached.
    $this->drupalGet('<front>');
    $this->assertSame('HIT', $this->getSession()->getResponseHeader('X-Drupal-Dynamic-Cache'));

    // Release a new document version.
    $this->createDocumentVersion($document, TRUE);

    // Reload the front page and check that the user is correctly redirected.
    $this->drupalGet('<front>');
    $this->assertSession()->pageTextContains('You must accept this agreement before continuing.');
    $this->assertSession()->pageTextContains('I agree to the document');
  }

  /**
   * Clicks on the email password reset one-time-login link.
   */
  protected function clickMailOneTimeLoginLink(): void {
    // Assume the most recent email.
    $emails = $this->getMails();
    $email = end($emails);
    $urls = [];
    preg_match('#.+user/reset/.+#', $email['body'], $urls);
    $this->drupalGet($urls[0]);
  }

  /**
   * Tests the bypass permission for the redirect method.
   */
  public function testBypassAcceptance(): void {
    $document = $this->createDocument(TRUE, TRUE, [
      'existing_users' => [
        'require_method' => 'redirect',
      ],
    ]);
    $this->createDocumentVersion($document, TRUE);

    $account = $this->createUserWithAcceptanceBypassPermissions($document);
    $this->drupalLogin($account);
    $this->assertSession()->addressEquals($account->toUrl());
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc