class TwigSandboxTest

Same name and namespace in other branches
  1. 9 core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php \Drupal\Tests\Core\Template\TwigSandboxTest
  2. 8.9.x core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php \Drupal\Tests\Core\Template\TwigSandboxTest
  3. 10 core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php \Drupal\Tests\Core\Template\TwigSandboxTest

Tests the twig sandbox policy.

@group Template

@coversDefaultClass \Drupal\Core\Template\TwigSandboxPolicy

Hierarchy

Expanded class hierarchy of TwigSandboxTest

File

core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php, line 23

Namespace

Drupal\Tests\Core\Template
View source
class TwigSandboxTest extends UnitTestCase {
  
  /**
   * The Twig environment loaded with the sandbox extension.
   *
   * @var \Twig\Environment
   */
  protected $twig;
  
  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();
    $loader = new StringLoader();
    $this->twig = new Environment($loader);
    $policy = new TwigSandboxPolicy();
    $sandbox = new SandboxExtension($policy, TRUE);
    $this->twig
      ->addExtension($sandbox);
  }
  
  /**
   * Tests that dangerous methods cannot be called in entity objects.
   *
   * @dataProvider getTwigEntityDangerousMethods
   */
  public function testEntityDangerousMethods($template) : void {
    $entity = $this->createMock('Drupal\\Core\\Entity\\EntityInterface');
    $this->expectException(SecurityError::class);
    $this->twig
      ->render($template, [
      'entity' => $entity,
    ]);
  }
  
  /**
   * Data provider for ::testEntityDangerousMethods.
   *
   * @return array
   *   An array of dangerous methods.
   */
  public static function getTwigEntityDangerousMethods() {
    return [
      [
        '{{ entity.delete }}',
      ],
      [
        '{{ entity.save }}',
      ],
      [
        '{{ entity.create }}',
      ],
    ];
  }
  
  /**
   * Tests that white listed classes can be extended.
   */
  public function testExtendedClass() : void {
    $this->assertEquals(' class="kitten"', $this->twig
      ->render('{{ attribute.addClass("kitten") }}', [
      'attribute' => new TestAttribute(),
    ]));
  }
  
  /**
   * Tests that prefixed methods can be called from within Twig templates.
   *
   * Currently "get", "has", and "is" are the only allowed prefixes.
   */
  public function testEntitySafePrefixes() : void {
    $entity = $this->createMock('Drupal\\Core\\Entity\\EntityInterface');
    $entity->expects($this->atLeastOnce())
      ->method('hasLinkTemplate')
      ->with('test')
      ->willReturn(TRUE);
    $result = $this->twig
      ->render('{{ entity.hasLinkTemplate("test") }}', [
      'entity' => $entity,
    ]);
    $this->assertTrue((bool) $result, 'Sandbox policy allows has* functions to be called.');
    $entity = $this->createMock('Drupal\\Core\\Entity\\EntityInterface');
    $entity->expects($this->atLeastOnce())
      ->method('isNew')
      ->willReturn(TRUE);
    $result = $this->twig
      ->render('{{ entity.isNew }}', [
      'entity' => $entity,
    ]);
    $this->assertTrue((bool) $result, 'Sandbox policy allows is* functions to be called.');
    $entity = $this->createMock('Drupal\\Core\\Entity\\EntityInterface');
    $entity->expects($this->atLeastOnce())
      ->method('getEntityType')
      ->willReturn('test');
    $result = $this->twig
      ->render('{{ entity.getEntityType }}', [
      'entity' => $entity,
    ]);
    $this->assertEquals('test', $result, 'Sandbox policy allows get* functions to be called.');
  }
  
  /**
   * Tests that valid methods can be called from within Twig templates.
   *
   * Currently the following methods are in the allowed list: id, label, bundle,
   * and get.
   */
  public function testEntitySafeMethods() : void {
    $entity = $this->getMockBuilder(ContentEntityBaseMockableClass::class)
      ->disableOriginalConstructor()
      ->getMock();
    $entity->expects($this->atLeastOnce())
      ->method('get')
      ->with('title')
      ->willReturn('test');
    $result = $this->twig
      ->render('{{ entity.get("title") }}', [
      'entity' => $entity,
    ]);
    $this->assertEquals('test', $result, 'Sandbox policy allows get() to be called.');
    $entity = $this->createMock('Drupal\\Core\\Entity\\EntityInterface');
    $entity->expects($this->atLeastOnce())
      ->method('id')
      ->willReturn('1234');
    $result = $this->twig
      ->render('{{ entity.id }}', [
      'entity' => $entity,
    ]);
    $this->assertEquals('1234', $result, 'Sandbox policy allows get() to be called.');
    $entity = $this->createMock('Drupal\\Core\\Entity\\EntityInterface');
    $entity->expects($this->atLeastOnce())
      ->method('label')
      ->willReturn('testing');
    $result = $this->twig
      ->render('{{ entity.label }}', [
      'entity' => $entity,
    ]);
    $this->assertEquals('testing', $result, 'Sandbox policy allows get() to be called.');
    $entity = $this->createMock('Drupal\\Core\\Entity\\EntityInterface');
    $entity->expects($this->atLeastOnce())
      ->method('bundle')
      ->willReturn('testing');
    $result = $this->twig
      ->render('{{ entity.bundle }}', [
      'entity' => $entity,
    ]);
    $this->assertEquals('testing', $result, 'Sandbox policy allows get() to be called.');
  }
  
  /**
   * Tests that safe methods inside Url objects can be called.
   */
  public function testUrlSafeMethods() : void {
    $url = $this->getMockBuilder('Drupal\\Core\\Url')
      ->disableOriginalConstructor()
      ->getMock();
    $url->expects($this->once())
      ->method('toString')
      ->willReturn('http://kittens.cat/are/cute');
    $result = $this->twig
      ->render('{{ url.toString }}', [
      'url' => $url,
    ]);
    $this->assertEquals('http://kittens.cat/are/cute', $result, 'Sandbox policy allows toString() to be called.');
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
ExpectDeprecationTrait::expectDeprecation public function Adds an expected deprecation.
ExpectDeprecationTrait::setUpErrorHandler public function Sets up the test error handler.
ExpectDeprecationTrait::tearDownErrorHandler public function Tears down the test error handler.
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers.
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
TwigSandboxTest::$twig protected property The Twig environment loaded with the sandbox extension.
TwigSandboxTest::getTwigEntityDangerousMethods public static function Data provider for ::testEntityDangerousMethods.
TwigSandboxTest::setUp protected function Overrides UnitTestCase::setUp
TwigSandboxTest::testEntityDangerousMethods public function Tests that dangerous methods cannot be called in entity objects.
TwigSandboxTest::testEntitySafeMethods public function Tests that valid methods can be called from within Twig templates.
TwigSandboxTest::testEntitySafePrefixes public function Tests that prefixed methods can be called from within Twig templates.
TwigSandboxTest::testExtendedClass public function Tests that white listed classes can be extended.
TwigSandboxTest::testUrlSafeMethods public function Tests that safe methods inside Url objects can be called.
UnitTestCase::$root protected property The app root.
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::setDebugDumpHandler public static function Registers the dumper CLI handler when the DebugDump extension is enabled.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.