diff --git a/src/Entity/FeaturesBundle.php b/src/Entity/FeaturesBundle.php
index c06d31f..6e7b4cf 100644
--- a/src/Entity/FeaturesBundle.php
+++ b/src/Entity/FeaturesBundle.php
@@ -8,6 +8,7 @@
 namespace Drupal\features\Entity;
 
 use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\features\FeaturesAssigner;
 use Drupal\features\FeaturesBundleInterface;
 
 /**
@@ -205,6 +206,12 @@ class FeaturesBundle extends ConfigEntityBase implements FeaturesBundleInterface
    * {@inheritdoc}
    */
   public function setEnabledAssignments(array $assignments) {
+    // Add any new assignments that we don't yet know about.
+    $new_assignments = array_diff($assignments, array_keys($this->assignments));
+    foreach ($new_assignments as $method_id) {
+      $this->assignments[$method_id] = $this->getAssignmentSettings($method_id);
+    }
+
     foreach ($this->assignments as $method_id => &$method) {
       $method['enabled'] = in_array($method_id, $assignments);
     }
@@ -240,15 +247,19 @@ class FeaturesBundle extends ConfigEntityBase implements FeaturesBundleInterface
       if (isset($this->assignments[$method_id])) {
         return $this->assignments[$method_id];
       }
+      else {
+        // Use defaults.
+        $method = FeaturesAssigner::getAssignmentMethod($method_id);
+        return $method->getDefaultSettings();
+      }
     }
     else {
       $list = array();
-      foreach ($this->assignments as $method_id => $method) {
-        $list[$method_id] = $method;
+      foreach (array_keys($this->assignments) as $method_id) {
+        $list[$method_id] = $this->getAssignmentSettings($method_id);
       }
       return $list;
     }
-    return array();
   }
 
   /**
diff --git a/src/FeaturesAssigner.php b/src/FeaturesAssigner.php
index 45ad5ab..421b893 100644
--- a/src/FeaturesAssigner.php
+++ b/src/FeaturesAssigner.php
@@ -414,4 +414,12 @@ class FeaturesAssigner implements FeaturesAssignerInterface {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function getAssignmentMethod($method_id) {
+    $assigner = \Drupal::service('features_assigner');
+    return $assigner->getAssignmentMethodInstance($method_id);
+  }
+
 }
diff --git a/src/FeaturesAssignerInterface.php b/src/FeaturesAssignerInterface.php
index 950f2a8..40c176b 100644
--- a/src/FeaturesAssignerInterface.php
+++ b/src/FeaturesAssignerInterface.php
@@ -230,4 +230,15 @@ interface FeaturesAssignerInterface {
    */
   public function loadBundle($machine_name = NULL);
 
+  /**
+   * Get an assignment method plugin.
+   *
+   * @param string $method_id
+   *   The string identifier of the package assignment method.
+   *
+   * @return \Drupal\features\FeaturesAssignmentMethodInterface
+   *   The assignment method.
+   */
+  public static function getAssignmentMethod($method_id);
+
 }
diff --git a/src/FeaturesAssignmentMethodBase.php b/src/FeaturesAssignmentMethodBase.php
index bf8f6c7..05eebf2 100644
--- a/src/FeaturesAssignmentMethodBase.php
+++ b/src/FeaturesAssignmentMethodBase.php
@@ -9,14 +9,12 @@ namespace Drupal\features;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\Plugin\PluginBase;
 
 /**
  * Base class for package assignment methods.
  */
-abstract class FeaturesAssignmentMethodBase implements FeaturesAssignmentMethodInterface {
-  use StringTranslationTrait;
-
+abstract class FeaturesAssignmentMethodBase extends PluginBase implements FeaturesAssignmentMethodInterface {
   /**
    * The features manager.
    *
@@ -76,17 +74,15 @@ abstract class FeaturesAssignmentMethodBase implements FeaturesAssignmentMethodI
   /**
    * Assigns configuration of the types specified in a setting to a package.
    *
-   * @param string $method_id
-   *   The ID of an assignment method.
    * @param string $machine_name
    *   Machine name of the package.
    * @param bool $force
    *   (optional) If TRUE, assign config regardless of restrictions such as it
    *   being already assigned to a package.
    */
-  protected function assignPackageByConfigTypes($method_id, $machine_name, $force = FALSE) {
+  protected function assignPackageByConfigTypes($machine_name, $force = FALSE) {
     $current_bundle = $this->assigner->getBundle();
-    $settings = $current_bundle->getAssignmentSettings($method_id);
+    $settings = $current_bundle->getAssignmentSettings($this->getPluginId());
     $types = $settings['types']['config'];
 
     $config_collection = $this->featuresManager->getConfigCollection();
@@ -107,14 +103,12 @@ abstract class FeaturesAssignmentMethodBase implements FeaturesAssignmentMethodI
   /**
    * Assigns a given subdirectory to configuration of specified types.
    *
-   * @param string $method_id
-   *   The ID of an assignment method.
    * @param string $subdirectory
    *   The subdirectory that designated configuration should be exported to.
    */
-  protected function assignSubdirectoryByConfigTypes($method_id, $subdirectory) {
+  protected function assignSubdirectoryByConfigTypes($subdirectory) {
     $current_bundle = $this->assigner->getBundle();
-    $settings = $current_bundle->getAssignmentSettings($method_id);
+    $settings = $current_bundle->getAssignmentSettings($this->getPluginId());
     $types = $settings['types']['config'];
 
     $config_collection = $this->featuresManager->getConfigCollection();
@@ -130,4 +124,21 @@ abstract class FeaturesAssignmentMethodBase implements FeaturesAssignmentMethodI
     $this->featuresManager->setConfigCollection($config_collection);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getDefaultSettings() {
+    $settings = ['enabled' => FALSE, 'weight' => 0];
+
+    $definition = $this->getPluginDefinition();
+    if (isset($definition['weight'])) {
+      $settings['weight'] = $definition['weight'];
+    }
+    if (isset($definition['default_settings'])) {
+      $settings += $definition['default_settings'];
+    }
+
+    return $settings;
+  }
+
 }
diff --git a/src/FeaturesAssignmentMethodInterface.php b/src/FeaturesAssignmentMethodInterface.php
index a2b90ce..c6b88b4 100644
--- a/src/FeaturesAssignmentMethodInterface.php
+++ b/src/FeaturesAssignmentMethodInterface.php
@@ -7,13 +7,14 @@
 
 namespace Drupal\features;
 
+use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 
 /**
  * Interface for package assignment classes.
  */
-interface FeaturesAssignmentMethodInterface {
+interface FeaturesAssignmentMethodInterface extends PluginInspectionInterface {
 
   /**
    * Injects the features manager.
@@ -57,4 +58,12 @@ interface FeaturesAssignmentMethodInterface {
    */
   public function assignPackages($force = FALSE);
 
+  /**
+   * Get the default settings for this assignment.
+   *
+   * @return array
+   *   The settings.
+   */
+  public function getDefaultSettings();
+
 }
diff --git a/src/FeaturesBundleInterface.php b/src/FeaturesBundleInterface.php
index b067105..b80a55b 100644
--- a/src/FeaturesBundleInterface.php
+++ b/src/FeaturesBundleInterface.php
@@ -217,7 +217,7 @@ interface FeaturesBundleInterface {
    *
    * @see \Drupal\features\FeaturesBundleInterface::setAssignmentSettings()
    */
-  public function getAssignmentSettings($method_id);
+  public function getAssignmentSettings($method_id = NULL);
 
   /**
    * Sets settings specific to an assignment method.
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentBaseType.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentBaseType.php
index 6aae549..edb70a5 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentBaseType.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentBaseType.php
@@ -14,26 +14,26 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * Class for assigning configuration to packages based on entity types.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentBaseType::METHOD_ID,
+ *   id = "base",
  *   weight = -2,
  *   name = @Translation("Base type"),
  *   description = @Translation("Use designated types of configuration as the base for configuration package modules. For example, if content types are selected as a base type, a package will be generated for each content type and will include all configuration dependent on that content type."),
- *   config_route_name = "features.assignment_base"
+ *   config_route_name = "features.assignment_base",
+ *   default_settings = {
+ *     "types" = {
+ *       "config" = {},
+ *       "content" = {}
+ *     }
+ *   }
  * )
  */
 class FeaturesAssignmentBaseType extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'base';
-
   /**
    * {@inheritdoc}
    */
   public function assignPackages($force = FALSE) {
     $current_bundle = $this->assigner->getBundle();
-    $settings = $current_bundle->getAssignmentSettings(self::METHOD_ID);
+    $settings = $current_bundle->getAssignmentSettings($this->getPluginId());
     $config_base_types = $settings['types']['config'];
 
     $config_types = $this->featuresManager->listConfigTypes();
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentCoreType.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentCoreType.php
index 1239dae..c18f778 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentCoreType.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentCoreType.php
@@ -14,20 +14,19 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * Class for assigning configuration to a core package based on entity types.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentCoreType::METHOD_ID,
+ *   id = "core",
  *   weight = 5,
  *   name = @Translation("Core type"),
  *   description = @Translation("Assign designated types of configuration to a core configuration package module. For example, if image styles are selected as a core type, a core package will be generated and image styles will be assigned to it."),
- *   config_route_name = "features.assignment_core"
+ *   config_route_name = "features.assignment_core",
+ *   default_settings = {
+ *     "types" = {
+ *       "config" = {},
+ *     }
+ *   }
  * )
  */
 class FeaturesAssignmentCoreType extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'core';
-
   /**
    * {@inheritdoc}
    */
@@ -37,7 +36,8 @@ class FeaturesAssignmentCoreType extends FeaturesAssignmentMethodBase {
     $name = $this->t('Core');
     $description = $this->t('Provides core components required by other features.');
     $this->featuresManager->initPackage($machine_name, $name, $description, 'module', $current_bundle);
-    $this->assignPackageByConfigTypes(self::METHOD_ID, $machine_name, $force);
+    $this->assignPackageByConfigTypes($machine_name, $force);
   }
 
+
 }
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentDependency.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentDependency.php
index ee63c75..cac0055 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentDependency.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentDependency.php
@@ -14,19 +14,13 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * dependencies.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentDependency::METHOD_ID,
+ *   id = "dependency",
  *   weight = 15,
  *   name = @Translation("Dependency"),
  *   description = @Translation("Add to packages configuration dependent on items already in that package."),
  * )
  */
 class FeaturesAssignmentDependency extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'dependency';
-
   /**
    * {@inheritdoc}
    */
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentExclude.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentExclude.php
index 9790b5f..1ef01a3 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentExclude.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentExclude.php
@@ -13,26 +13,29 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * Class for excluding configuration from packages.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentExclude::METHOD_ID,
+ *   id = "exclude",
  *   weight = -5,
  *   name = @Translation("Exclude"),
  *   description = @Translation("Exclude configuration items from packaging by various methods including by configuration type."),
- *   config_route_name = "features.assignment_exclude"
+ *   config_route_name = "features.assignment_exclude",
+ *   default_settings = {
+ *     "curated" = FALSE,
+ *     "module" = {
+ *       "installed" = FALSE,
+ *       "profile" = FALSE,
+ *       "namespace" = FALSE,
+ *     },
+ *     "types" = { "config" = {} }
+ *   }
  * )
  */
 class FeaturesAssignmentExclude extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'exclude';
-
   /**
    * {@inheritdoc}
    */
   public function assignPackages($force = FALSE) {
     $current_bundle = $this->assigner->getBundle();
-    $settings = $current_bundle->getAssignmentSettings(self::METHOD_ID);
+    $settings = $current_bundle->getAssignmentSettings($this->getPluginId());
 
     $config_collection = $this->featuresManager->getConfigCollection();
 
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentExisting.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentExisting.php
index cc12de0..b39b98a 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentExisting.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentExisting.php
@@ -14,19 +14,13 @@ use Drupal\features\FeaturesManagerInterface;
  * Class for assigning existing modules to packages.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentExisting::METHOD_ID,
+ *   id = "existing",
  *   weight = 12,
  *   name = @Translation("Existing"),
  *   description = @Translation("Add exported config to existing packages."),
  * )
  */
 class FeaturesAssignmentExisting extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'existing';
-
   /**
    * Calls assignConfigPackage without allowing exceptions to abort us.
    *
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentForwardDependency.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentForwardDependency.php
index c90c7ab..7f42bc2 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentForwardDependency.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentForwardDependency.php
@@ -14,19 +14,13 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * Class for assigning configuration to packages based on forward dependencies.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentForwardDependency::METHOD_ID,
+ *   id = "forward_dependency",
  *   weight = 20,
  *   name = @Translation("Forward dependency"),
  *   description = @Translation("Add to packages configuration on which items in the package depend."),
  * )
  */
 class FeaturesAssignmentForwardDependency extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'forward_dependency';
-
   /**
    * {@inheritdoc}
    */
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentNamespace.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentNamespace.php
index d191cd1..9915c8d 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentNamespace.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentNamespace.php
@@ -13,19 +13,13 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * Class for assigning configuration to packages based on namespaces.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentNamespace::METHOD_ID,
+ *   id = "namespace",
  *   weight = 0,
  *   name = @Translation("Namespace"),
  *   description = @Translation("Add to packages configuration with a machine name containing that package's machine name."),
  * )
  */
 class FeaturesAssignmentNamespace extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'namespace';
-
   /**
    * {@inheritdoc}
    */
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentOptionalType.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentOptionalType.php
index 9ce8f3d..188572b 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentOptionalType.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentOptionalType.php
@@ -16,28 +16,24 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * InstallStorage::CONFIG_OPTIONAL_DIRECTORY based on entity types.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentOptionalType::METHOD_ID,
+ *   id = "optional",
  *   weight = 0,
  *   name = @Translation("Optional type"),
  *   description = @Translation("Assign designated types of configuration to the 'config/optional' install directory. For example, if views are selected as optional, views assigned to any feature will be exported to the 'config/optional' directory and will not create a dependency on the Views module."),
- *   config_route_name = "features.assignment_optional"
+ *   config_route_name = "features.assignment_optional",
+ *   default_settings = {
+ *     "types" = {
+ *       "config" = {},
+ *     }
+ *   }
  * )
  */
 class FeaturesAssignmentOptionalType extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'optional';
-
   /**
    * {@inheritdoc}
    */
   public function assignPackages($force = FALSE) {
-    $machine_name = 'optional';
-    $name = $this->t('Optional');
-    $description = $this->t('Provide optional components required by other features.');
-    $this->assignSubdirectoryByConfigTypes(self::METHOD_ID, InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
+    $this->assignSubdirectoryByConfigTypes(InstallStorage::CONFIG_OPTIONAL_DIRECTORY);
   }
 
 }
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php
index 1fa363c..65051aa 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php
@@ -13,19 +13,13 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * Class for assigning existing modules to packages.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentPackages::METHOD_ID,
+ *   id = "packages",
  *   weight = -20,
  *   name = @Translation("Packages"),
  *   description = @Translation("Detect and add existing package modules."),
  * )
  */
 class FeaturesAssignmentPackages extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'packages';
-
   /**
    * {@inheritdoc}
    */
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php
index b63b72d..383a1db 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php
@@ -14,20 +14,22 @@ use Drupal\Core\Config\InstallStorage;
  * Class for adding configuration for the optional install profile.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentProfile::METHOD_ID,
+ *   id = "profile",
  *   weight = 10,
  *   name = @Translation("Profile"),
  *   description = @Translation("Add configuration and other files to the optional install profile from the Drupal core Standard install profile. Without these additions, a generated install profile will be missing some important initial setup."),
- *   config_route_name = "features.assignment_profile"
+ *   config_route_name = "features.assignment_profile",
+ *   default_settings = {
+ *     "curated" = FALSE,
+ *     "standard" = {
+ *       "files" = FALSE,
+ *       "dependencies" = FALSE,
+ *     },
+ *     "types" = { "config" = {} }
+ *   }
  * )
  */
 class FeaturesAssignmentProfile extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'profile';
-
   /**
    * {@inheritdoc}
    */
@@ -35,7 +37,7 @@ class FeaturesAssignmentProfile extends FeaturesAssignmentMethodBase {
     $current_bundle = $this->assigner->getBundle();
 
     if ($current_bundle->isProfile()) {
-      $settings = $current_bundle->getAssignmentSettings(self::METHOD_ID);
+      $settings = $current_bundle->getAssignmentSettings($this->getPluginId());
 
       // Ensure the profile package exists.
       $profile_name = $current_bundle->getProfileName();
@@ -46,7 +48,7 @@ class FeaturesAssignmentProfile extends FeaturesAssignmentMethodBase {
       }
 
       // Assign configuration by type.
-      $this->assignPackageByConfigTypes(self::METHOD_ID, $profile_name, $force);
+      $this->assignPackageByConfigTypes($profile_name, $force);
 
       // Include a curated list of configuration.
       if ($settings['curated']) {
diff --git a/src/Plugin/FeaturesAssignment/FeaturesAssignmentSiteType.php b/src/Plugin/FeaturesAssignment/FeaturesAssignmentSiteType.php
index ec8cdc3..8295822 100644
--- a/src/Plugin/FeaturesAssignment/FeaturesAssignmentSiteType.php
+++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentSiteType.php
@@ -14,20 +14,19 @@ use Drupal\features\FeaturesAssignmentMethodBase;
  * Class for assigning configuration to a site package based on entity types.
  *
  * @Plugin(
- *   id = \Drupal\features\Plugin\FeaturesAssignment\FeaturesAssignmentSiteType::METHOD_ID,
+ *   id = "site",
  *   weight = 7,
  *   name = @Translation("Site type"),
  *   description = @Translation("Assign designated types of configuration to a site configuration package module. For example, if image styles are selected as a site type, a site package will be generated and image styles will be assigned to it."),
- *   config_route_name = "features.assignment_site"
+ *   config_route_name = "features.assignment_site",
+ *   default_settings = {
+ *     "types" = {
+ *       "config" = {},
+ *     }
+ *   }
  * )
  */
 class FeaturesAssignmentSiteType extends FeaturesAssignmentMethodBase {
-
-  /**
-   * The package assignment method id.
-   */
-  const METHOD_ID = 'site';
-
   /**
    * {@inheritdoc}
    */
@@ -37,7 +36,7 @@ class FeaturesAssignmentSiteType extends FeaturesAssignmentMethodBase {
     $name = $this->t('Site');
     $description = $this->t('Provides site components.');
     $this->featuresManager->initPackage($machine_name, $name, $description, 'module', $current_bundle);
-    $this->assignPackageByConfigTypes(self::METHOD_ID, $machine_name, $force);
+    $this->assignPackageByConfigTypes($machine_name, $force);
   }
 
 }
diff --git a/src/Tests/FeaturesBundleUITest.php b/src/Tests/FeaturesBundleUITest.php
new file mode 100644
index 0000000..9bb598e
--- /dev/null
+++ b/src/Tests/FeaturesBundleUITest.php
@@ -0,0 +1,193 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\features\Tests\FeaturesBundleUITest.
+ */
+
+namespace Drupal\features\Tests;
+
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\features\FeaturesBundleInterface;
+use Drupal\simpletest\WebTestBase;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Tests configuring bundles.
+ *
+ * @group features
+ */
+class FeaturesBundleUITest extends WebTestBase {
+  use StringTranslationTrait;
+
+  /**
+   * @todo Remove the disabled strict config schema checking.
+   */
+  protected $strictConfigSchema = FALSE;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['block', 'features', 'features_ui'];
+
+  /**
+   * The features bundle storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface $bundleStorage
+   */
+  protected $bundleStorage;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $this->bundleStorage = \Drupal::entityTypeManager()->getStorage('features_bundle');
+
+    $admin_user = $this->createUser(['administer site configuration', 'export configuration', 'administer modules']);
+    $this->drupalLogin($admin_user);
+    $this->drupalPlaceBlock('local_actions_block');
+  }
+
+  /**
+   * Get the default features bundle.
+   *
+   * @return \Drupal\features\FeaturesBundleInterface
+   *   The features bundle.
+   */
+  protected function defaultBundle() {
+    return $this->bundleStorage->load('default');
+  }
+
+  /**
+   * Completely remove a features assignment method from the bundle.
+   *
+   * @param string $method_id
+   *   The assignment method ID.
+   */
+  protected function removeAssignment($method_id) {
+    $bundle = $this->defaultBundle();
+    $assignments = $bundle->get('assignments');
+    unset($assignments[$method_id]);
+    $bundle->set('assignments', $assignments);
+    $bundle->save();
+  }
+
+  /**
+   * Tests configuring an assignment.
+   */
+  public function testAssignmentConfigure() {
+    // Check initial values.
+    $settings = $this->defaultBundle()->getAssignmentSettings('exclude');
+    $this->assertTrue(isset($settings['types']['config']['features_bundle']), 'Excluding features_bundle');
+    $this->assertFalse(isset($settings['types']['config']['system_simple']), 'Not excluding system_simple');
+    $this->assertFalse(isset($settings['types']['config']['user_role']), 'Not excluding user_role');
+    $this->assertTrue($settings['curated'], 'Excluding curated items');
+    $this->assertTrue($settings['module']['namespace'], 'Excluding by namespace');
+
+    // Check initial form.
+    $this->drupalGet('admin/config/development/features/bundle/_exclude/default');
+    $this->assertFieldChecked('edit-types-config-features-bundle', 'features_bundle is checked');
+    $this->assertNoFieldChecked('edit-types-config-system-simple', 'system_simple is not checked');
+    $this->assertNoFieldChecked('edit-types-config-user-role', 'user_role is not checked');
+    $this->assertFieldChecked('edit-curated', 'curated is checked');
+    $this->assertFieldChecked('edit-module-namespace', 'namespace is checked');
+
+    // Configure the form.
+    $this->drupalPostForm(NULL, [
+      'types[config][system_simple]' => TRUE,
+      'types[config][user_role]' => FALSE,
+      'curated' => TRUE,
+      'module[namespace]' => FALSE,
+    ], $this->t('Save settings'));
+
+    // Check form results.
+    $this->drupalGet('admin/config/development/features/bundle/_exclude/default');
+    $this->assertFieldChecked('edit-types-config-features-bundle', 'Saved, features_bundle is checked');
+    $this->assertFieldChecked('edit-types-config-system-simple', 'Saved, system_simple is checked');
+    $this->assertNoFieldChecked('edit-types-config-user-role', 'Saved, user_role is not checked');
+    $this->assertFieldChecked('edit-curated', 'Saved, curated is checked');
+    $this->assertNoFieldChecked('edit-module-namespace', 'Saved, namespace is not checked');
+
+    // Check final values.
+    $settings = $this->defaultBundle()->getAssignmentSettings('exclude');
+    $this->assertTrue(isset($settings['types']['config']['features_bundle']), 'Saved, excluding features_bundle');
+    $this->assertTrue(isset($settings['types']['config']['system_simple']), 'Saved, excluding system_simple');
+    $this->assertFalse(isset($settings['types']['config']['user_role']), 'Saved, not excluding user_role');
+    $this->assertTrue($settings['curated'], 'Saved, excluding curated items');
+    $this->assertFalse($settings['module']['namespace'], 'Saved, not excluding by namespace');
+  }
+
+  /**
+   * Tests configuring an assignment that didn't exist before.
+   */
+  public function testNewAssignmentConfigure() {
+    $this->removeAssignment('exclude');
+
+    // Is it really removed?
+    $all_settings = $this->defaultBundle()->getAssignmentSettings();
+    $this->assertFalse(isset($all_settings['exclude']), 'Exclude plugin is unknown');
+
+    // Can still get settings.
+    $settings = $this->defaultBundle()->getAssignmentSettings('exclude');
+    $this->assertFalse($settings['enabled'], 'Disabled exclude plugin');
+    $this->assertFalse(isset($settings['types']['config']['features_bundle']), 'Not excluding features_bundle');
+    $this->assertFalse(isset($settings['types']['config']['system_simple']), 'Not excluding system_simple');
+    $this->assertFalse(isset($settings['types']['config']['user_role']), 'Not excluding user_role');
+    $this->assertFalse($settings['curated'], 'Not excluding curated items');
+    $this->assertFalse($settings['module']['namespace'], 'Not excluding by namespace');
+
+    // Can we visit the config page with no settings?
+    $this->drupalGet('admin/config/development/features/bundle/_exclude/default');
+    $this->assertNoFieldChecked('edit-types-config-features-bundle', 'features_bundle is not checked');
+    $this->assertNoFieldChecked('edit-types-config-system-simple', 'system_simple is not checked');
+    $this->assertNoFieldChecked('edit-types-config-user-role', 'user_role is not checked');
+    $this->assertNoFieldChecked('edit-curated', 'curated is not checked');
+    $this->assertNoFieldChecked('edit-module-namespace', 'namespace is not checked');
+
+    // Can we enable the method?
+    $this->drupalGet('admin/config/development/features/bundle');
+    $this->assertNoFieldChecked('edit-enabled-exclude', 'Exclude disabled');
+    $this->drupalPostForm(NULL, [
+      'enabled[exclude]' => TRUE,
+    ], $this->t('Save settings'));
+    $this->assertFieldChecked('edit-enabled-exclude', 'Exclude enabled');
+
+    // Check new settings.
+    $settings = $this->defaultBundle()->getAssignmentSettings('exclude');
+    $this->assertTrue($settings['enabled'], 'Enabled exclude plugin');
+    $this->assertFalse(isset($settings['types']['config']['features_bundle']), 'Not excluding features_bundle');
+    $this->assertFalse(isset($settings['types']['config']['system_simple']), 'Not excluding system_simple');
+    $this->assertFalse(isset($settings['types']['config']['user_role']), 'Not excluding user_role');
+    $this->assertFalse($settings['curated'], 'Not excluding curated items');
+    $this->assertFalse($settings['module']['namespace'], 'Not excluding by namespace');
+
+    // Can we run assignment with no settings?
+    $this->drupalGet('admin/config/development/features');
+
+    // Can we configure the method?
+    $this->drupalPostForm('admin/config/development/features/bundle/_exclude/default', [
+      'types[config][system_simple]' => TRUE,
+      'types[config][user_role]' => FALSE,
+      'curated' => TRUE,
+      'module[namespace]' => FALSE,
+    ], $this->t('Save settings'));
+
+    // Check form results.
+    $this->drupalGet('admin/config/development/features/bundle/_exclude/default');
+    $this->assertNoFieldChecked('edit-types-config-features-bundle', 'Saved, features_bundle is not checked');
+    $this->assertFieldChecked('edit-types-config-system-simple', 'Saved, system_simple is checked');
+    $this->assertNoFieldChecked('edit-types-config-user-role', 'Saved, user_role is not checked');
+    $this->assertFieldChecked('edit-curated', 'Saved, curated is checked');
+    $this->assertNoFieldChecked('edit-module-namespace', 'Saved, namespace is not checked');
+
+    // Check final values.
+    $settings = $this->defaultBundle()->getAssignmentSettings('exclude');
+    $this->assertFalse(isset($settings['types']['config']['features_bundle']), 'Saved, not excluding features_bundle');
+    $this->assertTrue(isset($settings['types']['config']['system_simple']), 'Saved, excluding system_simple');
+    $this->assertFalse(isset($settings['types']['config']['user_role']), 'Saved, not excluding user_role');
+    $this->assertTrue($settings['curated'], 'Saved, excluding curated items');
+    $this->assertFalse($settings['module']['namespace'], 'Saved, not excluding by namespace');
+  }
+
+}
diff --git a/tests/src/Unit/FeaturesBundleTest.php b/tests/src/Unit/FeaturesBundleTest.php
new file mode 100644
index 0000000..054a276
--- /dev/null
+++ b/tests/src/Unit/FeaturesBundleTest.php
@@ -0,0 +1,159 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\features\Unit\FeaturesBundleTest.
+ */
+
+namespace Drupal\Tests\features\Unit;
+
+use Drupal\features\Entity\FeaturesBundle;
+use Drupal\Tests\UnitTestCase;
+use Prophecy\Prophet;
+
+/**
+ * @coversDefaultClass Drupal\features\Entity\FeaturesBundle
+ * @group features
+ */
+class FeaturesBundleTest extends UnitTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    // Mock an assigner.
+    $assigner = new DummyAssigner();
+
+    // Mock the container.
+    $container = $this->prophesize('\Symfony\Component\DependencyInjection\ContainerInterface');
+    $container->get('features_assigner')
+      ->willReturn($assigner);
+    \Drupal::setContainer($container->reveal());
+  }
+
+  /**
+   * Test that assignments can be set and get.
+   */
+  public function testAssignmentSetting() {
+    // Create an entity.
+    $settings = [
+      'foo' => [
+        'enabled' => TRUE,
+        'weight' => 0,
+        'my_setting' => 42,
+      ],
+      'bar' => [
+        'enabled' => FALSE,
+        'weight' => 1,
+        'another_setting' => 'value',
+      ],
+    ];
+    $bundle = new FeaturesBundle([
+      'assignments' => $settings,
+    ], 'features_bundle');
+
+    // Get assignments and attributes.
+    $this->assertArrayEquals(
+      $bundle->getEnabledAssignments(),
+      ['foo' => 'foo'],
+      'Can get enabled assignments'
+    );
+    $this->assertArrayEquals(
+      $bundle->getAssignmentWeights(),
+      ['foo' => 0, 'bar' => 1],
+      'Can get assignment weights'
+    );
+    $this->assertArrayEquals(
+      $bundle->getAssignmentSettings('foo'),
+      $settings['foo'],
+      'Can get assignment settings'
+    );
+    $this->assertArrayEquals(
+      $bundle->getAssignmentSettings(),
+      $settings,
+      'Can get all assignment settings'
+    );
+
+    // Change settings.
+    $settings['foo']['my_setting'] = 97;
+    $bundle->setAssignmentSettings('foo', $settings['foo']);
+    $this->assertArrayEquals(
+      $bundle->getAssignmentSettings('foo'),
+      $settings['foo'],
+      'Can change assignment settings'
+    );
+
+    // Change weights.
+    $settings['foo']['weight'] = 1;
+    $settings['bar']['weight'] = 0;
+    $bundle->setAssignmentWeights(['foo' => 1, 'bar' => 0]);
+    $this->assertArrayEquals(
+      $bundle->getAssignmentWeights(),
+      ['foo' => 1, 'bar' => 0],
+      'Can change assignment weights'
+    );
+    $this->assertArrayEquals(
+      $bundle->getAssignmentSettings(),
+      $settings,
+      'Weight changes are reflected in settings'
+    );
+
+    // Enable existing assignment.
+    $settings['bar']['enabled'] = TRUE;
+    $bundle->setEnabledAssignments(['foo', 'bar']);
+    $this->assertArrayEquals(
+      $bundle->getEnabledAssignments(),
+      ['foo' => 'foo', 'bar' => 'bar'],
+      'Can enable assignment'
+    );
+    $this->assertArrayEquals(
+      $bundle->getAssignmentSettings(),
+      $settings,
+      'Enabled assignment status is reflected in settings'
+    );
+
+    // Disable existing assignments.
+    $settings['foo']['enabled'] = FALSE;
+    $settings['bar']['enabled'] = FALSE;
+    $bundle->setEnabledAssignments([]);
+    $this->assertArrayEquals(
+      $bundle->getEnabledAssignments(),
+      [],
+      'Can disable assignments'
+    );
+    $this->assertArrayEquals(
+      $bundle->getAssignmentSettings(),
+      $settings,
+      'Disabled assignment status is reflected in settings'
+    );
+
+    // Enable a new assignment.
+    $settings['foo']['enabled'] = TRUE;
+    $settings['iggy'] = ['enabled' => TRUE, 'weight' => 0, 'new_setting' => 3];
+    $bundle->setEnabledAssignments(['foo', 'iggy']);
+    $this->assertArrayEquals(
+      $bundle->getEnabledAssignments(),
+      ['foo' => 'foo', 'iggy' => 'iggy'],
+      'Can enable new assignment'
+    );
+    $this->assertArrayEquals(
+      $bundle->getAssignmentSettings(),
+      $settings,
+      'New enabled assignment status is reflected in settings'
+    );
+
+  }
+
+}
+
+/**
+ * A dummy assigner, to help testing.
+ */
+class DummyAssigner {
+  public function getAssignmentMethodInstance($method_id) {
+    $prophet = new Prophet();
+    $method = $prophet->prophesize('\Drupal\features\FeaturesAssignmentMethodInterface');
+    $method->getDefaultSettings()
+      ->willReturn(['enabled' => FALSE, 'weight' => 0, 'new_setting' => 3]);
+    return $method->reveal();
+  }
+
+}
