diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index e392b6a..8e14b36 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -194,6 +194,11 @@ route:
         - type: string
           label: 'Param'
 
+# HTML color value.
+color_hex:
+  type: string
+  label: 'Color'
+
 # Config dependencies.
 config_dependencies:
   type: mapping
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index 7809f5f..02cabf3 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -66,7 +66,7 @@ function color_css_alter(&$css) {
   $themes = list_themes();
 
   // Override stylesheets.
-  $color_paths = \Drupal::config('color.' . $theme_key)->get('stylesheets');
+  $color_paths = \Drupal::config('color.theme.' . $theme_key)->get('stylesheets');
 
   if (!empty($color_paths) && !empty($themes[$theme_key]->stylesheets['all'])) {
 
@@ -95,7 +95,7 @@ function color_preprocess_page(&$variables) {
   global $theme_key;
 
   // Override logo.
-  $logo = \Drupal::config('color.' . $theme_key)->get('logo');
+  $logo = \Drupal::config('color.theme.' . $theme_key)->get('logo');
   if ($logo && $variables['logo'] && preg_match('!' . $theme_key . '/logo.png$!', $variables['logo'])) {
     $variables['logo'] = file_create_url($logo);
   }
@@ -150,7 +150,7 @@ function color_get_palette($theme, $default = FALSE) {
 
   // Load variable.
   // @todo Default color config should be moved to yaml in the theme.
-  return \Drupal::config('color.' . $theme)->get('palette') ?: $palette;
+  return \Drupal::config('color.theme.' . $theme)->get('palette') ?: $palette;
 }
 
 /**
@@ -178,7 +178,7 @@ function color_scheme_form($complete_form, &$form_state, $theme) {
 
   // See if we're using a predefined scheme.
   // Note: we use the original theme when the default scheme is chosen.
-  $current_scheme = \Drupal::config('color.' . $theme)->get('palette');
+  $current_scheme = \Drupal::config('color.theme.' . $theme)->get('palette');
   foreach ($schemes as $key => $scheme) {
     if ($current_scheme == $scheme) {
       $scheme_name = $key;
@@ -349,7 +349,7 @@ function color_scheme_form_submit($form, &$form_state) {
   $theme = $form_state['values']['theme'];
   $info = $form_state['values']['info'];
 
-  $config = \Drupal::config('color.' . $theme);
+  $config = \Drupal::config('color.theme.' . $theme);
 
   // Resolve palette.
   $palette = $form_state['values']['palette'];
@@ -606,7 +606,7 @@ function _color_render_images($theme, &$info, &$paths, $palette) {
     if ($file == 'screenshot.png') {
       $slice = imagecreatetruecolor(150, 90);
       imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height);
-      \Drupal::config('color.' . $theme)
+      \Drupal::config('color.theme.' . $theme)
         ->set('screenshot', $image)
         ->save();
     }
diff --git a/core/modules/color/config/schema/color.schema.yml b/core/modules/color/config/schema/color.schema.yml
new file mode 100644
index 0000000..4b81f0c
--- /dev/null
+++ b/core/modules/color/config/schema/color.schema.yml
@@ -0,0 +1,20 @@
+color.theme.*:
+  type: mapping
+  label: 'Color theme settings'
+  mapping:
+    palette:
+      type: sequence
+      label: 'Palette settings'
+      sequence:
+        - type: color_hex
+    logo:
+      type: path
+      label: 'Logo path'
+    stylesheets:
+      type: sequence
+      sequence:
+        - type: path
+    files:
+      type: sequence
+      sequence:
+        - type: path
diff --git a/core/modules/color/lib/Drupal/color/Tests/ColorConfigSchemaTest.php b/core/modules/color/lib/Drupal/color/Tests/ColorConfigSchemaTest.php
new file mode 100644
index 0000000..d34f06e
--- /dev/null
+++ b/core/modules/color/lib/Drupal/color/Tests/ColorConfigSchemaTest.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\color\Tests\ColorConfigSchemaTest.
+ */
+
+namespace Drupal\color\Tests;
+
+use Drupal\config\Tests\ConfigSchemaTestBase;
+
+/**
+ * Tests the Color config schema.
+ */
+class ColorConfigSchemaTest extends ConfigSchemaTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('color');
+
+  /**
+   * A user with administrative permissions.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $big_user;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Color config schema',
+      'description' => 'Ensures the color config schema is correct.',
+      'group' => 'Color',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  function setUp() {
+    parent::setUp();
+    \Drupal::service('theme_handler')->enable(array('bartik'));
+
+    // Create user.
+    $this->big_user = $this->drupalCreateUser(array('administer themes'));
+    $this->drupalLogin($this->big_user);
+  }
+
+  /**
+   * Tests whether the color config schema is valid.
+   */
+  function testValidColorConfigSchema() {
+    $settings_path = 'admin/appearance/settings/bartik';
+    $edit['scheme'] = '';
+    $edit['palette[bg]'] = '#123456';
+    $this->drupalPostForm($settings_path, $edit, t('Save configuration'));
+    $this->assertConfigSchema(\Drupal::service('config.typed'), 'color.theme.bartik', \Drupal::config('color.theme.bartik')->get());
+  }
+
+}
diff --git a/core/modules/color/lib/Drupal/color/Tests/ColorTest.php b/core/modules/color/lib/Drupal/color/Tests/ColorTest.php
index 6238019..a3e1c08 100644
--- a/core/modules/color/lib/Drupal/color/Tests/ColorTest.php
+++ b/core/modules/color/lib/Drupal/color/Tests/ColorTest.php
@@ -123,7 +123,7 @@ function _testColor($theme, $test_values) {
     $this->drupalPostForm($settings_path, $edit, t('Save configuration'));
 
     $this->drupalGet('<front>');
-    $stylesheets = \Drupal::config('color.' . $theme)->get('stylesheets');
+    $stylesheets = \Drupal::config('color.theme.' . $theme)->get('stylesheets');
     foreach ($stylesheets as $stylesheet) {
       $this->assertPattern('|' . file_create_url($stylesheet) . '|', 'Make sure the color stylesheet is included in the content. (' . $theme . ')');
       $stylesheet_content = join("\n", file($stylesheet));
@@ -136,7 +136,7 @@ function _testColor($theme, $test_values) {
     $this->drupalPostForm($settings_path, $edit, t('Save configuration'));
 
     $this->drupalGet('<front>');
-    $stylesheets = \Drupal::config('color.' . $theme)->get('stylesheets');
+    $stylesheets = \Drupal::config('color.theme' . $theme)->get('stylesheets');
     foreach ($stylesheets as $stylesheet) {
       $stylesheet_content = join("\n", file($stylesheet));
       $this->assertTrue(strpos($stylesheet_content, 'color: ' . $test_values['scheme_color']) !== FALSE, 'Make sure the color we changed is in the color stylesheet. (' . $theme . ')');
diff --git a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigSchemaTestBase.php
similarity index 58%
copy from core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
copy to core/modules/config/lib/Drupal/config/Tests/ConfigSchemaTestBase.php
index 1ef3800..13e9c49 100644
--- a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigSchemaTestBase.php
@@ -7,30 +7,21 @@
 
 namespace Drupal\config\Tests;
 
-use Drupal\config_test\TestInstallStorage;
-use Drupal\Core\Config\InstallStorage;
 use Drupal\Core\Config\Schema\Property;
-use Drupal\Core\Config\TypedConfigManager;
+use Drupal\Core\Config\TypedConfigManagerInterface;
 use Drupal\Core\TypedData\Type\BooleanInterface;
 use Drupal\Core\TypedData\Type\StringInterface;
-use Drupal\simpletest\DrupalUnitTestBase;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Config\Schema\SchemaIncompleteException;
 use Drupal\Core\TypedData\PrimitiveInterface;
 use Drupal\Core\TypedData\Type\FloatInterface;
 use Drupal\Core\TypedData\Type\IntegerInterface;
+use Drupal\simpletest\WebTestBase;
 
 /**
  * Tests default configuration availability and type with configuration schema.
  */
-class DefaultConfigTest extends DrupalUnitTestBase {
-
-  /**
-   * Modules to enable.
-   *
-   * @var array
-   */
-  public static $modules = array('config_test');
+abstract class ConfigSchemaTestBase extends WebTestBase {
 
   /**
    * The config schema wrapper object for the configuration object under test.
@@ -65,51 +56,20 @@ public static function getInfo() {
   /**
    * Tests default configuration data type.
    */
-  public function testDefaultConfig() {
-    // Create a typed config manager with access to configuration schema in
-    // every module, profile and theme.
-    $typed_config = new TypedConfigManager(
-      \Drupal::service('config.storage'),
-      new TestInstallStorage(InstallStorage::CONFIG_SCHEMA_DIRECTORY),
-      \Drupal::service('cache.config')
-    );
-
-    // Create a configuration storage with access to default configuration in
-    // every module, profile and theme.
-    $default_config_storage = new TestInstallStorage();
-
-    foreach ($default_config_storage->listAll() as $config_name) {
-      // @todo: remove once migration (https://drupal.org/node/2183957) and
-      // translation (https://drupal.org/node/2168609) schemas are in.
-      if (strpos($config_name, 'migrate.migration') === 0 || strpos($config_name, 'language.config') === 0) {
-        continue;
-      }
-
-      // 1. config_test.noschema has to be skipped as it tests
-      // TypedConfigManagerInterface::hasConfigSchema() method.
-      // 2. config.someschema has to be skipped as it tests schema default data
-      // type fallback.
-      // 3. config_test.schema_in_install is testing that schema are used during
-      // configuration installation.
-      if ($config_name == 'config_test.noschema' || $config_name == 'config_test.someschema' || $config_name == 'config_test.schema_in_install') {
-        continue;
-      }
-
-      $this->configName = $config_name;
-      $data = $default_config_storage->read($config_name);
-      if (!$typed_config->hasConfigSchema($config_name)) {
-        $this->fail(String::format('No schema for !config_name', array('!config_name' => $config_name)));
-        continue;
-      }
-      $definition = $typed_config->getDefinition($config_name);
-      $this->schema = $typed_config->create($definition, $data);
-      $this->configPass = TRUE;
-      foreach ($data as $key => $value) {
-        $this->checkValue($key, $value);
-      }
-      if ($this->configPass) {
-        $this->pass(String::format('Schema found for !config_name and values comply with schema.', array('!config_name' => $config_name)));
-      }
+  public function assertConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data) {
+    $this->configName = $config_name;
+    if (!$typed_config->hasConfigSchema($config_name)) {
+      $this->fail(String::format('No schema for !config_name', array('!config_name' => $config_name)));
+      return;
+    }
+    $definition = $typed_config->getDefinition($config_name);
+    $this->schema = $typed_config->create($definition, $config_data);
+    $this->configPass = TRUE;
+    foreach ($config_data as $key => $value) {
+      $this->checkValue($key, $value);
+    }
+    if ($this->configPass) {
+      $this->pass(String::format('Schema found for !config_name and values comply with schema.', array('!config_name' => $config_name)));
     }
   }
 
diff --git a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
index 1ef3800..8a5d022 100644
--- a/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/DefaultConfigTest.php
@@ -9,21 +9,12 @@
 
 use Drupal\config_test\TestInstallStorage;
 use Drupal\Core\Config\InstallStorage;
-use Drupal\Core\Config\Schema\Property;
 use Drupal\Core\Config\TypedConfigManager;
-use Drupal\Core\TypedData\Type\BooleanInterface;
-use Drupal\Core\TypedData\Type\StringInterface;
-use Drupal\simpletest\DrupalUnitTestBase;
-use Drupal\Component\Utility\String;
-use Drupal\Core\Config\Schema\SchemaIncompleteException;
-use Drupal\Core\TypedData\PrimitiveInterface;
-use Drupal\Core\TypedData\Type\FloatInterface;
-use Drupal\Core\TypedData\Type\IntegerInterface;
 
 /**
  * Tests default configuration availability and type with configuration schema.
  */
-class DefaultConfigTest extends DrupalUnitTestBase {
+class DefaultConfigTest extends ConfigSchemaTestBase {
 
   /**
    * Modules to enable.
@@ -33,25 +24,6 @@ class DefaultConfigTest extends DrupalUnitTestBase {
   public static $modules = array('config_test');
 
   /**
-   * The config schema wrapper object for the configuration object under test.
-   *
-   * @var \Drupal\Core\Config\Schema\Element
-   */
-  protected $schema;
-
-  /**
-   * The configuration object name under test.
-   *
-   * @var string
-   */
-  protected $configName;
-
-  /**
-   * @var boolean
-   */
-  protected $configPass;
-
-  /**
    * {@inheritdoc}
    */
   public static function getInfo() {
@@ -95,91 +67,9 @@ public function testDefaultConfig() {
         continue;
       }
 
-      $this->configName = $config_name;
       $data = $default_config_storage->read($config_name);
-      if (!$typed_config->hasConfigSchema($config_name)) {
-        $this->fail(String::format('No schema for !config_name', array('!config_name' => $config_name)));
-        continue;
-      }
-      $definition = $typed_config->getDefinition($config_name);
-      $this->schema = $typed_config->create($definition, $data);
-      $this->configPass = TRUE;
-      foreach ($data as $key => $value) {
-        $this->checkValue($key, $value);
-      }
-      if ($this->configPass) {
-        $this->pass(String::format('Schema found for !config_name and values comply with schema.', array('!config_name' => $config_name)));
-      }
-    }
-  }
-
-  /**
-   * Helper method to check data type.
-   *
-   * @param string $key
-   *   A string of configuration key.
-   * @param mixed $value
-   *   Value of given key.
-   *
-   * @return mixed
-   *   Returns mixed value.
-   */
-  protected function checkValue($key, $value) {
-    if (is_scalar($value) || $value === NULL) {
-      try {
-        $success = FALSE;
-        $type = gettype($value);
-        $element = $this->schema->get($key);
-        if ($element instanceof PrimitiveInterface) {
-          if ($type == 'integer' && $element instanceof IntegerInterface) {
-            $success = TRUE;
-          }
-          if ($type == 'double' && $element instanceof FloatInterface) {
-            $success = TRUE;
-          }
-          if ($type == 'boolean' && $element instanceof BooleanInterface) {
-            $success = TRUE;
-          }
-          if ($type == 'string' && ($element instanceof StringInterface || $element instanceof Property)) {
-            $success = TRUE;
-          }
-          // Null values are allowed for all types.
-          if ($value === NULL) {
-            $success = TRUE;
-          }
-        }
-        else {
-          // @todo throw an exception due to an incomplete schema. Only possible
-          //   once https://drupal.org/node/1910624 is complete.
-        }
-        $class = get_class($element);
-        if (!$success) {
-          $this->fail("{$this->configName}:$key has the wrong schema. Variable type is $type and schema class is $class.");
-        }
-      }
-      catch (SchemaIncompleteException $e) {
-        $this->fail("{$this->configName}:$key has no schema.");
-      }
+      $this->assertConfigSchema($typed_config, $config_name, $data);
     }
-    else {
-      // Any non-scalar value must be an array.
-      if (!is_array($value)) {
-        $value = (array) $value;
-      }
-      // Recurse into any nested keys.
-      foreach ($value as $nested_value_key => $nested_value) {
-        $value[$nested_value_key] = $this->checkValue($key . '.' . $nested_value_key, $nested_value);
-      }
-    }
-    return $value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function fail($message = NULL, $group = 'Other') {
-    $this->configPass = FALSE;
-    return parent::fail($message, $group);
   }
 
 }
