diff --git a/README.txt b/README.txt
index 98e140f..f27bdbd 100644
--- a/README.txt
+++ b/README.txt
@@ -1,15 +1,10 @@
 CONTENTS OF THIS FILE
 ---------------------
- * Introduction
  * Requirements
  * Installation
  * Configuration
  * FAQ
 
- INTRODUCTION
- ------------
-Todo
-
 REQUIREMENTS
 ------------
 No other modules required, we're supporting drupal core as a source for creating
@@ -19,7 +14,7 @@ tested.
 INSTALLATION
 ------------
  * Install as you would normally install a contributed drupal module. See:
-  https://drupal.org/documentation/install/modules-themes/modules-7
+  https://www.drupal.org/docs/8/extending-drupal-8/installing-contributed-modules-find-import-enable-configure-drupal-8
   for further information.
 
 CONFIGURATION
@@ -35,8 +30,39 @@ After adding one of those, you can add a facet on the facets configuration page:
 If you're using Search API views, make sure to disable views cache when using
 facets for that view.
 
+
 FAQ
 ---
 
 Q: Why do the facets disappear after a refresh.
 A: We don't support cached views, change the view to disable caching.
+
+
+FEATURES
+--------
+
+If you are the developer of a search api backend implementation and want
+to support facets with your service class, too, you'll have to support the
+"search_api_facets" feature. In short, you'll just have to return facet terms
+and counts according to the query's "search_api_facets" option, when executing a
+query.
+In order for the module to be able to tell that your server supports facets,
+you will also have to change your service's supportsFeature() method to
+something like the following:
+```
+  public function getSupportedFeatures() {
+    return ['search_api_facets'];
+  }
+```
+
+If you don't do that, there's no way for the facet source to pick up facets.
+```$results->setExtraData('search_api_facets', $facets);```
+The structure of the array should look like this:
+```
+'$facet_name' =>
+  array (size=...)
+    0 =>
+      array (size=2)
+        'count' => string '26' (length=2)
+        'filter' => string '$option1' (length=9)
+```
diff --git a/facets.install b/facets.install
new file mode 100644
index 0000000..a1b0372
--- /dev/null
+++ b/facets.install
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @file
+ * Updates.
+ */
+
+use Drupal\facets\Entity\Facet;
+
+/**
+ * Rename facet sources to the new id, based on
+ */
+function facets_update_8001() {
+  /** @var \Drupal\facets\FacetInterface[] $entities */
+  $entities = Facet::loadMultiple();
+  foreach ($entities as $entity) {
+    $facetSourceId = $entity->getFacetSourceId();
+    $old_ids = ['views_page:', 'views_block:', 'views_rest:'];
+
+    foreach ($old_ids as $id) {
+      if (strpos($facetSourceId, $id) !== FALSE) {
+        $new_id = str_replace($id, 'search_api:', $facetSourceId);
+        $entity->setFacetSourceId($new_id);
+        $entity->save();
+      }
+    }
+  }
+}
diff --git a/facets.module b/facets.module
index 4bdd9f6..65daa1d 100644
--- a/facets.module
+++ b/facets.module
@@ -61,8 +61,11 @@ function facets_search_api_query_alter(QueryInterface &$query) {
 
     $search_id = $query->getSearchId();
 
+    $search_id_array = explode(':', $search_id);
+    $facet_source = 'search_api:' . $search_id_array[1];
+
     // Add the active filters.
-    $facet_manager->alterQuery($query, $search_id);
+    $facet_manager->alterQuery($query, $facet_source);
   }
 }
 
@@ -88,7 +91,7 @@ function facets_entity_presave(EntityInterface $entity) {
         // Check if the current display is also a facet source plugin and that
         // is removed from the view. We use the double underscore here to make
         // sure that we use core convention of "plugin:derived_plugin".
-        $facets_source_plugin_id = 'views_page:' . $entity->id() . '__' . $display['id'];
+        $facets_source_plugin_id = 'search_api:' . $entity->id() . '__' . $display['id'];
         if (array_key_exists($facets_source_plugin_id, $definitions) && !array_key_exists($k, $entity->get('display'))) {
           $entity_id = str_replace(':', '__', $facets_source_plugin_id);
           $source_entity = FacetSource::load($entity_id);
@@ -152,7 +155,7 @@ function facets_entity_predelete(EntityInterface $entity) {
     }
 
     foreach ($definitions as $plugin_id => $definition) {
-      if (strpos($plugin_id, 'views_page:' . $entity->id() . '__') !== FALSE) {
+      if (strpos($plugin_id, 'search_api:' . $entity->id() . '__') !== FALSE) {
         try {
           $facetManager = \Drupal::getContainer()->get('facets.manager');
         } catch (ServiceNotFoundException $e) {
diff --git a/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSource.php b/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSource.php
index 811e44a..46a4071 100644
--- a/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSource.php
+++ b/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSource.php
@@ -3,6 +3,7 @@
 namespace Drupal\core_search_facets\Plugin\facets\facet_source;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
 use Drupal\core_search_facets\Plugin\CoreSearchFacetSourceInterface;
 use Drupal\facets\FacetInterface;
 use Drupal\facets\FacetSource\FacetSourcePluginBase;
@@ -110,9 +111,9 @@ class CoreNodeSearchFacetSource extends FacetSourcePluginBase implements CoreSea
   public function getPath() {
     $search_page = $this->request->attributes->get('entity');
     if ($search_page instanceof SearchPageInterface) {
-      return '/search/' . $search_page->getPath();
+      return Url::fromUserInput('/search/' . $search_page->getPath());
     }
-    return '/';
+    return Url::fromUserInput('/');
   }
 
   /**
diff --git a/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSourceDeriver.php b/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSourceDeriver.php
index ba9d5f5..abce0f1 100644
--- a/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSourceDeriver.php
+++ b/modules/core_search_facets/src/Plugin/facets/facet_source/CoreNodeSearchFacetSourceDeriver.php
@@ -67,6 +67,7 @@ class CoreNodeSearchFacetSourceDeriver extends FacetSourceDeriverBase {
             'id' => $base_plugin_id . PluginBase::DERIVATIVE_SEPARATOR . $machine_name,
             'label' => $this->t('Core Search Page: %page_name', ['%page_name' => $page->get('label')]),
             'description' => $this->t('Provides a facet source.'),
+            'display_id' => $machine_name,
           ] + $base_plugin_definition;
         }
         uasort($plugin_derivatives, array($this, 'compareDerivatives'));
diff --git a/modules/rest_facets/rest_facets.info.yml b/modules/rest_facets/rest_facets.info.yml
index 6d53c5a..51181e1 100644
--- a/modules/rest_facets/rest_facets.info.yml
+++ b/modules/rest_facets/rest_facets.info.yml
@@ -5,6 +5,7 @@ core: 8.x
 package: Search
 dependencies:
   - facets:facets
+  - drupal:rest
 test_dependencies:
   - search_api:search_api
   - facets:facets
diff --git a/modules/rest_facets/src/Plugin/views/style/FacetsSerializer.php b/modules/rest_facets/src/Plugin/views/style/FacetsSerializer.php
index 5c4a1d3..fd0b239 100644
--- a/modules/rest_facets/src/Plugin/views/style/FacetsSerializer.php
+++ b/modules/rest_facets/src/Plugin/views/style/FacetsSerializer.php
@@ -24,7 +24,7 @@ class FacetsSerializer extends Serializer {
   /**
    * Tha facet manager.
    *
-   * @var DefaultFacetManager
+   * @var \Drupal\facets\FacetManager\DefaultFacetManager
    */
   protected $facetsManager;
 
@@ -80,7 +80,7 @@ class FacetsSerializer extends Serializer {
     }
 
     // Processing facets.
-    $facetsource_id = "views_page:{$this->view->id()}__{$this->view->getDisplay()->display['id']}";
+    $facetsource_id = "search_api:{$this->view->id()}__{$this->view->getDisplay()->display['id']}";
     $facets = $this->facetsManager->getFacetsByFacetSourceId($facetsource_id);
     $this->facetsManager->updateResults($facetsource_id);
 
diff --git a/modules/rest_facets/tests/src/Functional/RestIntegrationTest.php b/modules/rest_facets/tests/src/Functional/RestIntegrationTest.php
index addac17..48a0dac 100644
--- a/modules/rest_facets/tests/src/Functional/RestIntegrationTest.php
+++ b/modules/rest_facets/tests/src/Functional/RestIntegrationTest.php
@@ -79,6 +79,7 @@ class RestIntegrationTest extends FacetsTestBase {
     $values['facet_sorting[display_value_widget_order][status]'] = FALSE;
     $values['facet_sorting[active_widget_order][status]'] = FALSE;
     $values['facet_settings[query_operator]'] = 'or';
+    $values['facet_settings[only_visible_when_facet_source_is_visible]'] = FALSE;
 
     $this->drupalPostForm(NULL, $values, $this->t('Save'));
 
diff --git a/src/FacetManager/DefaultFacetManager.php b/src/FacetManager/DefaultFacetManager.php
index f6bbd97..2540ded 100644
--- a/src/FacetManager/DefaultFacetManager.php
+++ b/src/FacetManager/DefaultFacetManager.php
@@ -146,6 +146,10 @@ class DefaultFacetManager {
    *   The facet source ID to process.
    */
   public function alterQuery(&$query, $facetsource_id) {
+    if ($this->getFacetsByFacetSourceId($facetsource_id) === []) {
+      return;
+    }
+
     /** @var \Drupal\facets\FacetInterface[] $facets */
     foreach ($this->getFacetsByFacetSourceId($facetsource_id) as $facet) {
       /** @var \Drupal\facets\QueryType\QueryTypeInterface $query_type_plugin */
diff --git a/src/FacetSource/FacetSourcePluginInterface.php b/src/FacetSource/FacetSourcePluginInterface.php
index 698b365..0ff262d 100644
--- a/src/FacetSource/FacetSourcePluginInterface.php
+++ b/src/FacetSource/FacetSourcePluginInterface.php
@@ -40,10 +40,10 @@ interface FacetSourcePluginInterface extends PluginFormInterface, DependentPlugi
   public function getQueryTypesForFacet(FacetInterface $facet);
 
   /**
-   * Returns the path where a facet should link to.
+   * Returns the url of the facet source, used to build the facet url.
    *
-   * @return string
-   *   The path of the facet.
+   * @return \Drupal\Core\Url|NULL
+   *   The path of the facet if it's set, Null if no path can be created.
    */
   public function getPath();
 
diff --git a/src/FacetSource/FacetSourcePluginManager.php b/src/FacetSource/FacetSourcePluginManager.php
index 4f4146a..9731e2c 100644
--- a/src/FacetSource/FacetSourcePluginManager.php
+++ b/src/FacetSource/FacetSourcePluginManager.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\facets\FacetSource;
 
+use Drupal\Component\Plugin\Exception\PluginException;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
@@ -22,4 +23,30 @@ class FacetSourcePluginManager extends DefaultPluginManager {
     parent::__construct('Plugin/facets/facet_source', $namespaces, $module_handler, 'Drupal\facets\FacetSource\FacetSourcePluginInterface', 'Drupal\facets\Annotation\FacetsFacetSource');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function processDefinition(&$definition, $plugin_id) {
+    parent::processDefinition($definition, $plugin_id);
+
+    // At the very least - we need to have an ID in the definition of the
+    // plugin.
+    if (!isset($definition['id'])) {
+      throw new PluginException(sprintf('The facet source plugin %s must define the id property.', $plugin_id));
+    }
+
+    // If we're checking the search api plugin, only try to add it if search api
+    // is enabled.
+    if ($definition['id'] === 'search_api' && !$this->moduleHandler->moduleExists('search_api')) {
+      return;
+    }
+
+    // Check that other required labels are available.
+    foreach (['display_id', 'label'] as $required_property) {
+      if (empty($definition[$required_property])) {
+        throw new PluginException(sprintf('The facet source plugin %s must define the %s property.', $plugin_id, $required_property));
+      }
+    }
+  }
+
 }
diff --git a/src/Plugin/facets/facet_source/SearchApiDisplayDeriver.php b/src/Plugin/facets/facet_source/SearchApiDisplayDeriver.php
new file mode 100644
index 0000000..69710c9
--- /dev/null
+++ b/src/Plugin/facets/facet_source/SearchApiDisplayDeriver.php
@@ -0,0 +1,52 @@
+<?php
+
+namespace Drupal\facets\Plugin\facets\facet_source;
+
+use Drupal\Component\Plugin\PluginBase;
+use Drupal\facets\FacetSource\FacetSourceDeriverBase;
+
+/**
+ * Derives a facet source plugin definition for every Search API display plugin.
+ *
+ * This facet source supports all search api display sources.
+ *
+ * @see \Drupal\facets\Plugin\facets\facet_source\SearchApi
+ */
+class SearchApiDisplayDeriver extends FacetSourceDeriverBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    $base_plugin_id = $base_plugin_definition['id'];
+    $plugin_derivatives = array();
+
+    $display_plugin_manager = $this->getSearchApiDisplayPluginManager();
+    foreach ($display_plugin_manager->getInstances() as $display_id => $display) {
+      $machine_name = $display->getDerivativeId();
+
+      $supports_facets = $display->getIndex()
+        ->getServerInstance()
+        ->supportsFeature('search_api_facets');
+
+      // If facets are not supported by the server, don't actually add this to
+      // the list of plugins.
+      if (!$supports_facets) {
+        continue;
+      }
+
+      $plugin_derivatives[$machine_name] = [
+        'id' => $base_plugin_id . PluginBase::DERIVATIVE_SEPARATOR . $machine_name,
+        'display_id' => $display_id,
+        'label' => $display->label(),
+        'description' => $display->getDescription(),
+      ] + $base_plugin_definition;
+    }
+
+    uasort($plugin_derivatives, [$this, 'compareDerivatives']);
+
+    $this->derivatives[$base_plugin_id] = $plugin_derivatives;
+    return $this->derivatives[$base_plugin_id];
+  }
+
+}
diff --git a/src/Plugin/facets/facet_source/SearchApiBaseFacetSource.php b/src/Plugin/facets/facet_source/SearchApiFacetSource.php
similarity index 51%
rename from src/Plugin/facets/facet_source/SearchApiBaseFacetSource.php
rename to src/Plugin/facets/facet_source/SearchApiFacetSource.php
index 2a270db..f327453 100644
--- a/src/Plugin/facets/facet_source/SearchApiBaseFacetSource.php
+++ b/src/Plugin/facets/facet_source/SearchApiFacetSource.php
@@ -2,29 +2,65 @@
 
 namespace Drupal\facets\Plugin\facets\facet_source;
 
+use Drupal\Component\Plugin\DependentPluginInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\facets\Exception\InvalidQueryTypeException;
 use Drupal\facets\FacetInterface;
-use Drupal\search_api\Backend\BackendInterface;
 use Drupal\facets\FacetSource\FacetSourcePluginBase;
+use Drupal\facets\QueryType\QueryTypePluginManager;
+use Drupal\search_api\Backend\BackendInterface;
+use Drupal\search_api\Display\DisplayPluginManager;
 use Drupal\search_api\FacetsQueryTypeMappingInterface;
+use Drupal\search_api\Query\ResultSetInterface;
 use Drupal\search_api\Utility\QueryHelper;
-use Drupal\facets\QueryType\QueryTypePluginManager;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
- * A base class for Search API facet sources.
+ * Provides a facet source based on a Search API display.
+ *
+ * @FacetsFacetSource(
+ *   id = "search_api",
+ *   deriver = "Drupal\facets\Plugin\facets\facet_source\SearchApiDisplayDeriver"
+ * )
  */
-abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
+class SearchApiFacetSource extends FacetSourcePluginBase {
 
   /**
-   * The search index.
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManager|null
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The typed data manager.
+   *
+   * @var \Drupal\Core\TypedData\TypedDataManager|null
+   */
+  protected $typedDataManager;
+
+  /**
+   * The config factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactoryInterface|null
+   */
+  protected $configFactory;
+
+  /**
+   * The search index the query should is executed on.
    *
    * @var \Drupal\search_api\IndexInterface
    */
   protected $index;
 
   /**
+   * The display plugin manager.
+   *
+   * @var \Drupal\search_api\Display\DisplayPluginManager
+   */
+  protected $displayPluginManager;
+
+  /**
    * The search result cache.
    *
    * @var \Drupal\search_api\Utility\QueryHelper
@@ -44,16 +80,14 @@ abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
    *   The query type plugin manager.
    * @param \Drupal\search_api\Utility\QueryHelper $search_results_cache
    *   The query type plugin manager.
+   * @param \Drupal\search_api\Display\DisplayPluginManager $display_plugin_manager
+   *   The display plugin manager.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, QueryTypePluginManager $query_type_plugin_manager, QueryHelper $search_results_cache) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, QueryTypePluginManager $query_type_plugin_manager, QueryHelper $search_results_cache, DisplayPluginManager $display_plugin_manager) {
     parent::__construct($configuration, $plugin_id, $plugin_definition, $query_type_plugin_manager);
-    // Since defaultConfiguration() depends on the plugin definition, we need to
-    // override the constructor and set the definition property before calling
-    // that method.
-    $this->pluginDefinition = $plugin_definition;
-    $this->pluginId = $plugin_id;
-    $this->configuration = $configuration;
+
     $this->searchApiQueryHelper = $search_results_cache;
+    $this->displayPluginManager = $display_plugin_manager;
   }
 
   /**
@@ -65,15 +99,93 @@ abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
       $plugin_id,
       $plugin_definition,
       $container->get('plugin.manager.facets.query_type'),
-      $container->get('search_api.query_helper')
+      $container->get('search_api.query_helper'),
+      $container->get('plugin.manager.search_api.display')
     );
   }
 
   /**
+   * Retrieves the Search API index for this facet source.
+   *
+   * @return \Drupal\search_api\IndexInterface
+   *   The search index.
+   */
+  public function getIndex() {
+    if ($this->index === NULL) {
+      $this->index = $this->getDisplay()->getIndex();
+    }
+
+    return $this->index;
+  }
+
+  /**
    * {@inheritdoc}
    */
-  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+  public function getPath() {
+    return $this->getDisplay()->getUrl();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fillFacetsWithResults(array $facets) {
+    // Check if there are results in the static cache.
+    $search_id = $this->getDisplay()->getPluginId();
+    $results = $this->searchApiQueryHelper->getResults($search_id);
+
+    if ($results === NULL) {
+      // @todo: FIGURE OUT WHY WE NEED THIS SHIT.
+      // It looks like the getPluginId is
+      // "views_rest:search_content__rest_export_1" and the derivative id is
+      // "views_page:search_content__rest_export_1".
+      // It looks like another plugin is creating the display.
+      $ar = $this->searchApiQueryHelper->getAllResults();
+      $der_id = $this->getDisplay()->getDerivativeId();
+
+      foreach ($ar as $k => $res) {
+        if (strpos($k, $der_id) !== FALSE) {
+          $results = $res;
+        }
+      }
+      // END.
+    }
+
+    // Get the results from the cache. It is possible it still errored out.
+    if ($results instanceof ResultSetInterface) {
+      // Get our facet data.
+      $facet_results = $results->getExtraData('search_api_facets');
+      if ($facet_results === []) {
+        return;
+      }
+
+      // Loop over each facet and execute the build method from the given
+      // query type.
+      foreach ($facets as $facet) {
+        $configuration = array(
+          'query' => NULL,
+          'facet' => $facet,
+          'results' => isset($facet_results[$facet->getFieldIdentifier()]) ? $facet_results[$facet->getFieldIdentifier()] : [],
+        );
+
+        // Get the Facet Specific Query Type so we can process the results
+        // using the build() function of the query type.
+        $query_type = $this->queryTypePluginManager->createInstance($facet->getQueryType(), $configuration);
+        $query_type->build();
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isRenderedInCurrentRequest() {
+    return $this->getDisplay()->isRenderedInCurrentRequest();
+  }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
     $form['field_identifier'] = [
       '#type' => 'select',
       '#options' => $this->getFields(),
@@ -91,13 +203,17 @@ abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
    */
   public function getFields() {
     $indexed_fields = [];
-    $fields = $this->index->getFields();
+    /** @var \Drupal\search_api\IndexInterface $index */
+    $index = $this->getIndex();
+
+    $fields = $index->getFields();
     // Get the Search API Server.
-    $server = $this->index->getServerInstance();
+    $server = $index->getServerInstance();
     // Get the Search API Backend.
     $backend = $server->getBackend();
     foreach ($fields as $field) {
-      $query_types = $this->getQueryTypesForDataType($backend, $field->getDataTypePlugin()->getPluginId());
+      $query_types = $this->getQueryTypesForDataType($backend, $field->getDataTypePlugin()
+        ->getPluginId());
       if (!empty($query_types)) {
         $indexed_fields[$field->getFieldIdentifier()] = $field->getLabel() . ' (' . $field->getPropertyPath() . ')';
       }
@@ -112,12 +228,14 @@ abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
     // Get our Facets Field Identifier, which is equal to the Search API Field
     // identifier.
     $field_id = $facet->getFieldIdentifier();
+    /** @var \Drupal\search_api\IndexInterface $index */
+    $index = $this->getIndex();
     // Get the Search API Server.
-    $server = $this->index->getServerInstance();
+    $server = $index->getServerInstance();
     // Get the Search API Backend.
     $backend = $server->getBackend();
 
-    $fields = $this->index->getFields();
+    $fields = $index->getFields();
     foreach ($fields as $field) {
       if ($field->getFieldIdentifier() == $field_id) {
         return $this->getQueryTypesForDataType($backend, $field->getType());
@@ -165,20 +283,42 @@ abstract class SearchApiBaseFacetSource extends FacetSourcePluginBase {
     // Find out if the backend implemented the Interface to retrieve specific
     // query types for the supported data_types.
     if ($backend instanceof FacetsQueryTypeMappingInterface) {
-      // If the input arrays have the same string keys, then the later value
-      // for that key will overwrite the previous one. If, however, the arrays
-      // contain numeric keys, the later value will not overwrite the original
-      // value, but will be appended.
-      $query_types = array_merge($query_types, $backend->getQueryTypesForDataType($data_type_plugin_id));
+      $mapping = [
+        $data_type_plugin_id => &$query_types,
+      ];
+      $backend->alterFacetQueryTypeMapping($mapping);
     }
     // Add it to a variable so we can pass it by reference. Alter hook complains
     // due to the property of the backend object is not passable by reference.
     $backend_plugin_id = $backend->getPluginId();
 
     // Let modules alter this mapping.
-    \Drupal::moduleHandler()->alter('facets_search_api_query_type_mapping', $backend_plugin_id, $query_types);
+    \Drupal::moduleHandler()
+      ->alter('facets_search_api_query_type_mapping', $backend_plugin_id, $query_types);
 
     return $query_types;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function calculateDependencies() {
+    $display = $this->getDisplay();
+    if ($display instanceof DependentPluginInterface) {
+      return $display->calculateDependencies();
+    }
+    return [];
+  }
+
+  /**
+   * Retrieves the Search API display plugin associated with this facet source.
+   *
+   * @return \Drupal\search_api\Display\DisplayInterface
+   *   The Search API display plugin associated with this facet source.
+   */
+  protected function getDisplay() {
+    return $this->displayPluginManager
+      ->createInstance($this->pluginDefinition['display_id']);
+  }
+
 }
diff --git a/src/Plugin/facets/facet_source/SearchApiViews.php b/src/Plugin/facets/facet_source/SearchApiViews.php
deleted file mode 100644
index 755949b..0000000
--- a/src/Plugin/facets/facet_source/SearchApiViews.php
+++ /dev/null
@@ -1,184 +0,0 @@
-<?php
-
-namespace Drupal\facets\Plugin\facets\facet_source;
-
-use Drupal\facets\FacetSource\SearchApiFacetSourceInterface;
-use Drupal\search_api\Plugin\views\query\SearchApiQuery;
-use Drupal\search_api\Query\ResultSetInterface;
-use Drupal\views\Entity\View;
-use Drupal\views\Views;
-
-/**
- * A facet source to support search api views trough display plugins.
- *
- * @FacetsFacetSource(
- *   id = "views_page",
- *   deriver = "Drupal\facets\Plugin\facets\facet_source\SearchApiViewsDeriver"
- * )
- */
-class SearchApiViews extends SearchApiBaseFacetSource implements SearchApiFacetSourceInterface {
-
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManager|null
-   */
-  protected $entityTypeManager;
-
-  /**
-   * The typed data manager.
-   *
-   * @var \Drupal\Core\TypedData\TypedDataManager|null
-   */
-  protected $typedDataManager;
-
-  /**
-   * The config factory.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface|null
-   */
-  protected $configFactory;
-
-  /**
-   * The search index the query should is executed on.
-   *
-   * @var \Drupal\search_api\IndexInterface
-   */
-  protected $index;
-
-  /**
-   * {@inheritdoc}
-   */
-  public function __construct(array $configuration, $plugin_id, array $plugin_definition, $query_type_plugin_manager, $search_results_cache) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition, $query_type_plugin_manager, $search_results_cache);
-
-    // Load facet plugin definition and depending on those settings; load the
-    // corresponding view with the correct view with the correct display set.
-    // Get that display's query so we can check if this is a Search API based
-    // view.
-    $view = Views::getView($plugin_definition['view_id']);
-    if (!empty($view)) {
-      $view->setDisplay($plugin_definition['view_display']);
-      $query = $view->getQuery();
-
-      // Only add the index if the $query is a Search API Query.
-      if ($query instanceof SearchApiQuery) {
-        // Set the Search API Index.
-        $this->index = $query->getIndex();
-      }
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getPath() {
-    $display = View::load($this->pluginDefinition['view_id'])->getDisplay($this->pluginDefinition['view_display']);
-    switch ($display['display_plugin']) {
-      case 'page':
-        $view = Views::getView($this->pluginDefinition['view_id']);
-        $view->setDisplay($this->pluginDefinition['view_display']);
-        return '/' . $view->getDisplay()->getPath();
-
-      case 'block':
-      default:
-        $current_path = \Drupal::service('path.current')->getPath();
-        if (\Drupal::moduleHandler()->moduleExists('path')) {
-          return \Drupal::service('path.alias_manager')->getAliasByPath($current_path);
-        }
-        else {
-          return $current_path;
-        }
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function fillFacetsWithResults(array $facets) {
-    // Check if there are results in the static cache.
-    $results = $this->searchApiQueryHelper->getResults($this->pluginId);
-
-    // If our results are not there, execute the view to get the results.
-    if ($results === NULL) {
-      // If there are no results, execute the view. and check for results again!
-      $view = Views::getView($this->pluginDefinition['view_id']);
-      $view->setDisplay($this->pluginDefinition['view_display']);
-      $view->execute();
-      $results = $this->searchApiQueryHelper->getResults($this->pluginId);
-    }
-
-    // Get the results from the cache. It is possible it still errored out.
-    if ($results instanceof ResultSetInterface) {
-      // Get our facet data.
-      $facet_results = $results->getExtraData('search_api_facets');
-      if ($facet_results === []) {
-        return;
-      }
-
-      // Loop over each facet and execute the build method from the given
-      // query type.
-      foreach ($facets as $facet) {
-        $configuration = array(
-          'query' => NULL,
-          'facet' => $facet,
-          'results' => isset($facet_results[$facet->getFieldIdentifier()]) ? $facet_results[$facet->getFieldIdentifier()] : [],
-        );
-
-        // Get the Facet Specific Query Type so we can process the results
-        // using the build() function of the query type.
-        $query_type = $this->queryTypePluginManager->createInstance($facet->getQueryType(), $configuration);
-        $query_type->build();
-      }
-    }
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function isRenderedInCurrentRequest() {
-    $display = View::load($this->pluginDefinition['view_id'])->getDisplay($this->pluginDefinition['view_display']);
-    switch ($display['display_plugin']) {
-      case 'rest_export':
-      case 'page':
-        $request = \Drupal::requestStack()->getMasterRequest();
-        if ($request->attributes->get('_controller') === 'Drupal\views\Routing\ViewPageController::handle') {
-          list(, $view) = explode(':', $this->getPluginId());
-          list($search_api_view_id, $search_api_view_display) = explode('__', $view);
-
-          if ($request->attributes->get('view_id') == $search_api_view_id && $request->attributes->get('display_id') == $search_api_view_display) {
-            return TRUE;
-          }
-        }
-        return FALSE;
-
-      case 'block':
-        // There is no way to know if a block is embedded on a page, because
-        // blocks can be rendered in isolation (see big_pipe, esi, ...). To be
-        // sure we're not disclosing information we're not sure about, we always
-        // return false.
-        return FALSE;
-    }
-    return FALSE;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getIndex() {
-    return $this->index;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function calculateDependencies() {
-    $plugin_id_array = explode(':', $this->pluginId);
-    list($view_id,) = explode('__', $plugin_id_array[1]);
-    return [
-      'config' => ['views.view.' . $view_id],
-      'module' => ['views'],
-    ];
-  }
-
-}
diff --git a/src/Plugin/facets/facet_source/SearchApiViewsDeriver.php b/src/Plugin/facets/facet_source/SearchApiViewsDeriver.php
deleted file mode 100644
index b6b6632..0000000
--- a/src/Plugin/facets/facet_source/SearchApiViewsDeriver.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-
-namespace Drupal\facets\Plugin\facets\facet_source;
-
-use Drupal\facets\FacetSource\FacetSourceDeriverBase;
-
-/**
- * Derives a facet source plugin definition for every Search API display plugin.
- *
- * This facet source supports all search api display sources.
- *
- * @see \Drupal\facets\Plugin\facets\facet_source\SearchApi
- */
-class SearchApiViewsDeriver extends FacetSourceDeriverBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getDerivativeDefinitions($base_plugin_definition) {
-    $base_plugin_id = $base_plugin_definition['id'];
-
-    $search_api_displays = $this->getSearchApiDisplayPluginManager();
-
-    $plugin_derivatives = array();
-    foreach ($search_api_displays->getDefinitions() as $display) {
-      // Avoid providing corrupted displays.
-      if (isset($display['view_id']) && isset($display['view_display']) && isset($display['label'])) {
-        $machine_name = $display['view_id'] . '__' . $display['view_display'];
-
-        $plugin_derivatives[$machine_name] = [
-          'id' => $base_plugin_id . ':' . $machine_name,
-          'label' => $display['label'],
-          'description' => $this->t('Provides a facet source.'),
-          'view_id' => $display['view_id'],
-          'view_display' => $display['view_display'],
-        ] + $base_plugin_definition;
-
-        $arguments = [
-          '%view' => $display['label'],
-          '%display' => $display['view_display'],
-        ];
-        $sources[] = $this->t('Search API view: %view, display: %display', $arguments);
-      }
-    }
-
-    uasort($plugin_derivatives, array($this, 'compareDerivatives'));
-
-    $this->derivatives[$base_plugin_id] = $plugin_derivatives;
-    return $this->derivatives[$base_plugin_id];
-  }
-
-}
diff --git a/src/Plugin/facets/url_processor/QueryString.php b/src/Plugin/facets/url_processor/QueryString.php
index aacc644..0e3f56c 100644
--- a/src/Plugin/facets/url_processor/QueryString.php
+++ b/src/Plugin/facets/url_processor/QueryString.php
@@ -68,15 +68,16 @@ class QueryString extends UrlProcessorPluginBase {
     // Set the url alias from the the facet object.
     $this->urlAlias = $facet->getUrlAlias();
 
-    $request = $this->request;
-    if ($facet->getFacetSource()->getPath()) {
-      $request = Request::create($facet->getFacetSource()->getPath());
+    if ($facet->getFacetSource()->getPath() instanceof Url) {
+      $url = $facet->getFacetSource()->getPath();
     }
+    else {
+      $url = Url::createFromRequest($this->request);
+    }
+    $url->setOption('attributes', ['rel' => 'nofollow']);
+
     /** @var \Drupal\facets\Result\ResultInterface[] $results */
     foreach ($results as &$result) {
-      // Reset the URL for each result.
-      $url = Url::createFromRequest($request);
-      $url->setOption('attributes', ['rel' => 'nofollow']);
       // Sets the url for children.
       if ($children = $result->getChildren()) {
         $this->buildUrls($facet, $children);
@@ -133,12 +134,12 @@ class QueryString extends UrlProcessorPluginBase {
 
       $result_get_params->set($this->filterKey, array_values($filter_params));
 
-      $url = clone $url;
+      $new_url = clone $url;
       if ($result_get_params->all() !== [$this->filterKey => []]) {
-        $url->setOption('query', $result_get_params->all());
+        $new_url->setOption('query', $result_get_params->all());
       }
 
-      $result->setUrl($url);
+      $result->setUrl($new_url);
     }
 
     // Restore page parameter again. See https://www.drupal.org/node/2726455.
diff --git a/tests/facets_query_processor/src/Plugin/facets/url_processor/DummyQuery.php b/tests/facets_query_processor/src/Plugin/facets/url_processor/DummyQuery.php
index 8eead55..8e518c9 100644
--- a/tests/facets_query_processor/src/Plugin/facets/url_processor/DummyQuery.php
+++ b/tests/facets_query_processor/src/Plugin/facets/url_processor/DummyQuery.php
@@ -82,11 +82,14 @@ class DummyQuery extends UrlProcessorPluginBase {
       }
 
       $result_get_params->set($this->filterKey, $filter_params);
-      $request = $this->request;
-      if ($facet->getFacetSource()->getPath()) {
-        $request = Request::create($facet->getFacetSource()->getPath());
+
+      if ($facet->getFacetSource()->getPath() instanceof Url) {
+        $url = $facet->getFacetSource()->getPath();
+      }
+      else {
+        $url = Url::createFromRequest($this->request);
       }
-      $url = Url::createFromRequest($request);
+
       $url->setOption('query', $result_get_params->all());
 
       $result->setUrl($url);
diff --git a/tests/src/Functional/BlockTestTrait.php b/tests/src/Functional/BlockTestTrait.php
index aedc178..ffb9c22 100644
--- a/tests/src/Functional/BlockTestTrait.php
+++ b/tests/src/Functional/BlockTestTrait.php
@@ -33,12 +33,12 @@ trait BlockTestTrait {
 
     $this->drupalGet($facet_add_page);
 
-    $facet_source = "views_page:{$source}__{$display_id}";
+    $facet_source = "search_api:{$source}__{$display_id}";
     $form_values = [
       'id' => $id,
       'name' => $name,
       'facet_source_id' => $facet_source,
-      "facet_source_configs[views_page:{$source}__{$display_id}][field_identifier]" => $field,
+      "facet_source_configs[search_api:{$source}__{$display_id}][field_identifier]" => $field,
     ];
     $this->drupalPostForm(NULL, ['facet_source_id' => $facet_source], 'Configure facet source');
     $this->drupalPostForm(NULL, $form_values, 'Save');
diff --git a/tests/src/Functional/FacetSourceTest.php b/tests/src/Functional/FacetSourceTest.php
index 7db5756..cbfdc57 100644
--- a/tests/src/Functional/FacetSourceTest.php
+++ b/tests/src/Functional/FacetSourceTest.php
@@ -49,7 +49,7 @@ class FacetSourceTest extends FacetsTestBase {
     $this->assertResponse(200);
 
     $this->assertUrl('admin/config/search/facets');
-    $this->assertText('Facet source views_page:search_api_test_view__block_1 has been saved.');
+    $this->assertText('Facet source search_api:search_api_test_view__block_1 has been saved.');
     $this->clickLink('Configure');
 
     // Test that saving worked filter_key has the new value.
@@ -72,7 +72,7 @@ class FacetSourceTest extends FacetsTestBase {
     $this->assertResponse(200);
 
     $this->assertUrl('admin/config/search/facets');
-    $this->assertText('Facet source views_page:search_api_test_view__block_1 has been saved.');
+    $this->assertText('Facet source search_api:search_api_test_view__block_1 has been saved.');
     $this->clickLink('Configure');
 
     // Test that saving worked and that the url processor has the new value.
diff --git a/tests/src/Functional/IntegrationTest.php b/tests/src/Functional/IntegrationTest.php
index 51554be..0dde302 100644
--- a/tests/src/Functional/IntegrationTest.php
+++ b/tests/src/Functional/IntegrationTest.php
@@ -348,13 +348,13 @@ class IntegrationTest extends FacetsTestBase {
 
     // Configure the facet source by selecting one of the Search API views.
     $this->drupalGet($facet_add_page);
-    $this->drupalPostForm(NULL, ['facet_source_id' => 'views_page:search_api_test_view__page_1'], 'Configure facet source');
+    $this->drupalPostForm(NULL, ['facet_source_id' => 'search_api:search_api_test_view__page_1'], 'Configure facet source');
 
     // Fill in all fields and make sure the 'field is required' message is no
     // longer shown.
     $facet_source_form = [
-      'facet_source_id' => 'views_page:search_api_test_view__page_1',
-      'facet_source_configs[views_page:search_api_test_view__page_1][field_identifier]' => 'type',
+      'facet_source_id' => 'search_api:search_api_test_view__page_1',
+      'facet_source_configs[search_api:search_api_test_view__page_1][field_identifier]' => 'type',
     ];
     $this->drupalPostForm(NULL, $facet_source_form, 'Save');
 
@@ -542,8 +542,8 @@ class IntegrationTest extends FacetsTestBase {
     $this->assertResponse(200);
 
     // Check that the expected facet sources and the owl facet are shown.
-    $this->assertText('views_page:search_api_test_view__block_1');
-    $this->assertText('views_page:search_api_test_view__page_1');
+    $this->assertText('search_api:search_api_test_view__block_1');
+    $this->assertText('search_api:search_api_test_view__page_1');
     $this->assertText($name);
 
     // Delete the view on which both facet sources are based.
@@ -554,8 +554,8 @@ class IntegrationTest extends FacetsTestBase {
     // and the facet/facet source are deleted.
     $this->drupalGet('/admin/config/search/facets');
     $this->assertResponse(200);
-    $this->assertNoText('views_page:search_api_test_view__page_1');
-    $this->assertNoText('views_page:search_api_test_view__block_1');
+    $this->assertNoText('search_api:search_api_test_view__page_1');
+    $this->assertNoText('search_api:search_api_test_view__block_1');
     $this->assertNoText($name);
   }
 
@@ -582,8 +582,8 @@ class IntegrationTest extends FacetsTestBase {
     $this->assertResponse(200);
 
     // Check that the expected facet sources and the owl facet are shown.
-    $this->assertText('views_page:search_api_test_view__block_1');
-    $this->assertText('views_page:search_api_test_view__page_1');
+    $this->assertText('search_api:search_api_test_view__block_1');
+    $this->assertText('search_api:search_api_test_view__page_1');
     $this->assertText($name);
 
     // Delete the view display for the page.
@@ -595,8 +595,8 @@ class IntegrationTest extends FacetsTestBase {
     // and the facet/facet source are deleted.
     $this->drupalGet('/admin/config/search/facets');
     $this->assertResponse(200);
-    $this->assertNoText('views_page:search_api_test_view__page_1');
-    $this->assertText('views_page:search_api_test_view__block_1');
+    $this->assertNoText('search_api:search_api_test_view__page_1');
+    $this->assertText('search_api:search_api_test_view__block_1');
     $this->assertNoText($name);
   }
 
@@ -731,8 +731,8 @@ class IntegrationTest extends FacetsTestBase {
     $this->assertNoText('Field:');
 
     // Check that the expected facet sources are shown.
-    $this->assertText('views_page:search_api_test_view__block_1');
-    $this->assertText('views_page:search_api_test_view__page_1');
+    $this->assertText('search_api:search_api_test_view__block_1');
+    $this->assertText('search_api:search_api_test_view__page_1');
   }
 
   /**
@@ -767,7 +767,7 @@ class IntegrationTest extends FacetsTestBase {
 
     // Configure the facet source by selecting one of the Search API views.
     $this->drupalGet($facet_add_page);
-    $this->drupalPostForm(NULL, ['facet_source_id' => 'views_page:search_api_test_view__page_1'], 'Configure facet source');
+    $this->drupalPostForm(NULL, ['facet_source_id' => 'search_api:search_api_test_view__page_1'], 'Configure facet source');
 
     // The field is still required.
     $this->drupalPostForm(NULL, $form_values, 'Save');
@@ -776,8 +776,8 @@ class IntegrationTest extends FacetsTestBase {
     // Fill in all fields and make sure the 'field is required' message is no
     // longer shown.
     $facet_source_form = [
-      'facet_source_id' => 'views_page:search_api_test_view__page_1',
-      'facet_source_configs[views_page:search_api_test_view__page_1][field_identifier]' => $facet_type,
+      'facet_source_id' => 'search_api:search_api_test_view__page_1',
+      'facet_source_configs[search_api:search_api_test_view__page_1][field_identifier]' => $facet_type,
     ];
     $this->drupalPostForm(NULL, $form_values + $facet_source_form, 'Save');
     $this->assertNoText('field is required.');
@@ -804,10 +804,10 @@ class IntegrationTest extends FacetsTestBase {
     $form_values = [
       'name' => $facet_name,
       'id' => $facet_id,
-      'facet_source_id' => 'views_page:search_api_test_view__page_1',
+      'facet_source_id' => 'search_api:search_api_test_view__page_1',
     ];
 
-    $facet_source_configs['facet_source_configs[views_page:search_api_test_view__page_1][field_identifier]'] = $facet_type;
+    $facet_source_configs['facet_source_configs[search_api:search_api_test_view__page_1][field_identifier]'] = $facet_type;
 
     // Try to submit a facet with a duplicate machine name after form rebuilding
     // via facet source submit.
diff --git a/tests/src/Functional/UrlIntegrationTest.php b/tests/src/Functional/UrlIntegrationTest.php
index ee64250..c3e9cc5 100644
--- a/tests/src/Functional/UrlIntegrationTest.php
+++ b/tests/src/Functional/UrlIntegrationTest.php
@@ -78,9 +78,6 @@ class UrlIntegrationTest extends FacetsTestBase {
     $this->assertTrue($config instanceof FacetSourceInterface);
     $this->assertEqual('f', $config->getFilterKey());
 
-    $facet = NULL;
-    $config = NULL;
-
     // Go to the only enabled facet source's config and change the filter key.
     $this->drupalGet('admin/config/search/facets');
     $this->clickLink('Configure', 1);
@@ -97,9 +94,6 @@ class UrlIntegrationTest extends FacetsTestBase {
     $this->assertTrue($config instanceof FacetSourceInterface);
     $this->assertEqual('y', $config->getFilterKey());
 
-    $facet = NULL;
-    $config = NULL;
-
     $url_2 = Url::fromUserInput('/search-api-test-fulltext', ['query' => ['y[0]' => 'facet:item']]);
     $this->checkClickedFacetUrl($url_2);
 
@@ -120,9 +114,6 @@ class UrlIntegrationTest extends FacetsTestBase {
     $this->assertTrue($config instanceof FacetSourceInterface);
     $this->assertEqual('y', $config->getFilterKey());
 
-    $facet = NULL;
-    $config = NULL;
-
     $url_3 = Url::fromUserInput('/search-api-test-fulltext', ['query' => ['y[0]' => 'facet||item']]);
     $this->checkClickedFacetUrl($url_3);
   }
diff --git a/tests/src/FunctionalJavascript/WidgetJSTest.php b/tests/src/FunctionalJavascript/WidgetJSTest.php
index e085958..b63abed 100644
--- a/tests/src/FunctionalJavascript/WidgetJSTest.php
+++ b/tests/src/FunctionalJavascript/WidgetJSTest.php
@@ -52,10 +52,10 @@ class WidgetJSTest extends JavascriptTestBase {
 
     // Select one of the options from the facet source dropdown and wait for the
     // result to show.
-    $page->selectFieldOption('edit-facet-source-id', 'views_page:search_api_test_view__page_1');
+    $page->selectFieldOption('edit-facet-source-id', 'search_api:search_api_test_view__page_1');
     $this->getSession()->wait(6000, "jQuery('.facet-source-field-wrapper').length > 0");
 
-    $page->selectFieldOption('facet_source_configs[views_page:search_api_test_view__page_1][field_identifier]', 'type');
+    $page->selectFieldOption('facet_source_configs[search_api:search_api_test_view__page_1][field_identifier]', 'type');
 
     // Check that after choosing the field, the name is already filled in.
     $field_value = $this->getSession()->getPage()->findField('edit-name')->getValue();
@@ -74,7 +74,7 @@ class WidgetJSTest extends JavascriptTestBase {
       'id' => $id,
       'name' => strtoupper($id),
       'url_alias' => $id,
-      'facet_source_id' => 'views_page:search_api_test_view__page_1',
+      'facet_source_id' => 'search_api:search_api_test_view__page_1',
       'field_identifier' => 'type',
       'empty_behavior' => ['behavior' => 'none'],
       'widget' => [
diff --git a/tests/src/Unit/FacetSource/FacetSourcePluginManagerTest.php b/tests/src/Unit/FacetSource/FacetSourcePluginManagerTest.php
index ad648d2..99de6ab 100644
--- a/tests/src/Unit/FacetSource/FacetSourcePluginManagerTest.php
+++ b/tests/src/Unit/FacetSource/FacetSourcePluginManagerTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\facets\Unit\FacetSource;
 
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+use Drupal\Component\Plugin\Exception\PluginException;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -83,22 +84,56 @@ class FacetSourcePluginManagerTest extends UnitTestCase {
   public function testConstruct() {
     $namespaces = new ArrayObject();
     $sut = new FacetSourcePluginManager($namespaces, $this->cache, $this->moduleHandler);
-    $this->assertInstanceOf('\Drupal\facets\FacetSource\FacetSourcePluginManager', $sut);
+    $this->assertInstanceOf(FacetSourcePluginManager::class, $sut);
   }
 
   /**
    * Tests plugin manager's getDefinitions method.
    */
   public function testGetDefinitions() {
-    $definitions = array(
-      'foo' => array(
-        'label' => $this->randomMachineName(),
-      ),
-    );
+    $definitions = [
+      'foo' => [
+        'id' => 'foo_bar',
+        'label' => 'Foo bar',
+        'description' => 'test',
+        'display_id' => 'foo',
+      ],
+    ];
     $this->discovery->expects($this->once())
       ->method('getDefinitions')
       ->willReturn($definitions);
     $this->assertSame($definitions, $this->sut->getDefinitions());
   }
 
+  /**
+   * Tests plugin manager definitions.
+   *
+   * @dataProvider invalidDefinitions
+   */
+  public function testInvalidDefinitions($invalid_definition) {
+    $definitions = ['foo' => [$invalid_definition]];
+
+    $this->discovery->expects($this->once())
+      ->method('getDefinitions')
+      ->willReturn($definitions);
+
+    $this->setExpectedException(PluginException::class);
+    $this->sut->getDefinitions();
+  }
+
+  /**
+   * Provides invalid definitions.
+   *
+   * @return array
+   *   An invalid data provider.
+   */
+  public function invalidDefinitions() {
+    return [
+      'only id' => ['id' => 'owl'],
+      'only display_id' => ['display_id' => 'search_api:owl'],
+      'only label' => ['label' => 'Owl'],
+      'no label' => ['id' => 'owl', 'display_id' => 'Owl']
+    ];
+  }
+
 }
diff --git a/tests/src/Unit/Plugin/url_processor/QueryStringTest.php b/tests/src/Unit/Plugin/url_processor/QueryStringTest.php
index 089dae1..40019f8 100644
--- a/tests/src/Unit/Plugin/url_processor/QueryStringTest.php
+++ b/tests/src/Unit/Plugin/url_processor/QueryStringTest.php
@@ -238,11 +238,13 @@ class QueryStringTest extends UnitTestCase {
         ]
       );
 
+    $validator = $this->getMock('Drupal\Core\Path\PathValidatorInterface');
+
     $fsi = $this->getMockBuilder('\Drupal\facets\FacetSource\FacetSourcePluginInterface')
       ->disableOriginalConstructor()
       ->getMock();
     $fsi->method('getPath')
-      ->willReturn('search/test');
+      ->willReturn('/search/test');
 
     $manager = $this->getMockBuilder('\Drupal\facets\FacetSource\FacetSourcePluginManager')
       ->disableOriginalConstructor()
@@ -266,6 +268,7 @@ class QueryStringTest extends UnitTestCase {
     $container->set('plugin.manager.facets.facet_source', $manager);
     $container->set('entity_type.manager', $em);
     $container->set('entity.manager', $em);
+    $container->set('path.validator', $validator);
     \Drupal::setContainer($container);
   }
 
