diff --git a/core/core.services.yml b/core/core.services.yml
index 598754e..a391849 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -339,7 +339,7 @@ services:
       - [setValidationConstraintManager, ['@validation.constraint']]
   context.handler:
     class: Drupal\Core\Plugin\Context\ContextHandler
-    arguments: ['@typed_data_manager']
+    arguments: ['@typed_data_manager', '@entity_type.manager', '@entity_type.bundle.info']
   context.repository:
     class: Drupal\Core\Plugin\Context\LazyContextRepository
     arguments: ['@service_container']
diff --git a/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php b/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php
index 2a13d36..4a7354f 100644
--- a/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php
+++ b/core/lib/Drupal/Core/Plugin/Context/ContextHandler.php
@@ -4,7 +4,15 @@
 
 use Drupal\Component\Plugin\Exception\ContextException;
 use Drupal\Core\Cache\CacheableDependencyInterface;
+use Drupal\Core\Entity\ContentEntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
+use Drupal\Core\Entity\Plugin\Validation\Constraint\BundleConstraint;
+use Drupal\Core\Entity\Plugin\Validation\Constraint\EntityTypeConstraint;
+use Drupal\Core\Entity\TypedData\EntityDataDefinition;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
+use Drupal\Core\TypedData\TypedDataManagerInterface;
 
 /**
  * Provides methods to handle sets of contexts.
@@ -12,6 +20,43 @@
 class ContextHandler implements ContextHandlerInterface {
 
   /**
+   * The typed data manager.
+   *
+   * @var \Drupal\Core\TypedData\TypedDataManagerInterface
+   */
+  protected $typedDataManager;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The entity type bundle information object.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
+   */
+  protected $entityTypeBundleInfo;
+
+  /**
+   * ContextHandler constructor.
+   *
+   * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
+   *   The typed data manager.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
+   *   The entity type bundle information object.
+   */
+  public function __construct(TypedDataManagerInterface $typed_data_manager, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
+    $this->typedDataManager = $typed_data_manager;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->entityTypeBundleInfo = $entity_type_bundle_info;
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function filterPluginDefinitionsByContexts(array $contexts, array $definitions) {
@@ -51,11 +96,13 @@ public function getMatchingContexts(array $contexts, ContextDefinitionInterface
         return FALSE;
       }
 
-      // If any constraint does not match, this context is invalid.
-      foreach ($definition->getConstraints() as $constraint_name => $constraint) {
-        if ($context_definition->getConstraint($constraint_name) != $constraint) {
-          return FALSE;
-        }
+      // If the definition has constraints, validate the contexts against them.
+      if ($definition->getConstraints()) {
+        $typed_data_definition = $this->getTypedDataFromContext($context);
+        $validator = $this->typedDataManager->getValidator();
+        $violations = $validator->validate($typed_data_definition, array_values($this->getConstraintsFromContextDefinition($definition)));
+        // Contexts without any violations are valid.
+        return !$violations->count();
       }
 
       // All contexts with matching data type and contexts are valid.
@@ -118,4 +165,66 @@ public function applyContextMapping(ContextAwarePluginInterface $plugin, $contex
     }
   }
 
+  /**
+   * Extracts an array of constraints for a context definition object.
+   *
+   * @param \Drupal\Core\Plugin\Context\ContextDefinitionInterface $definition
+   *   The context definition object.
+   *
+   * @return \Symfony\Component\Validator\Constraint[]
+   *   A list of applied constraints for the context definition.
+   */
+  protected function getConstraintsFromContextDefinition(ContextDefinitionInterface $definition) {
+    $constraints = [];
+    $definition_constraints = $definition->getConstraints();
+    // If the data type is an entity, but doesn't provide a corresponding
+    // constraint, we need to manually add one to the constraints array.
+    if (strpos($definition->getDataType(), 'entity:') === 0 && !array_key_exists('EntityType', $definition_constraints)) {
+      $entity_type = substr($definition->getDataType(), 7);
+      $constraints['EntityType'] = $this->typedDataManager->getValidationConstraintManager()->create('EntityType', ['type' => $entity_type]);
+    }
+    foreach ($definition_constraints as $constraint_name => $constraint_settings) {
+      $constraints[$constraint_name] = $this->typedDataManager->getValidationConstraintManager()->create($constraint_name, $constraint_settings);
+    }
+    return $constraints;
+  }
+
+  /**
+   * Provides a reliable TypedData object from a context or its definition.
+   *
+   * @param \Drupal\Core\Plugin\Context\ContextInterface $context
+   *   The context from which to generate a TypedData object.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface
+   *   The generated typed data object.
+   */
+  protected function getTypedDataFromContext(ContextInterface $context) {
+    // If the context has a value, just return that.
+    if ($context->hasContextValue()) {
+      return $context->getContextData();
+    }
+    $context_definition = $context->getContextDefinition();
+    // Get the constraints from the context's definition.
+    $constraints = $this->getConstraintsFromContextDefinition($context_definition);
+    // If constraints include EntityType, we generate an entity or adapter.
+    if (!empty($constraints['EntityType']) && $constraints['EntityType'] instanceof EntityTypeConstraint) {
+      $entity_type_id = $constraints['EntityType']->type;
+      $storage = $this->entityTypeManager->getStorage($entity_type_id);
+      // If the storage can generate a sample entity we might delegate to that.
+      if ($storage instanceof ContentEntityStorageInterface) {
+        if (!empty($constraints['Bundle']) && $constraints['Bundle'] instanceof BundleConstraint) {
+          $bundle = $constraints['Bundle']->bundle[0];
+          // We have a bundle, we are bundleable and we can generate a sample.
+          return EntityAdapter::createFromEntity($storage->createWithSampleValues($bundle));
+        }
+      }
+      // Either no bundle, or not bundleable, so generate an entity adapter.
+      $definition = EntityDataDefinition::create()
+        ->setEntityTypeId($entity_type_id);
+      return new EntityAdapter($definition);
+    }
+    // No entity related constraints, so generate a basic typed data object.
+    return $this->typedDataManager->createInstance($context_definition->getDataType());
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php b/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php
index 4ed5e6e..5516ac9 100644
--- a/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Plugin/ContextHandlerTest.php
@@ -1,26 +1,23 @@
 <?php
 
-/**
- * @file
- * Contains \Drupal\Tests\Core\Plugin\ContextHandlerTest.
- */
-
 namespace Drupal\Tests\Core\Plugin;
 
 use Drupal\Component\Plugin\ConfigurablePluginInterface;
 use Drupal\Component\Plugin\Exception\ContextException;
+use Drupal\Core\Plugin\Context\Context;
 use Drupal\Core\Plugin\Context\ContextDefinition;
-use Drupal\Core\Plugin\Context\ContextHandler;
 use Drupal\Core\Plugin\ContextAwarePluginInterface;
 use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\TypedData\Plugin\DataType\StringData;
-use Drupal\Tests\UnitTestCase;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
 
 /**
  * @coversDefaultClass \Drupal\Core\Plugin\Context\ContextHandler
  * @group Plugin
  */
-class ContextHandlerTest extends UnitTestCase {
+class ContextHandlerTest extends KernelTestBase {
+  use ContentTypeCreationTrait;
 
   /**
    * The context handler.
@@ -30,202 +27,178 @@ class ContextHandlerTest extends UnitTestCase {
   protected $contextHandler;
 
   /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['user', 'system', 'node', 'field', 'text', 'filter'];
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
-    $this->contextHandler = new ContextHandler();
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('node_type');
+    $this->installEntitySchema('node');
+    $this->installConfig('node');
+    $this->createContentType(['type' => 'page', 'name' => 'Page']);
+    $this->createContentType(['type' => 'article', 'name' => 'Article']);
+    $this->contextHandler = $this->container->get('context.handler');
   }
 
   /**
    * @covers ::checkRequirements
-   *
-   * @dataProvider providerTestCheckRequirements
    */
-  public function testCheckRequirements($contexts, $requirements, $expected) {
-    $this->assertSame($expected, $this->contextHandler->checkRequirements($contexts, $requirements));
-  }
-
-  /**
-   * Provides data for testCheckRequirements().
-   */
-  public function providerTestCheckRequirements() {
-    $requirement_optional = new ContextDefinition();
-    $requirement_optional->setRequired(FALSE);
+  public function testCheckRequirements() {
+    // No contexts, no requirements = TRUE
+    $this->assertSame(TRUE, $this->contextHandler->checkRequirements([], []));
 
+    // No contexts, any requirement = FALSE
     $requirement_any = new ContextDefinition();
     $requirement_any->setRequired(TRUE);
+    $this->assertSame(FALSE, $this->contextHandler->checkRequirements([], [$requirement_any]));
 
-    $context_any = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_any->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('empty')));
-
-    $requirement_specific = new ContextDefinition('specific');
-    $requirement_specific->setConstraints(['bar' => 'baz']);
-
-    $context_constraint_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_constraint_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('foo')));
-    $context_datatype_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_datatype_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('fuzzy')));
-
-    $context_definition_specific = new ContextDefinition('specific');
-    $context_definition_specific->setConstraints(['bar' => 'baz']);
-    $context_specific = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_specific->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue($context_definition_specific));
-
-    $data = [];
-    $data[] = [[], [], TRUE];
-    $data[] = [[], [$requirement_any], FALSE];
-    $data[] = [[], [$requirement_optional], TRUE];
-    $data[] = [[], [$requirement_any, $requirement_optional], FALSE];
-    $data[] = [[$context_any], [$requirement_any], TRUE];
-    $data[] = [[$context_constraint_mismatch], [$requirement_specific], FALSE];
-    $data[] = [[$context_datatype_mismatch], [$requirement_specific], FALSE];
-    $data[] = [[$context_specific], [$requirement_specific], TRUE];
-
-    return $data;
+    // No context, optional requirements = TRUE
+    $requirement_optional = new ContextDefinition();
+    $requirement_optional->setRequired(FALSE);
+    $this->assertSame(TRUE, $this->contextHandler->checkRequirements([], [$requirement_optional]));
+
+    // No context, required or optional requirements = FALSE
+    $this->assertSame(FALSE, $this->contextHandler->checkRequirements([], [$requirement_any, $requirement_optional]));
+
+    // Any context, any requirement = TRUE
+    $context_any = new Context(new ContextDefinition('any'));
+    $this->assertSame(TRUE, $this->contextHandler->checkRequirements([$context_any], [$requirement_any]));
+
+    // Article node context, page node requirement = FALSE
+    $requirement_specific = new ContextDefinition('entity:node');
+    $requirement_specific->setConstraints(array('Bundle' => [0 => 'page']));
+    $mismatch_def = new ContextDefinition('entity:node');
+    $context_constraint_mismatch = new Context($mismatch_def->setConstraints(['EntityType' => 'node', 'Bundle' => [0 => 'article']]));
+    $this->assertSame(FALSE, $this->contextHandler->checkRequirements([$context_constraint_mismatch], [$requirement_specific]));
+
+    // User context, page node requirement = FALSE
+    $context_datatype_mismatch = new Context(new ContextDefinition('entity:user'));
+    $this->assertSame(FALSE, $this->contextHandler->checkRequirements([$context_datatype_mismatch], [$requirement_specific]));
+
+    // Page node context, page node requirement = TRUE
+    $specific_def = new ContextDefinition('entity:node');
+    $context_specific = new Context($specific_def->setConstraints(array('Bundle' => [0 => 'page'])));
+    $this->assertSame(TRUE, $this->contextHandler->checkRequirements([$context_specific], [$requirement_specific]));
+
+    // Page node context, page OR article node requirement = TRUE
+    $requirement_complex = new ContextDefinition('entity:node');
+    $requirement_complex->setConstraints(['Bundle' => [0 => 'page', 1 => 'article']]);
+    $this->assertSame(TRUE, $this->contextHandler->checkRequirements([$context_specific], [$requirement_complex]));
+
+    // Article node context, page OR article node requirement = TRUE
+    $this->assertSame(TRUE, $this->contextHandler->checkRequirements([$context_constraint_mismatch], [$requirement_complex]));
   }
 
   /**
    * @covers ::getMatchingContexts
-   *
-   * @dataProvider providerTestGetMatchingContexts
    */
-  public function testGetMatchingContexts($contexts, $requirement, $expected = NULL) {
-    if (is_null($expected)) {
-      $expected = $contexts;
-    }
-    $this->assertSame($expected, $this->contextHandler->getMatchingContexts($contexts, $requirement));
-  }
-
-  /**
-   * Provides data for testGetMatchingContexts().
-   */
-  public function providerTestGetMatchingContexts() {
+  public function testGetMatchingContexts() {
     $requirement_any = new ContextDefinition();
 
-    $requirement_specific = new ContextDefinition('specific');
-    $requirement_specific->setConstraints(['bar' => 'baz']);
-
-    $context_any = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_any->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('empty')));
-    $context_constraint_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_constraint_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('foo')));
-    $context_datatype_mismatch = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_datatype_mismatch->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue(new ContextDefinition('fuzzy')));
-    $context_definition_specific = new ContextDefinition('specific');
-    $context_definition_specific->setConstraints(['bar' => 'baz']);
-    $context_specific = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-    $context_specific->expects($this->atLeastOnce())
-      ->method('getContextDefinition')
-      ->will($this->returnValue($context_definition_specific));
-
-    $data = [];
+    $requirement_specific = new ContextDefinition('entity:node');
+    $requirement_specific->setConstraints(array('Bundle' => [0 => 'page']));
+
+    $context_any = new Context(new ContextDefinition());
+
+    $definition_constraint_mismatch = new ContextDefinition('entity:node');
+    $definition_constraint_mismatch->setConstraints(array('Bundle' => [0 => 'article']));
+    $context_constraint_mismatch = new Context($definition_constraint_mismatch);
+
+    $definition_datatype_mismatch = new ContextDefinition('entity:user');
+    $context_datatype_mismatch = new Context($definition_datatype_mismatch);
+
+    $context_definition_specific = new ContextDefinition('entity:node');
+    $context_definition_specific->setConstraints(array('Bundle' => [0 => 'page']));
+    $context_specific = new Context($context_definition_specific);
+
     // No context will return no valid contexts.
-    $data[] = [[], $requirement_any];
+    $this->assertEquals([], $this->contextHandler->getMatchingContexts([], $requirement_any));
     // A context with a generic matching requirement is valid.
-    $data[] = [[$context_any], $requirement_any];
+    $this->assertEquals([$context_any], $this->contextHandler->getMatchingContexts([$context_any], $requirement_any));
     // A context with a specific matching requirement is valid.
-    $data[] = [[$context_specific], $requirement_specific];
-
+    $this->assertEquals([$context_specific], $this->contextHandler->getMatchingContexts([$context_specific], $requirement_specific));
     // A context with a mismatched constraint is invalid.
-    $data[] = [[$context_constraint_mismatch], $requirement_specific, []];
+    $this->assertEquals([], $this->contextHandler->getMatchingContexts([$context_constraint_mismatch], $requirement_specific));
     // A context with a mismatched datatype is invalid.
-    $data[] = [[$context_datatype_mismatch], $requirement_specific, []];
-
-    return $data;
+    $this->assertEquals([], $this->contextHandler->getMatchingContexts([$context_datatype_mismatch], $requirement_specific));
   }
 
   /**
    * @covers ::filterPluginDefinitionsByContexts
-   *
-   * @dataProvider providerTestFilterPluginDefinitionsByContexts
-   */
-  public function testFilterPluginDefinitionsByContexts($has_context, $definitions, $expected) {
-    if ($has_context) {
-      $context = $this->getMock('Drupal\Core\Plugin\Context\ContextInterface');
-      $expected_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(['expected_constraint_name' => 'expected_constraint_value']);
-      $context->expects($this->atLeastOnce())
-        ->method('getContextDefinition')
-        ->will($this->returnValue($expected_context_definition));
-      $contexts = [$context];
-    }
-    else {
-      $contexts = [];
-    }
-
-    $this->assertSame($expected, $this->contextHandler->filterPluginDefinitionsByContexts($contexts, $definitions));
-  }
-
-  /**
-   * Provides data for testFilterPluginDefinitionsByContexts().
    */
-  public function providerTestFilterPluginDefinitionsByContexts() {
-    $data = [];
-
-    $plugins = [];
-    // No context and no plugins, no plugins available.
-    $data[] = [FALSE, $plugins, []];
-
-    $plugins = ['expected_plugin' => []];
-    // No context, all plugins available.
-    $data[] = [FALSE, $plugins, $plugins];
-
-    $plugins = ['expected_plugin' => ['context' => []]];
-    // No context, all plugins available.
-    $data[] = [FALSE, $plugins, $plugins];
-
-    $plugins = ['expected_plugin' => ['context' => ['context1' => new ContextDefinition('expected_data_type')]]];
-    // Missing context, no plugins available.
-    $data[] = [FALSE, $plugins, []];
-    // Satisfied context, all plugins available.
-    $data[] = [TRUE, $plugins, $plugins];
-
-    $mismatched_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(['mismatched_constraint_name' => 'mismatched_constraint_value']);
-    $plugins = ['expected_plugin' => ['context' => ['context1' => $mismatched_context_definition]]];
-    // Mismatched constraints, no plugins available.
-    $data[] = [TRUE, $plugins, []];
-
-    $optional_mismatched_context_definition = clone $mismatched_context_definition;
-    $optional_mismatched_context_definition->setRequired(FALSE);
-    $plugins = ['expected_plugin' => ['context' => ['context1' => $optional_mismatched_context_definition]]];
-    // Optional mismatched constraint, all plugins available.
-    $data[] = [FALSE, $plugins, $plugins];
-
-    $expected_context_definition = (new ContextDefinition('expected_data_type'))->setConstraints(['expected_constraint_name' => 'expected_constraint_value']);
-    $plugins = ['expected_plugin' => ['context' => ['context1' => $expected_context_definition]]];
-    // Satisfied context with constraint, all plugins available.
-    $data[] = [TRUE, $plugins, $plugins];
-
-    $optional_expected_context_definition = clone $expected_context_definition;
-    $optional_expected_context_definition->setRequired(FALSE);
-    $plugins = ['expected_plugin' => ['context' => ['context1' => $optional_expected_context_definition]]];
-    // Optional unsatisfied context, all plugins available.
-    $data[] = [FALSE, $plugins, $plugins];
-
-    $unexpected_context_definition = (new ContextDefinition('unexpected_data_type'))->setConstraints(['mismatched_constraint_name' => 'mismatched_constraint_value']);
+  public function testFilterPluginDefinitionsByContexts() {
+    $user = new ContextDefinition('entity:user');
+    $node = new ContextDefinition('entity:node');
+    $string = new ContextDefinition('string');
+    $page = new ContextDefinition('entity:node');
+    $page->addConstraint('Bundle', [0 => 'page']);
+    $article = new ContextDefinition('entity:node');
+    $article->addConstraint('Bundle', [0 => 'article']);
+    $multi_bundle = clone ($node);
+    $multi_bundle->addConstraint('Bundle', [0 => 'page', 1 => 'article']);
     $plugins = [
-      'unexpected_plugin' => ['context' => ['context1' => $unexpected_context_definition]],
-      'expected_plugin' => ['context' => ['context2' => new ContextDefinition('expected_data_type')]],
+      'needs_node' => [
+        'context' => [
+          'node' => $node,
+        ],
+      ],
+      'needs_page' => [
+        'context' => [
+          'node' => $page,
+        ],
+      ],
+      'needs_article' => [
+        'context' => [
+          'node' => $article,
+        ],
+      ],
+      'needs_page_or_article' => [
+        'context' => [
+          'node' => $multi_bundle,
+        ],
+      ],
+      'needs_user' => [
+        'context' => [
+          'user' => $user,
+        ],
+      ],
+      'no_context_1' => [],
+      'no_context_2' => [],
+      'needs_string' => [
+        'context' => [
+          'string' => $string,
+        ]
+      ]
     ];
-    // Context only satisfies one plugin.
-    $data[] = [TRUE, $plugins, ['expected_plugin' => $plugins['expected_plugin']]];
-
-    return $data;
+    // No context, plugins without contextual requirements available.
+    //$data[] = [[], $plugins, ['no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']]];
+    $this->assertSame(['no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']], $this->contextHandler->filterPluginDefinitionsByContexts([], $plugins));
+    // Node context, plugins without contextual requirements and node specific
+    // contexts available.
+    $this->assertSame(['needs_node' => $plugins['needs_node'], 'needs_page' => $plugins['needs_page'], 'needs_article' => $plugins['needs_article'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']], $this->contextHandler->filterPluginDefinitionsByContexts(['node' => new Context($node)], $plugins));
+    // Node of bundle article contexts, plugins without contextual requirements
+    // and node or article specific bundle contexts available.
+    $this->assertSame(['needs_node' => $plugins['needs_node'], 'needs_article' => $plugins['needs_article'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']], $this->contextHandler->filterPluginDefinitionsByContexts(['node' => new Context($article)], $plugins));
+    // Node of bundle page contexts, plugins without contextual requirements and
+    // node or page specific bundle contexts available.
+    $this->assertSame(['needs_node' => $plugins['needs_node'], 'needs_page' => $plugins['needs_page'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']], $this->contextHandler->filterPluginDefinitionsByContexts(['node' => new Context($page)], $plugins));
+    // Nodes of bundles page and article contexts, plugins without contextual
+    // requirements and node, page or article specific bundle contexts
+    // available.
+    $this->assertSame(['needs_node' => $plugins['needs_node'], 'needs_page' => $plugins['needs_page'], 'needs_article' => $plugins['needs_article'], 'needs_page_or_article' => $plugins['needs_page_or_article'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']], $this->contextHandler->filterPluginDefinitionsByContexts(['page' => new Context($page), 'article' => new Context($article)], $plugins));
+    // User context, plugins without contextual requirements and user specific
+    // contexts available.
+    $this->assertSame(['needs_user' => $plugins['needs_user'], 'no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2']], $this->contextHandler->filterPluginDefinitionsByContexts(['user' => new Context($user)], $plugins));
+    // Non-entity contextual requirements test.
+    $this->assertSame(['no_context_1' => $plugins['no_context_1'], 'no_context_2' => $plugins['no_context_2'], 'needs_string' => $plugins['needs_string']], $this->contextHandler->filterPluginDefinitionsByContexts(['string' => new Context($string)], $plugins));
   }
 
   /**
