diff --git a/core/core.services.yml b/core/core.services.yml
index 7608878..a6f6aea 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1551,7 +1551,7 @@ services:
       - { name: needs_destruction }
   library.discovery.parser:
     class: Drupal\Core\Asset\LibraryDiscoveryParser
-    arguments: ['@app.root', '@module_handler', '@theme.manager']
+    arguments: ['@app.root', '@module_handler', '@theme.manager', '@theme_handler']
   library.dependency_resolver:
     class: Drupal\Core\Asset\LibraryDependencyResolver
     arguments: ['@library.discovery']
diff --git a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
index 91f702f..7f0a1d4 100644
--- a/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
+++ b/core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Theme\ThemeManagerInterface;
 use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
 use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\Extension\ThemeHandlerInterface;
 
 /**
  * Parses library files to get extension data.
@@ -32,6 +33,13 @@ class LibraryDiscoveryParser {
   protected $themeManager;
 
   /**
+   * The theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface
+   */
+  protected $themeHandler;
+
+  /**
    * The app root.
    *
    * @var string
@@ -47,11 +55,14 @@ class LibraryDiscoveryParser {
    *   The module handler.
    * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
    *   The theme manager.
+   * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
+   *   The theme handler.
    */
-  public function __construct($root, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager) {
+  public function __construct($root, ModuleHandlerInterface $module_handler, ThemeManagerInterface $theme_manager, ThemeHandlerInterface $theme_handler) {
     $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->themeManager = $theme_manager;
+    $this->themeHandler = $theme_handler;
   }
 
   /**
@@ -63,6 +74,8 @@ public function __construct($root, ModuleHandlerInterface $module_handler, Theme
    * @return array
    *   All library definitions of the passed extension.
    *
+   * @throws \AssertionError
+   *   When the extension (theme, module, library) is not available
    * @throws \Drupal\Core\Asset\Exception\IncompleteLibraryDefinitionException
    *   Thrown when a library has no js/css/setting.
    * @throws \UnexpectedValueException
@@ -79,9 +92,10 @@ public function buildByExtension($extension) {
       if ($this->moduleHandler->moduleExists($extension)) {
         $extension_type = 'module';
       }
-      else {
+      elseif ($this->themeHandler->themeExists($extension)) {
         $extension_type = 'theme';
       }
+      assert(isset($extension_type), sprintf('The extension "%s" is not available.', $extension));
       $path = $this->drupalGetPath($extension_type, $extension);
     }
 
diff --git a/core/modules/config/src/Tests/CacheabilityMetadataConfigOverrideIntegrationTest.php b/core/modules/config/tests/src/Functional/CacheabilityMetadataConfigOverrideIntegrationTest.php
similarity index 89%
rename from core/modules/config/src/Tests/CacheabilityMetadataConfigOverrideIntegrationTest.php
rename to core/modules/config/tests/src/Functional/CacheabilityMetadataConfigOverrideIntegrationTest.php
index 3ef0754..f2f8730 100644
--- a/core/modules/config/src/Tests/CacheabilityMetadataConfigOverrideIntegrationTest.php
+++ b/core/modules/config/tests/src/Functional/CacheabilityMetadataConfigOverrideIntegrationTest.php
@@ -1,15 +1,18 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests if configuration overrides correctly affect cacheability metadata.
  *
  * @group config
  */
-class CacheabilityMetadataConfigOverrideIntegrationTest extends WebTestBase {
+class CacheabilityMetadataConfigOverrideIntegrationTest extends BrowserTestBase {
+
+  use AssertPageCacheContextsAndTagsTrait;
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/config/src/Tests/ConfigEntityFormOverrideTest.php b/core/modules/config/tests/src/Functional/ConfigEntityFormOverrideTest.php
similarity index 87%
rename from core/modules/config/src/Tests/ConfigEntityFormOverrideTest.php
rename to core/modules/config/tests/src/Functional/ConfigEntityFormOverrideTest.php
index 41419b0..2f48a7c 100644
--- a/core/modules/config/src/Tests/ConfigEntityFormOverrideTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigEntityFormOverrideTest.php
@@ -1,15 +1,15 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests that config overrides do not bleed through in entity forms and lists.
  *
  * @group config
  */
-class ConfigEntityFormOverrideTest extends WebTestBase {
+class ConfigEntityFormOverrideTest extends BrowserTestBase {
 
   /**
    * {@inheritdoc}
@@ -46,7 +46,7 @@ public function testFormsWithOverrides() {
     // Test that the original label on the editing page is intact.
     $this->drupalGet('admin/structure/config_test/manage/dotted.default');
     $elements = $this->xpath('//input[@name="label"]');
-    $this->assertIdentical((string) $elements[0]['value'], $original_label);
+    $this->assertIdentical((string) $elements[0]->getValue(), $original_label);
     $this->assertNoText($overridden_label);
 
     // Change to a new label and test that the listing now has the edited label.
@@ -61,7 +61,7 @@ public function testFormsWithOverrides() {
     // Test that the editing page now has the edited label.
     $this->drupalGet('admin/structure/config_test/manage/dotted.default');
     $elements = $this->xpath('//input[@name="label"]');
-    $this->assertIdentical((string) $elements[0]['value'], $edited_label);
+    $this->assertIdentical((string) $elements[0]->getValue(), $edited_label);
 
     // Test that the overridden label is still loaded with the entity.
     $this->assertEqual($config_test_storage->load('dotted.default')->label(), $overridden_label);
diff --git a/core/modules/config/src/Tests/ConfigEntityListTest.php b/core/modules/config/tests/src/Functional/ConfigEntityListTest.php
similarity index 96%
rename from core/modules/config/src/Tests/ConfigEntityListTest.php
rename to core/modules/config/tests/src/Functional/ConfigEntityListTest.php
index e9950ea..69ef797 100644
--- a/core/modules/config/src/Tests/ConfigEntityListTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigEntityListTest.php
@@ -1,17 +1,17 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
-use Drupal\simpletest\WebTestBase;
 use Drupal\config_test\Entity\ConfigTest;
 use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests the listing of configuration entities.
  *
  * @group config
  */
-class ConfigEntityListTest extends WebTestBase {
+class ConfigEntityListTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -168,7 +168,7 @@ public function testListUI() {
     // Test the contents of each th cell.
     $expected_items = ['Label', 'Machine name', 'Operations'];
     foreach ($elements as $key => $element) {
-      $this->assertIdentical((string) $element[0], $expected_items[$key]);
+      $this->assertIdentical($element->getText(), $expected_items[$key]);
     }
 
     // Check the number of table row cells.
@@ -178,9 +178,9 @@ public function testListUI() {
     // Check the contents of each row cell. The first cell contains the label,
     // the second contains the machine name, and the third contains the
     // operations list.
-    $this->assertIdentical((string) $elements[0], 'Default');
-    $this->assertIdentical((string) $elements[1], 'dotted.default');
-    $this->assertTrue($elements[2]->children()->xpath('//ul'), 'Operations list found.');
+    $this->assertIdentical($elements[0]->getText(), 'Default');
+    $this->assertIdentical($elements[1]->getText(), 'dotted.default');
+    $this->assertNotEmpty($elements[2]->find('xpath', '//ul'), 'Operations list found.');
 
     // Add a new entity using the operations link.
     $this->assertLink('Add test configuration');
diff --git a/core/modules/config/src/Tests/ConfigEntityTest.php b/core/modules/config/tests/src/Functional/ConfigEntityTest.php
similarity index 69%
rename from core/modules/config/src/Tests/ConfigEntityTest.php
rename to core/modules/config/tests/src/Functional/ConfigEntityTest.php
index c0dc97b..6c515f5 100644
--- a/core/modules/config/src/Tests/ConfigEntityTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigEntityTest.php
@@ -1,6 +1,6 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\EntityMalformedException;
@@ -8,14 +8,14 @@
 use Drupal\Core\Config\Entity\ConfigEntityStorage;
 use Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException;
 use Drupal\Core\Url;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests configuration entities.
  *
  * @group config
  */
-class ConfigEntityTest extends WebTestBase {
+class ConfigEntityTest extends BrowserTestBase {
 
   /**
    * The maximum length for the entity storage used in this test.
@@ -233,112 +233,14 @@ public function testCRUD() {
   public function testCRUDUI() {
     $this->drupalLogin($this->drupalCreateUser(['administer site configuration']));
 
-    $id = strtolower($this->randomMachineName());
-    $label1 = $this->randomMachineName();
-    $label2 = $this->randomMachineName();
-    $label3 = $this->randomMachineName();
-    $message_insert = format_string('%label configuration has been created.', ['%label' => $label1]);
-    $message_update = format_string('%label configuration has been updated.', ['%label' => $label2]);
-    $message_delete = format_string('The test configuration %label has been deleted.', ['%label' => $label2]);
-
-    // Create a configuration entity.
-    $edit = [
-      'id' => $id,
-      'label' => $label1,
-    ];
-    $this->drupalPostForm('admin/structure/config_test/add', $edit, 'Save');
-    $this->assertUrl('admin/structure/config_test');
-    $this->assertResponse(200);
-    $this->assertRaw($message_insert);
-    $this->assertNoRaw($message_update);
-    $this->assertLinkByHref("admin/structure/config_test/manage/$id");
-
-    // Update the configuration entity.
-    $edit = [
-      'label' => $label2,
-    ];
-    $this->drupalPostForm("admin/structure/config_test/manage/$id", $edit, 'Save');
-    $this->assertUrl('admin/structure/config_test');
-    $this->assertResponse(200);
-    $this->assertNoRaw($message_insert);
-    $this->assertRaw($message_update);
-    $this->assertLinkByHref("admin/structure/config_test/manage/$id");
-    $this->assertLinkByHref("admin/structure/config_test/manage/$id/delete");
-
-    // Delete the configuration entity.
-    $this->drupalGet("admin/structure/config_test/manage/$id");
-    $this->clickLink(t('Delete'));
-    $this->assertUrl("admin/structure/config_test/manage/$id/delete");
-    $this->drupalPostForm(NULL, [], 'Delete');
-    $this->assertUrl('admin/structure/config_test');
-    $this->assertResponse(200);
-    $this->assertNoRaw($message_update);
-    $this->assertRaw($message_delete);
-    $this->assertNoText($label1);
-    $this->assertNoLinkByHref("admin/structure/config_test/manage/$id");
-
-    // Re-create a configuration entity.
-    $edit = [
-      'id' => $id,
-      'label' => $label1,
-    ];
-    $this->drupalPostForm('admin/structure/config_test/add', $edit, 'Save');
-    $this->assertUrl('admin/structure/config_test');
-    $this->assertResponse(200);
-    $this->assertText($label1);
-    $this->assertLinkByHref("admin/structure/config_test/manage/$id");
-
-    // Rename the configuration entity's ID/machine name.
-    $edit = [
-      'id' => strtolower($this->randomMachineName()),
-      'label' => $label3,
-    ];
-    $this->drupalPostForm("admin/structure/config_test/manage/$id", $edit, 'Save');
-    $this->assertUrl('admin/structure/config_test');
-    $this->assertResponse(200);
-    $this->assertNoText($label1);
-    $this->assertNoText($label2);
-    $this->assertText($label3);
-    $this->assertNoLinkByHref("admin/structure/config_test/manage/$id");
-    $id = $edit['id'];
-    $this->assertLinkByHref("admin/structure/config_test/manage/$id");
-
-    // Create a configuration entity with '0' machine name.
-    $edit = [
-      'id' => '0',
-      'label' => '0',
-    ];
-    $this->drupalPostForm('admin/structure/config_test/add', $edit, 'Save');
-    $this->assertResponse(200);
-    $message_insert = format_string('%label configuration has been created.', ['%label' => $edit['label']]);
-    $this->assertRaw($message_insert);
-    $this->assertLinkByHref('admin/structure/config_test/manage/0');
-    $this->assertLinkByHref('admin/structure/config_test/manage/0/delete');
-    $this->drupalPostForm('admin/structure/config_test/manage/0/delete', [], 'Delete');
-    $this->assertFalse(entity_load('config_test', '0'), 'Test entity deleted');
-
-    // Create a configuration entity with a property that uses AJAX to show
-    // extra form elements.
-    $this->drupalGet('admin/structure/config_test/add');
-
-    // Test that the dependent element is not shown initially.
-    $this->assertFieldByName('size');
-    $this->assertNoFieldByName('size_value');
-
+    // Create a configuration entity with a property that uses the non-JS case
+    // by using a 'js-hidden' submit button.
     $id = strtolower($this->randomMachineName());
     $edit = [
       'id' => $id,
       'label' => $this->randomString(),
       'size' => 'custom',
     ];
-    $this->drupalPostAjaxForm(NULL, $edit, 'size');
-
-    // Check that the dependent element is shown after selecting a 'size' value.
-    $this->assertFieldByName('size');
-    $this->assertFieldByName('size_value');
-
-    // Test the same scenario but it in a non-JS case by using a 'js-hidden'
-    // submit button.
     $this->drupalGet('admin/structure/config_test/add');
     $this->assertFieldByName('size');
     $this->assertNoFieldByName('size_value');
diff --git a/core/modules/config/src/Tests/ConfigExportImportUITest.php b/core/modules/config/tests/src/Functional/ConfigExportImportUITest.php
similarity index 99%
rename from core/modules/config/src/Tests/ConfigExportImportUITest.php
rename to core/modules/config/tests/src/Functional/ConfigExportImportUITest.php
index 9ba59a8..96a80a6 100644
--- a/core/modules/config/src/Tests/ConfigExportImportUITest.php
+++ b/core/modules/config/tests/src/Functional/ConfigExportImportUITest.php
@@ -1,12 +1,12 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Archiver\ArchiveTar;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\field\Entity\FieldStorageConfig;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests the user interface for importing/exporting configuration.
@@ -17,7 +17,7 @@
  *
  * @group config
  */
-class ConfigExportImportUITest extends WebTestBase {
+class ConfigExportImportUITest extends BrowserTestBase {
 
   /**
    * The contents of the config export tarball, held between test methods.
diff --git a/core/modules/config/src/Tests/ConfigExportUITest.php b/core/modules/config/tests/src/Functional/ConfigExportUITest.php
similarity index 96%
rename from core/modules/config/src/Tests/ConfigExportUITest.php
rename to core/modules/config/tests/src/Functional/ConfigExportUITest.php
index c9f53b3..d9bdbc4 100644
--- a/core/modules/config/src/Tests/ConfigExportUITest.php
+++ b/core/modules/config/tests/src/Functional/ConfigExportUITest.php
@@ -1,17 +1,17 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Core\Archiver\Tar;
 use Drupal\Core\Serialization\Yaml;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests the user interface for exporting configuration.
  *
  * @group config
  */
-class ConfigExportUITest extends WebTestBase {
+class ConfigExportUITest extends BrowserTestBase {
 
   /**
    * Modules to enable.
diff --git a/core/modules/config/src/Tests/ConfigFormOverrideTest.php b/core/modules/config/tests/src/Functional/ConfigFormOverrideTest.php
similarity index 81%
rename from core/modules/config/src/Tests/ConfigFormOverrideTest.php
rename to core/modules/config/tests/src/Functional/ConfigFormOverrideTest.php
index f721eeb..59276e3 100644
--- a/core/modules/config/src/Tests/ConfigFormOverrideTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigFormOverrideTest.php
@@ -1,8 +1,8 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests config overrides do not appear on forms that extend ConfigFormBase.
@@ -10,7 +10,7 @@
  * @group config
  * @see \Drupal\Core\Form\ConfigFormBase
  */
-class ConfigFormOverrideTest extends WebTestBase {
+class ConfigFormOverrideTest extends BrowserTestBase {
 
   /**
    * Tests that overrides do not affect forms.
@@ -32,7 +32,7 @@ public function testFormsWithOverrides() {
     $this->drupalGet('admin/config/system/site-information');
     $this->assertTitle('Basic site settings | ' . $overridden_name);
     $elements = $this->xpath('//input[@name="site_name"]');
-    $this->assertIdentical((string) $elements[0]['value'], 'Drupal');
+    $this->assertIdentical((string) $elements[0]->getValue(), 'Drupal');
 
     // Submit the form and ensure the site name is not changed.
     $edit = [
@@ -41,7 +41,7 @@ public function testFormsWithOverrides() {
     $this->drupalPostForm('admin/config/system/site-information', $edit, t('Save configuration'));
     $this->assertTitle('Basic site settings | ' . $overridden_name);
     $elements = $this->xpath('//input[@name="site_name"]');
-    $this->assertIdentical((string) $elements[0]['value'], $edit['site_name']);
+    $this->assertIdentical((string) $elements[0]->getValue(), $edit['site_name']);
   }
 
 }
diff --git a/core/modules/config/src/Tests/ConfigImportAllTest.php b/core/modules/config/tests/src/Functional/ConfigImportAllTest.php
similarity index 97%
rename from core/modules/config/src/Tests/ConfigImportAllTest.php
rename to core/modules/config/tests/src/Functional/ConfigImportAllTest.php
index 459be7a..0608681 100644
--- a/core/modules/config/src/Tests/ConfigImportAllTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigImportAllTest.php
@@ -1,12 +1,13 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Core\Config\StorageComparer;
 use Drupal\filter\Entity\FilterFormat;
-use Drupal\system\Tests\Module\ModuleTestBase;
 use Drupal\shortcut\Entity\Shortcut;
 use Drupal\taxonomy\Entity\Term;
+use Drupal\Tests\SchemaCheckTestTrait;
+use Drupal\Tests\system\Functional\Module\ModuleTestBase;
 
 /**
  * Tests the largest configuration import possible with all available modules.
diff --git a/core/modules/config/src/Tests/ConfigImportInstallProfileTest.php b/core/modules/config/tests/src/Functional/ConfigImportInstallProfileTest.php
similarity index 94%
rename from core/modules/config/src/Tests/ConfigImportInstallProfileTest.php
rename to core/modules/config/tests/src/Functional/ConfigImportInstallProfileTest.php
index eaece36..8b0787d 100644
--- a/core/modules/config/src/Tests/ConfigImportInstallProfileTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigImportInstallProfileTest.php
@@ -1,15 +1,15 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests the importing/exporting configuration based on the install profile.
  *
  * @group config
  */
-class ConfigImportInstallProfileTest extends WebTestBase {
+class ConfigImportInstallProfileTest extends BrowserTestBase {
 
   /**
    * The profile to install as a basis for testing.
diff --git a/core/modules/config/src/Tests/ConfigImportUITest.php b/core/modules/config/tests/src/Functional/ConfigImportUITest.php
similarity index 99%
rename from core/modules/config/src/Tests/ConfigImportUITest.php
rename to core/modules/config/tests/src/Functional/ConfigImportUITest.php
index 772dada..cf767eb 100644
--- a/core/modules/config/src/Tests/ConfigImportUITest.php
+++ b/core/modules/config/tests/src/Functional/ConfigImportUITest.php
@@ -1,18 +1,18 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Config\InstallStorage;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests the user interface for importing/exporting configuration.
  *
  * @group config
  */
-class ConfigImportUITest extends WebTestBase {
+class ConfigImportUITest extends BrowserTestBase {
 
   /**
    * Modules to install.
@@ -30,7 +30,6 @@ class ConfigImportUITest extends WebTestBase {
 
   protected function setUp() {
     parent::setUp();
-
     $this->webUser = $this->drupalCreateUser(['synchronize configuration']);
     $this->drupalLogin($this->webUser);
     $this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
@@ -119,6 +118,7 @@ public function testImport() {
 
     // Import and verify that both do not appear anymore.
     $this->drupalPostForm(NULL, [], t('Import all'));
+    $this->rebuildContainer();
     $this->assertNoRaw('<td>' . $name);
     $this->assertNoRaw('<td>' . $dynamic_name);
     $this->assertNoRaw('<td>core.extension');
diff --git a/core/modules/config/src/Tests/ConfigImportUploadTest.php b/core/modules/config/tests/src/Functional/ConfigImportUploadTest.php
similarity index 86%
rename from core/modules/config/src/Tests/ConfigImportUploadTest.php
rename to core/modules/config/tests/src/Functional/ConfigImportUploadTest.php
index 5e21295..955842d 100644
--- a/core/modules/config/src/Tests/ConfigImportUploadTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigImportUploadTest.php
@@ -1,15 +1,18 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\TestFileCreationTrait;
 
 /**
  * Tests importing configuration from an uploaded file.
  *
  * @group config
  */
-class ConfigImportUploadTest extends WebTestBase {
+class ConfigImportUploadTest extends BrowserTestBase {
+
+  use TestFileCreationTrait;
 
   /**
    * A user with the 'import configuration' permission.
@@ -41,7 +44,7 @@ public function testImport() {
     $this->assertResponse(200);
 
     // Attempt to upload a non-tar file.
-    $text_file = current($this->drupalGetTestFiles('text'));
+    $text_file = $this->getTestFiles('text')[0];
     $edit = ['files[import_tarball]' => drupal_realpath($text_file->uri)];
     $this->drupalPostForm('admin/config/development/configuration/full/import', $edit, t('Upload'));
     $this->assertText(t('Could not extract the contents of the tar file'));
diff --git a/core/modules/config/src/Tests/ConfigInstallWebTest.php b/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php
similarity index 91%
rename from core/modules/config/src/Tests/ConfigInstallWebTest.php
rename to core/modules/config/tests/src/Functional/ConfigInstallWebTest.php
index 63ecb5b..3d694bd 100644
--- a/core/modules/config/src/Tests/ConfigInstallWebTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigInstallWebTest.php
@@ -1,11 +1,11 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Config\StorageInterface;
 use Drupal\language\Entity\ConfigurableLanguage;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests installation and removal of configuration objects in install, disable
@@ -13,7 +13,7 @@
  *
  * @group config
  */
-class ConfigInstallWebTest extends WebTestBase {
+class ConfigInstallWebTest extends BrowserTestBase {
 
   /**
    * The admin user used in this test.
@@ -51,6 +51,7 @@ public function testIntegrationModuleReinstallation() {
 
     // Install the integration module.
     \Drupal::service('module_installer')->install(['config_integration_test']);
+    $this->resetAll();
 
     // Verify that default module config exists.
     \Drupal::configFactory()->reset($default_config);
@@ -148,7 +149,8 @@ public function testPreExistingConfigInstall() {
       ->save();
 
     $this->drupalPostForm('admin/modules', ['modules[config_install_fail_test][enable]' => TRUE], t('Install'));
-    $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default</em> already exist in active configuration.');
+    $placeholder = str_replace('/', DIRECTORY_SEPARATOR,'language/fr/config_test.dynamic.dotted.default');
+    $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default, ' . $placeholder . '</em> already exist in active configuration.');
 
     // Test installing a theme through the UI that has existing configuration.
     // This relies on the fact the config_test has been installed and created
@@ -156,8 +158,9 @@ public function testPreExistingConfigInstall() {
     // override created still exists.
     $this->drupalGet('admin/appearance');
     $url = $this->xpath("//a[contains(@href,'config_clash_test_theme') and contains(@href,'/install?')]/@href")[0];
-    $this->drupalGet($this->getAbsoluteUrl($url));
-    $this->assertRaw('Unable to install config_clash_test_theme, <em class="placeholder">config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default</em> already exist in active configuration.');
+    $this->drupalGet($this->getAbsoluteUrl($url->getText()));
+    $placeholder = str_replace('/', DIRECTORY_SEPARATOR, 'language/fr/config_test.dynamic.dotted.default');
+    $this->assertRaw('Unable to install config_clash_test_theme, <em class="placeholder">config_test.dynamic.dotted.default, ' . $placeholder . '</em> already exist in active configuration.');
 
     // Test installing a theme through the API that has existing configuration.
     try {
@@ -167,7 +170,9 @@ public function testPreExistingConfigInstall() {
     catch (PreExistingConfigException $e) {
       $this->assertEqual($e->getExtension(), 'config_clash_test_theme');
       $this->assertEqual($e->getConfigObjects(), [StorageInterface::DEFAULT_COLLECTION => ['config_test.dynamic.dotted.default'], 'language.fr' => ['config_test.dynamic.dotted.default']]);
-      $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default) provided by config_clash_test_theme already exist in active configuration');
+      $placeholder = str_replace('/', DIRECTORY_SEPARATOR, 'language/fr/config_test.dynamic.dotted.default');
+      $expected = str_replace('/', DIRECTORY_SEPARATOR, 'Configuration objects (config_test.dynamic.dotted.default, ' . $placeholder . ') provided by config_clash_test_theme already exist in active configuration');
+      $this->assertEqual($e->getMessage(), $expected);
     }
   }
 
diff --git a/core/modules/config/src/Tests/ConfigSingleImportExportTest.php b/core/modules/config/tests/src/Functional/ConfigSingleImportExportTest.php
similarity index 93%
rename from core/modules/config/src/Tests/ConfigSingleImportExportTest.php
rename to core/modules/config/tests/src/Functional/ConfigSingleImportExportTest.php
index 607e80c..5c0b420 100644
--- a/core/modules/config/src/Tests/ConfigSingleImportExportTest.php
+++ b/core/modules/config/tests/src/Functional/ConfigSingleImportExportTest.php
@@ -1,16 +1,16 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
 use Drupal\Core\Serialization\Yaml;
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests the user interface for importing/exporting a single configuration.
  *
  * @group config
  */
-class ConfigSingleImportExportTest extends WebTestBase {
+class ConfigSingleImportExportTest extends BrowserTestBase {
 
   /**
    * Modules to enable.
@@ -225,16 +225,18 @@ public function testExport() {
     $this->drupalGet('admin/config/development/configuration/single/export/system.simple');
     $this->assertFieldByXPath('//select[@name="config_type"]//option[@selected="selected"]', t('Simple configuration'), 'The simple configuration option is selected when specified in the URL.');
     // Spot check several known simple configuration files.
-    $element = $this->xpath('//select[@name="config_name"]');
-    $options = $this->getAllOptions($element[0]);
+    $element = $this->xpath('//select[@name="config_name"]')[0];
+    $options = $element->findAll('css', 'option');
     $expected_options = ['system.site', 'user.settings'];
     foreach ($options as &$option) {
-      $option = (string) $option;
+      $option = (string) $option->getValue();
     }
     $this->assertIdentical($expected_options, array_intersect($expected_options, $options), 'The expected configuration files are listed.');
 
     $this->drupalGet('admin/config/development/configuration/single/export/system.simple/system.image');
-    $this->assertFieldByXPath('//textarea[@name="export"]', "toolkit: gd\n_core:\n  default_config_hash: durWHaKeBaq4d9Wpi4RqwADj1OufDepcnJuhVLmKN24\n", 'The expected system configuration is displayed.');
+    $actual = $this->xpath('//textarea[@name="export"]')[0]->getValue();
+    $expected = "toolkit: gd\n_core:\n  default_config_hash: durWHaKeBaq4d9Wpi4RqwADj1OufDepcnJuhVLmKN24\n";
+    $this->assertEquals($expected, $actual, 'The expected system configuration is displayed.');
 
     $this->drupalGet('admin/config/development/configuration/single/export/date_format');
     $this->assertFieldByXPath('//select[@name="config_type"]//option[@selected="selected"]', t('Date format'), 'The date format entity type is selected when specified in the URL.');
@@ -243,7 +245,7 @@ public function testExport() {
     $this->assertFieldByXPath('//select[@name="config_name"]//option[@selected="selected"]', t('Fallback date format (fallback)'), 'The fallback date format config entity is selected when specified in the URL.');
 
     $fallback_date = \Drupal::entityManager()->getStorage('date_format')->load('fallback');
-    $yaml_text = (string) $this->xpath('//textarea[@name="export"]')[0];
+    $yaml_text = $this->xpath('//textarea[@name="export"]')[0]->getValue();
     $this->assertEqual(Yaml::decode($yaml_text), $fallback_date->toArray(), 'The fallback date format config entity export code is displayed.');
   }
 
diff --git a/core/modules/config/src/Tests/LanguageNegotiationFormOverrideTest.php b/core/modules/config/tests/src/Functional/LanguageNegotiationFormOverrideTest.php
similarity index 93%
rename from core/modules/config/src/Tests/LanguageNegotiationFormOverrideTest.php
rename to core/modules/config/tests/src/Functional/LanguageNegotiationFormOverrideTest.php
index ba67960..6c4e1bb 100644
--- a/core/modules/config/src/Tests/LanguageNegotiationFormOverrideTest.php
+++ b/core/modules/config/tests/src/Functional/LanguageNegotiationFormOverrideTest.php
@@ -1,8 +1,8 @@
 <?php
 
-namespace Drupal\config\Tests;
+namespace Drupal\Tests\config\Functional;
 
-use Drupal\simpletest\WebTestBase;
+use Drupal\Tests\BrowserTestBase;
 
 /**
  * Tests language-negotiation overrides are not on language-negotiation form.
@@ -10,7 +10,7 @@
  * @group config
  * @see \Drupal\Core\Form\ConfigFormBase
  */
-class LanguageNegotiationFormOverrideTest extends WebTestBase {
+class LanguageNegotiationFormOverrideTest extends BrowserTestBase {
 
   public static $modules = ['language', 'locale', 'locale_test'];
 
diff --git a/core/modules/config/tests/src/FunctionalJavascript/ConfigEntityTest.php b/core/modules/config/tests/src/FunctionalJavascript/ConfigEntityTest.php
new file mode 100644
index 0000000..aad3cf2
--- /dev/null
+++ b/core/modules/config/tests/src/FunctionalJavascript/ConfigEntityTest.php
@@ -0,0 +1,162 @@
+<?php
+
+namespace Drupal\Tests\config\FunctionalJavascript;
+
+use Drupal\Component\Render\FormattableMarkup;
+use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
+
+/**
+ * Tests the View UI filter criteria group dialog.
+ *
+ * @group views_ui
+ */
+class ConfigEntityTest extends JavascriptTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['config_test'];
+
+  /**
+   * Tests CRUD operations through the UI.
+   */
+  public function testCRUDUI() {
+    $this->drupalLogin($this->drupalCreateUser(['administer site configuration']));
+
+    $id = strtolower($this->randomMachineName());
+    $label1 = $this->randomMachineName();
+    $label2 = $this->randomMachineName();
+    $label3 = $this->randomMachineName();
+    $message_insert = new FormattableMarkup('%label configuration has been created.', array('%label' => $label1));
+    $message_update = new FormattableMarkup('%label configuration has been updated.', array('%label' => $label2));
+    $message_delete = new FormattableMarkup('The test configuration %label has been deleted.', array('%label' => $label2));
+
+    // Create a configuration entity.
+    $this->drupalGet('admin/structure/config_test/add');
+
+    $session = $this->getSession();
+    $assert_session = $this->assertSession();
+    $page = $session->getPage();
+
+    $field_id = $page->findField('id');
+    $field_label = $page->findField('label');
+    $button_save = $page->findButton('Save');
+
+    // Set values for the configuration entity and submit the form.
+    $field_id->setValue($id);
+    $field_label->setValue($label1);
+    $button_save->click();
+
+    $assert_session->addressEquals('admin/structure/config_test');
+    $assert_session->statusCodeEquals(200);
+    $assert_session->responseContains($message_insert);
+    $assert_session->responseNotContains($message_update);
+    $this->assertNotEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/' . $id . '"]'));
+
+    // Update the configuration entity.
+    $this->drupalGet("admin/structure/config_test/manage/$id");
+    $field_label->setValue($label2);
+    $button_save->click();
+    $assert_session->addressEquals('admin/structure/config_test');
+    $assert_session->statusCodeEquals(200);
+    $assert_session->responseNotContains($message_insert);
+    $assert_session->responseContains($message_update);
+    $this->assertNotEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/' . $id . '"]'));
+    $this->assertNotEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/' . $id . '/delete"]'));
+
+    // Delete the configuration entity.
+    $this->drupalGet("admin/structure/config_test/manage/$id");
+    $this->clickLink(t('Delete'));
+    $assert_session->addressEquals("admin/structure/config_test/manage/$id/delete");
+    $page->findButton('Delete')->click();
+
+    $assert_session->addressEquals('admin/structure/config_test');
+    $assert_session->statusCodeEquals(200);
+    $assert_session->responseNotContains($message_update);
+    $assert_session->responseContains($message_delete);
+    $assert_session->responseNotContains($label1);
+    $this->assertEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/' . $id . '"]'));
+
+    // Re-create a configuration entity.
+    $this->drupalGet('admin/structure/config_test/add');
+    $field_id->setValue($id);
+    $field_label->setValue($label1);
+    $button_save->click();
+
+    $assert_session->addressEquals('admin/structure/config_test');
+    $assert_session->statusCodeEquals(200);
+    $assert_session->responseContains($label1);
+    $this->assertNotEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/' . $id . '"]'));
+
+    // Rename the configuration entity's ID/machine name.
+    $new_id = strtolower($this->randomMachineName());
+    $this->drupalGet("admin/structure/config_test/manage/$id");
+    $field_id->setValue($new_id);
+    $field_label->setValue($label3);
+    $button_save->click();
+
+    $assert_session->addressEquals('admin/structure/config_test');
+    $assert_session->statusCodeEquals(200);
+    $assert_session->responseNotContains($label1);
+    $assert_session->responseNotContains($label2);
+    $assert_session->responseContains($label3);
+    $this->assertEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/' . $id . '"]'));
+
+    $id = $new_id;
+    $this->assertNotEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/' . $id . '"]'));
+
+    // Create a configuration entity with '0' machine name.
+    $this->drupalGet('admin/structure/config_test/add');
+    $field_id->setValue('0');
+    $field_label->setValue('0');
+    $button_save->click();
+
+    $assert_session->statusCodeEquals(200);
+    $message_insert = new FormattableMarkup('%label configuration has been created.', array('%label' => '0'));
+    $assert_session->responseContains($message_insert);
+
+    $this->assertNotEmpty($page->find('css' , 'a[href="/admin/structure/config_test/manage/0"]'));
+    $delete_link = $page->find('css' , 'a[href="/admin/structure/config_test/manage/0/delete"]');
+
+    // Expand the options.
+    $ul = $delete_link->getParent()->getParent();
+    $ul->find('css', '.dropbutton-toggle button')->click();
+    $this->assertTrue($delete_link->isVisible());
+
+    // Navigate to the delete page and submit the delete form.
+    $delete_link->click();
+    $page->findButton('Delete')->click();
+
+    $entity = \Drupal::entityTypeManager()->getStorage('config_test')->load('0');
+    $this->assertFalse($entity, 'Test entity deleted');
+
+    // Create a configuration entity with a property that uses AJAX to show
+    // extra form elements.
+    $this->drupalGet('admin/structure/config_test/add');
+
+    // Test that the dependent element is not shown initially.
+    $field_size = $page->findField('size');
+    $field_size_value = $page->findField('size_value');
+    $this->assertNotEmpty($field_size);
+    $this->assertEmpty($field_size_value);
+
+    $id = strtolower($this->randomMachineName());
+    $field_id->setValue($id);
+    $field_label->setValue($this->randomString());
+    $field_size->setValue('custom');
+    $assert_session->assertWaitOnAjaxRequest();
+
+    // Check that the dependent element is shown after selecting a 'size' value.
+    $field_size_value = $page->findField('size_value');
+    $this->assertNotEmpty($field_size);
+    $this->assertNotEmpty($field_size_value);
+
+    $field_size_value->setValue('medium');
+    $button_save->click();
+
+    $entity = \Drupal::entityTypeManager()->getStorage('config_test')->load($id);
+    $this->assertEquals('custom', $entity->get('size'));
+    $this->assertEquals('medium', $entity->get('size_value'));
+  }
+
+}
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 09a7aad..6008076 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -141,8 +141,9 @@
   exit(SIMPLETEST_SCRIPT_EXIT_SUCCESS);
 }
 
-$test_list = simpletest_script_get_test_list();
-
+// $test_list = simpletest_script_get_test_list();
+$test_list = array_fill(0, 50, 'Drupal\Tests\config\Functional\ConfigImportUITest');
+$test_list[] = 'Drupal\Tests\config\FunctionalJavascript\ConfigEntityTest';
 // Try to allocate unlimited time to run the tests.
 drupal_set_time_limit(0);
 simpletest_script_reporter_init();
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php
index e059405..7339db8 100644
--- a/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxTest.php
@@ -53,7 +53,7 @@ public function testDrupalSettingsCachingRegression() {
     $session = $this->getSession();
 
     // Insert a fake library into the already loaded library settings.
-    $fake_library = 'fakeLibrary/fakeLibrary';
+    $fake_library = 'core/fakeLibrary';
     $session->evaluateScript("drupalSettings.ajaxPageState.libraries = drupalSettings.ajaxPageState.libraries + ',$fake_library';");
 
     $libraries = $session->evaluateScript('drupalSettings.ajaxPageState.libraries');
diff --git a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
index cbb0666..4f95a91 100644
--- a/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
+++ b/core/tests/Drupal/Tests/Core/Asset/LibraryDiscoveryParserTest.php
@@ -48,6 +48,13 @@ class LibraryDiscoveryParserTest extends UnitTestCase {
   protected $themeManager;
 
   /**
+   * The mocked theme handler.
+   *
+   * @var \Drupal\Core\Extension\ThemeHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $themeHandler;
+
+  /**
    * The mocked lock backend.
    *
    * @var \Drupal\Core\Lock\LockBackendInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -62,6 +69,8 @@ protected function setUp() {
 
     $this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
     $this->themeManager = $this->getMock('Drupal\Core\Theme\ThemeManagerInterface');
+    $this->themeHandler = $this->getMock('Drupal\Core\Extension\ThemeHandlerInterface');
+
     $mock_active_theme = $this->getMockBuilder('Drupal\Core\Theme\ActiveTheme')
       ->disableOriginalConstructor()
       ->getMock();
@@ -71,7 +80,7 @@ protected function setUp() {
     $this->themeManager->expects($this->any())
       ->method('getActiveTheme')
       ->willReturn($mock_active_theme);
-    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager);
+    $this->libraryDiscoveryParser = new TestLibraryDiscoveryParser($this->root, $this->moduleHandler, $this->themeManager, $this->themeHandler);
   }
 
   /**
@@ -112,6 +121,11 @@ public function testBuildByExtensionWithTheme() {
       ->with('example_theme')
       ->will($this->returnValue(FALSE));
 
+    $this->themeHandler->expects($this->atLeastOnce())
+      ->method('themeExists')
+      ->with('example_theme')
+      ->will($this->returnValue(TRUE));
+
     $path = __DIR__ . '/library_test_files';
     $path = substr($path, strlen($this->root) + 1);
     $this->libraryDiscoveryParser->setPaths('theme', 'example_theme', $path);
@@ -163,6 +177,28 @@ public function testInvalidLibrariesFile() {
   }
 
   /**
+   * Tests that an exception is thrown when the extension is not a valid
+   * module, theme or library.
+   *
+   * @covers ::buildByExtension
+   */
+  public function testMissingExtension() {
+    $this->moduleHandler->expects($this->atLeastOnce())
+      ->method('moduleExists')
+      ->with('missing_extension')
+      ->will($this->returnValue(FALSE));
+
+    $this->themeHandler->expects($this->atLeastOnce())
+      ->method('themeExists')
+      ->with('missing_extension')
+      ->will($this->returnValue(FALSE));
+
+    assert_options(ASSERT_ACTIVE, 1);
+    $this->setExpectedException('\AssertionError', 'The extension "missing_extension" is not available.');
+    $this->libraryDiscoveryParser->buildByExtension('missing_extension');
+  }
+
+  /**
    * Tests that an exception is thrown when no CSS/JS/setting is specified.
    *
    * @covers ::buildByExtension
