ResourceTest.php 5.02 KB
Newer Older
1 2
<?php

3
namespace Drupal\Tests\rest\Functional;
4

5
use Drupal\Core\Session\AccountInterface;
6 7
use Drupal\entity_test\Entity\EntityTest;
use Drupal\rest\Entity\RestResourceConfig;
8
use Drupal\rest\RestResourceConfigInterface;
9
use Drupal\Tests\BrowserTestBase;
10
use Drupal\user\Entity\Role;
11
use Drupal\user\RoleInterface;
12
use GuzzleHttp\RequestOptions;
13 14

/**
15 16 17
 * Tests the structure of a REST resource.
 *
 * @group rest
18
 */
19
class ResourceTest extends BrowserTestBase {
20 21

  /**
22
   * Modules to install.
23 24 25
   *
   * @var array
   */
26
  public static $modules = ['hal', 'rest', 'entity_test', 'rest_test'];
27

28 29 30 31 32 33 34
  /**
   * The entity.
   *
   * @var \Drupal\Core\Entity\EntityInterface
   */
  protected $entity;

35 36 37 38 39
  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();
40
    // Create an entity programmatic.
41 42 43
    $this->entity = EntityTest::create([
      'name' => $this->randomMachineName(),
      'user_id' => 1,
44 45 46 47 48 49
      'field_test_text' => [
        0 => [
          'value' => $this->randomString(),
          'format' => 'plain_text',
        ],
      ],
50
    ]);
51
    $this->entity->save();
52 53 54 55

    Role::load(AccountInterface::ANONYMOUS_ROLE)
      ->grantPermission('view test entity')
      ->save();
56 57 58 59 60 61
  }

  /**
   * Tests that a resource without formats cannot be enabled.
   */
  public function testFormats() {
62
    RestResourceConfig::create([
63 64 65 66 67
      'id' => 'entity.entity_test',
      'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
      'configuration' => [
        'GET' => [
          'supported_auth' => [
68
            'basic_auth',
69 70 71 72
          ],
        ],
      ],
    ])->save();
73

74
    // Verify that accessing the resource returns 406.
75
    $this->drupalGet($this->entity->urlInfo()->setRouteParameter('_format', 'hal_json'));
76 77 78 79 80
    // \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
    // non-REST route a match, but a lower quality one: no format restrictions
    // means there's always a match and hence when there is no matching REST
    // route, the non-REST route is used, but can't render into
    // application/hal+json, so it returns a 406.
81
    $this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
82 83 84 85 86 87
  }

  /**
   * Tests that a resource without authentication cannot be enabled.
   */
  public function testAuthentication() {
88
    RestResourceConfig::create([
89 90 91 92 93
      'id' => 'entity.entity_test',
      'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
      'configuration' => [
        'GET' => [
          'supported_formats' => [
94
            'hal_json',
95 96 97 98
          ],
        ],
      ],
    ])->save();
99 100

    // Verify that accessing the resource returns 401.
101
    $this->drupalGet($this->entity->urlInfo()->setRouteParameter('_format', 'hal_json'));
102 103 104 105 106
    // \Drupal\Core\Routing\RequestFormatRouteFilter considers the canonical,
    // non-REST route a match, but a lower quality one: no format restrictions
    // means there's always a match and hence when there is no matching REST
    // route, the non-REST route is used, but can't render into
    // application/hal+json, so it returns a 406.
107
    $this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
108 109
  }

110 111 112 113
  /**
   * Tests that serialization_class is optional.
   */
  public function testSerializationClassIsOptional() {
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    RestResourceConfig::create([
      'id' => 'serialization_test',
      'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY,
      'configuration' => [
        'POST' => [
          'supported_formats' => [
            'json',
          ],
          'supported_auth' => [
            'cookie',
          ]
        ],
      ],
    ])->save();
    \Drupal::service('router.builder')->rebuildIfNeeded();
129 130 131 132 133 134

    Role::load(RoleInterface::ANONYMOUS_ID)
      ->grantPermission('restful post serialization_test')
      ->save();

    $serialized = $this->container->get('serializer')->serialize(['foo', 'bar'], 'json');
135 136 137 138 139 140 141 142 143
    $request_options = [
      RequestOptions::HEADERS => ['Content-Type' => 'application/json'],
      RequestOptions::BODY => $serialized,
    ];
    /** @var \GuzzleHttp\ClientInterface $client */
    $client = $this->getSession()->getDriver()->getClient()->getClient();
    $response = $client->request('POST', $this->buildUrl('serialization_test', ['query' => ['_format' => 'json']]), $request_options);
    $this->assertSame(200, $response->getStatusCode());
    $this->assertSame('["foo","bar"]', (string) $response->getBody());
144 145
  }

146 147 148 149 150 151 152 153 154 155 156 157 158 159
  /**
   * Tests that resource URI paths are formatted properly.
   */
  public function testUriPaths() {
    /** @var \Drupal\rest\Plugin\Type\ResourcePluginManager $manager */
    $manager = \Drupal::service('plugin.manager.rest');

    foreach ($manager->getDefinitions() as $resource => $definition) {
      foreach ($definition['uri_paths'] as $key => $uri_path) {
        $this->assertFalse(strpos($uri_path, '//'), 'The resource URI path does not have duplicate slashes.');
      }
    }
  }

160
}