diff --git a/core/modules/breakpoint/breakpoint.info b/core/modules/breakpoint/breakpoint.info
new file mode 100644
index 0000000..7868658
--- /dev/null
+++ b/core/modules/breakpoint/breakpoint.info
@@ -0,0 +1,7 @@
+name = Breakpoint
+description = Manage breakpoints and breakpoint sets for responsive designs.
+package = Core
+version = VERSION
+core = 8.x
+
+dependencies[] = config
diff --git a/core/modules/breakpoint/breakpoint.module b/core/modules/breakpoint/breakpoint.module
new file mode 100644
index 0000000..8525494
--- /dev/null
+++ b/core/modules/breakpoint/breakpoint.module
@@ -0,0 +1,263 @@
+<?php
+
+/**
+ * @file
+ * Manage breakpoints and breakpoint sets for responsive designs.
+ */
+
+use \Drupal\breakpoint\Breakpoint;
+use \Drupal\breakpoint\BreakpointSet;
+
+/**
+ * Implements hook_enable().
+ *
+ * Import breakpoints from all enabled themes.
+ */
+function breakpoint_enable() {
+  config_install_default_config('module', 'breakpoint');
+  $themes = list_themes();
+  breakpoint_themes_enabled(array_keys($themes));
+}
+
+/**
+ * Implements hook_themes_enabled().
+ *
+ * Import breakpoints from all new enabled themes.
+ *
+ * @param array $theme_list
+ *   An array of theme names.
+ */
+function breakpoint_themes_enabled($theme_list) {
+  $themes = list_themes();
+  foreach ($theme_list as $theme_key) {
+    if ($themes[$theme_key]->status) {
+      $theme_breakpoints = breakpoint_get_theme_breakpoint_list($theme_key);
+      if (!empty($theme_breakpoints)) {
+        $weight = 0;
+        // Build a breakpoint set for each theme.
+        $breakpointset = new BreakpointSet();
+        $breakpointset->id = $theme_key;
+        $breakpointset->label = $themes[$theme_key]->info['name'];
+        $breakpointset->sourceType = Breakpoint::SOURCE_TYPE_THEME;
+        foreach ($theme_breakpoints as $name => $mediaQuery) {
+          $breakpoint = new Breakpoint;
+          $breakpoint->name = $name;
+          $breakpoint->label = ucfirst($name);
+          $breakpoint->mediaQuery = $mediaQuery;
+          $breakpoint->source = $theme_key;
+          $breakpoint->sourceType = Breakpoint::SOURCE_TYPE_THEME;
+          $breakpoint->status = TRUE;
+          $breakpoint->weight = $weight++;
+          $breakpoint->save();
+          $breakpointset->breakpoints[$breakpoint->id()] = $breakpoint;
+        }
+        $breakpointset->save();
+
+        $uri = $breakpointset->uri();
+        if ($uri) {
+          $uri_options = $uri;
+          unset($uri_options['path']);
+          $uri = $uri['path'];
+        }
+        $message = t('The breakpoints from theme %theme are imported.', array(
+          '%theme' => check_plain($themes[$theme_key]->info['name']),
+        ));
+        if (module_exists('breakpoint_ui') && $uri) {
+          $message .= '<p>' . l(t('A new breakpoint set is created for theme %theme.', array(
+            '%theme' => check_plain($themes[$theme_key]->info['name']),
+          )), $uri, $uri_options);
+        }
+        drupal_set_message($message, 'status');
+      }
+    }
+  }
+}
+
+/**
+ * Implements hook_themes_disabled().
+ *
+ * Remove breakpoints from all disabled themes.
+ *
+ * @param array $theme_list
+ *   An array of theme names.
+ */
+function breakpoint_themes_disabled($theme_list) {
+  $breakpointsets = entity_load_multiple('breakpoint_breakpointset', $theme_list);
+  foreach ($breakpointsets as $breakpointset) {
+    $breakpointset->delete();
+    // delete all breakpoints defined by this theme.
+    $names = drupal_container()->get('config.storage')->listAll('breakpoints.breakpoint.' . Breakpoint::SOURCE_TYPE_THEME . '.' . $breakpointset->id() . '.');
+    $entity_info = entity_get_info('breakpoint_breakpoint');
+
+    foreach ($names as &$name) {
+      $name = substr($name, strlen($entity_info['config prefix']) + 1);
+    }
+    $breakpoints = entity_load_multiple('breakpoint_breakpoint', $names);
+
+    foreach ($breakpoints as $breakpoint) {
+      $breakpoint->delete();
+    }
+  }
+}
+
+/**
+ * Load general settings.
+ */
+function breakpoint_settings() {
+  $config = config('breakpoint');
+  if ($config->isNew()) {
+    return FALSE;
+  }
+  return (object)$config->get();
+}
+
+/**
+ * Save multipliers to settings.
+ *
+ * @param array $multipliers
+ *   array containing multipliers.
+ */
+function breakpoint_settings_save_multipliers($multipliers) {
+  $config = config('breakpoint');
+  $config->set('multipliers', $multipliers);
+  $config->save();
+}
+
+/**
+ * Reload breakpoint sets as they were defined in the theme.
+ *
+ * @param string $theme_key
+ *   The name of the theme.
+ *
+ * @return BreakpointSet
+ *   Returns a BreakpointSet containing the breakpoints defined by the theme.
+ */
+function breakpoint_breakpointset_reload_from_theme($theme_key) {
+  // Clear caches so theme.info is fresh.
+  system_rebuild_theme_data();
+  drupal_theme_rebuild();
+
+  $themes = list_themes();
+  if ($themes[$theme_key]->status) {
+    $theme_breakpoints = breakpoint_get_theme_breakpoint_list($theme_key);
+    if (!empty($theme_breakpoints)) {
+      $weight = 0;
+      // Build a set for each theme
+      $breakpointset = new BreakpointSet();
+      $breakpointset->id = $theme_key;
+      $breakpointset->label = $themes[$theme_key]->info['name'];
+      $breakpointset->sourceType = Breakpoint::SOURCE_TYPE_THEME;
+      foreach ($theme_breakpoints as $name => $mediaQuery) {
+        $breakpoint = new Breakpoint;
+        $breakpoint->name = $name;
+        $breakpoint->label = ucfirst($name);
+        $breakpoint->mediaQuery = $mediaQuery;
+        $breakpoint->source = $theme_key;
+        $breakpoint->sourceType = Breakpoint::SOURCE_TYPE_THEME;
+        $breakpoint->status = TRUE;
+        $breakpoint->weight = $weight++;
+        $breakpoint->save();
+        $breakpointset->breakpoints[$breakpoint->getConfigName()] = $breakpoint;
+      }
+    }
+    return $breakpointset;
+  }
+  return FALSE;
+}
+
+/**
+ * Get a list of available breakpoints from a specified theme.
+ *
+ * @param $theme_key
+ *   The name of the theme.
+ *
+ * @return
+ *   An array of breakpoints in the form $breakpoint['name'] = 'media query'.
+ */
+function breakpoint_get_theme_breakpoint_list($theme_key) {
+  $themes = list_themes();
+  if (!isset($themes[$theme_key])) {
+    return array();
+  }
+
+  $config = config($theme_key . '.breakpoints');
+  if ($config) {
+    return $config->get();
+  }
+  return array();
+}
+
+/**
+ * Implements hook_entity_info().
+ */
+function breakpoint_entity_info() {
+  // Breakpoint
+  $types['breakpoint_breakpoint'] = array(
+    'label' => 'Breakpoint',
+    'entity class' => 'Drupal\breakpoint\Breakpoint',
+    'controller class' => 'Drupal\Core\Config\Entity\ConfigStorageController',
+    'config prefix' => 'breakpoint.breakpoint',
+    'entity keys' => array(
+      'id' => 'id',
+      'label' => 'label',
+      'uuid' => 'uuid',
+    ),
+  );
+
+  // Breakpointset
+  $types['breakpoint_breakpointset'] = array(
+    'label' => 'Breakpoint Set',
+    'entity class' => 'Drupal\breakpoint\BreakpointSet',
+    'controller class' => 'Drupal\breakpoint\BreakpointSetController',
+    'config prefix' => 'breakpoint.breakpointset',
+    'entity keys' => array(
+      'id' => 'id',
+      'label' => 'label',
+      'uuid' => 'uuid',
+    ),
+  );
+
+  return $types;
+}
+
+/**
+ * Load one breakpoint set by its identifier.
+ */
+function breakpoint_breakpointset_load($id) {
+  return entity_load('breakpoint_breakpointset', $id);
+}
+
+/**
+ * Load all breakpoint sets.
+ */
+function breakpoint_breakpointset_load_all() {
+  $breakpointsets = entity_load_multiple('breakpoint_breakpointset');
+  return $breakpointsets;
+}
+
+/**
+ * Load one breakpoint by its identifier.
+ */
+function breakpoint_breakpoint_load($id) {
+  return entity_load('breakpoint_breakpoint', $id);
+}
+
+/**
+ * Load all breakpoints.
+ */
+function breakpoint_breakpoint_load_all() {
+  $breakpoints = entity_load_multiple('breakpoint_breakpoint');
+  return $breakpoints;
+}
+
+/**
+ * Load all breakpointsets as select options.
+ */
+function breakpoint_breakpointset_select_options() {
+  $options = array();
+  $breakpointsets = breakpoint_breakpointset_load_all();
+  foreach ($breakpointsets as $breakpointset) {
+    $options[$breakpointset->id()] = $breakpointset->label();
+  }
+  return $options;
+}
diff --git a/core/modules/breakpoint/config/breakpoint.yml b/core/modules/breakpoint/config/breakpoint.yml
new file mode 100644
index 0000000..0ba703d
--- /dev/null
+++ b/core/modules/breakpoint/config/breakpoint.yml
@@ -0,0 +1,2 @@
+multipliers: [1x, 1.5x, 2x]
+
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Breakpoint.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Breakpoint.php
new file mode 100644
index 0000000..9a3ce86
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Breakpoint.php
@@ -0,0 +1,294 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Breakpoint.
+ */
+
+namespace Drupal\breakpoint;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Exception;
+
+/**
+ * Defines the Breakpoint entity.
+ */
+class Breakpoint extends ConfigEntityBase {
+
+  /**
+   * The possible values for sourceType.
+   */
+  const SOURCE_TYPE_THEME = 'theme';
+  const SOURCE_TYPE_MODULE = 'module';
+  const SOURCE_TYPE_CUSTOM = 'custom';
+
+  /**
+   * The breakpoint ID (config name).
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The breakpoint UUID.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The breakpoint name (machine name).
+   *
+   * @var string
+   */
+  public $name;
+
+  /**
+   * The breakpoint label.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * The breakpoint media query.
+   *
+   * @var string
+   */
+  public $mediaQuery = '';
+
+  /**
+   * The breakpoint source.
+   *
+   * @var string
+   */
+  public $source = 'user';
+
+  /**
+   * The breakpoint source type.
+   *
+   * @var string
+   *   Allowed values:
+   *     Breakpoint::SOURCE_TYPE_THEME
+   *     Breakpoint::SOURCE_TYPE_MODULE
+   *     Breakpoint::SOURCE_TYPE_CUSTOM
+   */
+  public $sourceType = Breakpoint::SOURCE_TYPE_CUSTOM;
+
+  /**
+   * The breakpoint status.
+   *
+   * @var string
+   */
+  public $status = TRUE;
+
+  /**
+   * The breakpoint weight.
+   *
+   * @var weight
+   */
+  public $weight = 0;
+
+  /**
+   * The breakpoint multipliers.
+   *
+   * @var multipliers
+   */
+  public $multipliers = array();
+
+  /**
+   * Overrides Drupal\config\ConfigEntityBase::__construct().
+   */
+  public function __construct(array $values = array(), $entity_type = 'breakpoint_breakpoint') {
+    parent::__construct($values, $entity_type);
+  }
+
+  /**
+   * Overrides Drupal\config\ConfigEntityBase::save().
+   */
+  public function save() {
+    if (empty($this->id)) {
+      $this->id = $this->buildConfigName();
+    }
+    if (empty($this->label)) {
+      $this->label = ucfirst($this->name);
+    }
+    if (!$this->isValid()) {
+      throw new Exception(t('Invalid media query detected.'));
+    }
+    return parent::save();
+  }
+
+  /**
+   * Get config name.
+   */
+  public function getConfigName() {
+    return $this->sourceType
+      . '.' . $this->source
+      . '.' . $this->name;
+  }
+
+  /**
+   * Build config name.
+   */
+  protected function buildConfigName() {
+    // Check for illegal values in breakpoint source type.
+    if (!in_array($this->sourceType, array(
+        Breakpoint::SOURCE_TYPE_CUSTOM,
+        Breakpoint::SOURCE_TYPE_MODULE,
+        Breakpoint::SOURCE_TYPE_THEME)
+      )) {
+      throw new Exception(
+          t(
+            "Expected one of '@custom', '@module' or '@theme' for breakpoint sourceType property but got '@sourcetype'.",
+            array(
+              '@custom' => Breakpoint::SOURCE_TYPE_CUSTOM,
+              '@module' => Breakpoint::SOURCE_TYPE_MODULE,
+              '@theme' => Breakpoint::SOURCE_TYPE_THEME,
+              '@sourcetype' => $this->sourceType,
+            )
+          )
+      );
+    }
+    // Check for illegal characters in breakpoint source.
+    if (preg_match('/[^a-z_]+/', $this->source)) {
+      throw new Exception(t("Invalid value '@source' for breakpoint source property. Breakpoint source property can only contain lowercase letters and underscores.", array('@source' => $this->source)));
+    }
+    // Check for illegal characters in breakpoint names.
+    if (preg_match('/[^0-9a-z_\-]/', $this->name)) {
+      throw new Exception(t("Invalid value '@name' for breakpoint name property. Breakpoint name property can only contain lowercase alphanumeric characters, underscores (_), and hyphens (-).", array('@name' => $this->name)));
+    }
+    return $this->sourceType
+      . '.' . $this->source
+      . '.' . $this->name;
+  }
+
+  /**
+   * Shortcut function to enable a breakpoint and save it.
+   *
+   * @see breakpoint_breakpoint_action_confirm_submit()
+   */
+  public function enable() {
+    if (!$this->status) {
+      $this->status = 1;
+      $this->save();
+    }
+  }
+
+  /**
+   * Shortcut function to disable a breakpoint and save it.
+   *
+   * @see breakpoint_breakpoint_action_confirm_submit()
+   */
+  public function disable() {
+    if ($this->status) {
+      $this->status = 0;
+      $this->save();
+    }
+  }
+
+  /**
+   * Check if the mediaQuery is valid.
+   *
+   * @see isValidMediaQuery()
+   */
+  public function isValid() {
+    return $this::isValidMediaQuery($this->mediaQuery);
+  }
+
+  /**
+   * Check if a mediaQuery is valid.
+   *
+   * @see http://www.w3.org/TR/css3-mediaqueries/
+   * @see http://www.w3.org/Style/CSS/Test/MediaQueries/20120229/reports/implement-report.html
+   */
+  public static function isValidMediaQuery($media_query) {
+    $media_features = array(
+      'width' => 'length', 'min-width' => 'length', 'max-width' => 'length',
+      'height' => 'length', 'min-height' => 'length', 'max-height' => 'length',
+      'device-width' => 'length', 'min-device-width' => 'length', 'max-device-width' => 'length',
+      'device-height' => 'length', 'min-device-height' => 'length', 'max-device-height' => 'length',
+      'orientation' => array('portrait', 'landscape'),
+      'aspect-ratio' => 'ratio', 'min-aspect-ratio' => 'ratio', 'max-aspect-ratio' => 'ratio',
+      'device-aspect-ratio' => 'ratio', 'min-device-aspect-ratio' => 'ratio', 'max-device-aspect-ratio' => 'ratio',
+      'color' => 'integer', 'min-color' => 'integer', 'max-color' => 'integer',
+      'color-index' => 'integer', 'min-color-index' => 'integer', 'max-color-index' => 'integer',
+      'monochrome' => 'integer', 'min-monochrome' => 'integer', 'max-monochrome' => 'integer',
+      'resolution' => 'resolution', 'min-resolution' => 'resolution', 'max-resolution' => 'resolution',
+      'scan' => array('progressive', 'interlace'),
+      'grid' => 'integer',
+    );
+    if ($media_query) {
+      // Strip new lines and trim.
+      $media_query = str_replace(array("\r", "\n"), ' ', trim($media_query));
+
+      // Remove comments /* ... */.
+      $media_query = preg_replace('/\/\*[\s\S]*?\*\//', '', $media_query);
+
+      // Check mediaQuery_list: S* [mediaQuery [ ',' S* mediaQuery ]* ]?
+      $parts = explode(',', $media_query);
+      foreach ($parts as $part) {
+        // Split on ' and '
+        $query_parts = explode(' and ', trim($part));
+        $media_type_found = FALSE;
+        foreach ($query_parts as $query_part) {
+          $matches = array();
+          // Check expression: '(' S* media_feature S* [ ':' S* expr ]? ')' S*
+          if (preg_match('/^\(([\w\-]+)(:\s?([\w\-]+))?\)/', trim($query_part), $matches)) {
+            // Single expression.
+            if (isset($matches[1]) && !isset($matches[2])) {
+              if (!array_key_exists($matches[1], $media_features)) {
+                return FALSE;
+              }
+            }
+            // Full expression.
+            elseif (isset($matches[3]) && !isset($matches[4])) {
+              $value = trim($matches[3]);
+              if (!array_key_exists($matches[1], $media_features)) {
+                return FALSE;
+              }
+              if (is_array($media_features[$matches[1]])) {
+                // Check if value is allowed.
+                if (!array_key_exists($value, $media_features[$matches[1]])) {
+                  return FALSE;
+                }
+              }
+              else {
+                switch ($media_features[$matches[1]]) {
+                  case 'length':
+                    $length_matches = array();
+                    if (preg_match('/^(\-)?(\d+)?((?:|em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|dpi|dpcm))$/i', trim($value), $length_matches)) {
+                      // Only -0 is allowed.
+                      if ($length_matches[1] === '-' && $length_matches[2] !== '0') {
+                        return FALSE;
+                      }
+                      // If there's a unit, a number is needed as well.
+                      if ($length_matches[2] === '' && $length_matches[3] !== '') {
+                        return FALSE;
+                      }
+                    }
+                    else {
+                      return FALSE;
+                    }
+                    break;
+                }
+              }
+            }
+          }
+          // Check [ONLY | NOT]? S* media_type
+          elseif (preg_match('/((?:only|not)?\s?)([\w\-]+)$/i', trim($query_part), $matches)) {
+            if ($media_type_found) {
+              throw new Exception(t('Only when media type allowed.'));
+            }
+            $media_type_found = TRUE;
+          }
+          else {
+            throw new Exception(t("Invalid value '@query_part' for breakpoint media query property.", array('@query_part' => $query_part)));
+          }
+        }
+      }
+      return TRUE;
+    }
+    return FALSE;
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointSet.php b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointSet.php
new file mode 100644
index 0000000..fd8566e
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointSet.php
@@ -0,0 +1,124 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\breakpoint\BreakpointSet.
+ */
+
+namespace Drupal\breakpoint;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+
+/**
+ * Defines the BreakpointSet entity.
+ */
+class BreakpointSet extends ConfigEntityBase {
+
+  /**
+   * The BreakpointSet ID (machine name).
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The BreakpointSet UUID.
+   *
+   * @var string
+   */
+  public $uuid;
+
+  /**
+   * The BreakpointSet label.
+   *
+   * @var string
+   */
+  public $label;
+
+  /**
+   * The BreakpointSet breakpoints.
+   *
+   * @var array
+   *   Array containing all breakpoints of this set.
+   *
+   * @see Drupal\breakpoints\Breakpoint
+   */
+  public $breakpoints = array();
+
+  /**
+   * The BreakpointSet source type.
+   *
+   * @var string
+   *   Allowed values:
+   *     Breakpoint::SOURCE_TYPE_THEME
+   *     Breakpoint::SOURCE_TYPE_MODULE
+   *     Breakpoint::SOURCE_TYPE_CUSTOM
+   *
+   * @see Drupal\breakpoint\Breakpoint
+   */
+  public $sourceType = Breakpoint::SOURCE_TYPE_CUSTOM;
+
+  /**
+   * The BreakpointSet overridden status.
+   *
+   * @var string
+   */
+  public $overridden = FALSE;
+
+  /**
+   * Overrides Drupal\config\ConfigEntityBase::__construct().
+   */
+  public function __construct(array $values = array(), $entity_type = 'breakpoint_breakpointset') {
+    parent::__construct($values, $entity_type);
+    $this->loadAllBreakpoints();
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity::save().
+   */
+  public function save() {
+    // Only save the keys, but return the full objects.
+    $this->breakpoints = array_keys($this->breakpoints);
+    parent::save();
+    $this->loadAllBreakpoints();
+  }
+
+  /**
+   * Override and save a breakpoint set.
+   */
+  public function override() {
+    return entity_get_controller($this->entityType)->override($this);
+  }
+
+  /**
+   * Revert a breakpoint set after it has been overridden.
+   */
+  public function revert() {
+    return entity_get_controller($this->entityType)->revert($this);
+  }
+
+  /**
+   * Implements EntityInterface::createDuplicate().
+   */
+  public function createDuplicate() {
+    $duplicate = new BreakpointSet();
+    $duplicate->id = '';
+    $duplicate->label = t('Clone of') . ' ' . $this->label();
+    $duplicate->breakpoints = $this->breakpoints;
+    return $duplicate;
+  }
+
+  /**
+   * Load all breakpoints, remove non-existing ones.
+   */
+  protected function loadAllBreakpoints() {
+    $breakpoints = $this->breakpoints;
+    $this->breakpoints = array();
+    foreach ($breakpoints as $breakpoint_id) {
+      $breakpoint = breakpoint_breakpoint_load($breakpoint_id);
+      if ($breakpoint) {
+        $this->breakpoints[$breakpoint_id] = $breakpoint;
+      }
+    }
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointSetController.php b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointSetController.php
new file mode 100644
index 0000000..7f688f0
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/BreakpointSetController.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\BreakpointSetController.
+ */
+
+namespace Drupal\breakpoint;
+
+use Drupal\Core\Config\Entity\ConfigStorageController;
+use Drupal\breakpoint\BreakpointSet;
+use Drupal\breakpoint\Breakpoint;
+
+/**
+ * Defines the BreakpointSet entity's controller.
+ */
+class BreakpointSetController extends ConfigStorageController {
+
+  /**
+   * Override and save a breakpoint set.
+   */
+  public function override(BreakpointSet $breakpointset) {
+    if (!$breakpointset->sourceType == Breakpoint::SOURCE_TYPE_THEME) {
+      return FALSE;
+    }
+    foreach ($breakpointset->breakpoints as $key => $breakpoint) {
+      if ($breakpoint->sourceType == Breakpoint::SOURCE_TYPE_THEME && $breakpoint->source == $breakpointset->id()) {
+        $new_breakpoint = $breakpoint->createDuplicate();
+        $new_breakpoint->id = '';
+        $new_breakpoint->sourceType = Breakpoint::SOURCE_TYPE_CUSTOM;
+        $new_breakpoint->save();
+
+        // Remove old one, add new one.
+        unset($breakpointset->breakpoints[$key]);
+        $breakpointset->breakpoints[$new_breakpoint->id] = $new_breakpoint;
+      }
+    }
+    $breakpointset->overridden = TRUE;
+    $breakpointset->save();
+    return $breakpointset;
+  }
+
+  /**
+   * Revert a breakpoint set after it has been overridden.
+   */
+  public function revert(BreakpointSet $breakpointset) {
+    if (!$breakpointset->overridden || !$breakpointset->sourceType == Breakpoint::SOURCE_TYPE_THEME) {
+      return FALSE;
+    }
+
+    // Reload all breakpoints from theme.
+    $reloaded_set = breakpoint_breakpointset_reload_from_theme($breakpointset->id());
+    if ($reloaded_set) {
+      $breakpointset->breakpoints = $reloaded_set->breakpoints;
+      $breakpointset->overridden = FALSE;
+      $breakpointset->save();
+    }
+    return $breakpointset;
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointApiTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointApiTest.php
new file mode 100644
index 0000000..0cc3adb
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointApiTest.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Tests\BreakpointsApiTest.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\breakpoint\Tests\BreakpointsTestBase;
+use Drupal\breakpoint\Breakpoint;
+use Exception;
+
+/**
+ * Tests for general breakpoint api functions.
+ */
+class BreakpointApiTest extends BreakpointTestBase {
+
+  /**
+   * Drupal\simpletest\WebTestBase\getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Breakpoint general API functions',
+      'description' => 'Test general API functions of the breakpoint module.',
+      'group' => 'Breakpoint',
+    );
+  }
+
+  /**
+   * Test Breakpoint::buildConfigName().
+   */
+  public function testConfigName() {
+    $breakpoint = new Breakpoint(
+      array(
+        'label' => drupal_strtolower($this->randomName()),
+        'source' => 'custom_module',
+        // Try an invalid sourceType.
+        'sourceType' => 'oops',
+      )
+    );
+
+    try {
+      $breakpoint->save();
+    }
+    catch (Exception $e) {
+      $exception = TRUE;
+    }
+    $this->assertTrue($exception, t('breakpoint_breakpoint_config_name: An exception is thrown when an invalid sourceType is entered.'));
+    $this->assertEqual((string) $breakpoint->id(), '', t('breakpoint_breakpoint_config_name: No id is set when an invalid sourceType is entered.'));
+
+    // Try an invalid source.
+    $breakpoint->sourceType = Breakpoint::SOURCE_TYPE_CUSTOM;
+    $breakpoint->source = 'custom*_module source';
+    $exception = FALSE;
+    try {
+      $breakpoint->save();
+    }
+    catch (Exception $e) {
+      $exception = TRUE;
+    }
+    $this->assertTrue($exception, t('breakpoint_breakpoint_config_name: An exception is thrown when an invalid source is entered.'));
+    $this->assertEqual((string) $breakpoint->id(), '', t('breakpoint_breakpoint_config_name: No id is set when an invalid sourceType is entered.'));
+
+    // Try an invalid name (make sure there is at least once capital letter).
+    $breakpoint->source = 'custom_module';
+    $breakpoint->name = drupal_ucfirst($this->randomName());
+    $exception = FALSE;
+    try {
+      $breakpoint->save();
+    }
+    catch (Exception $e) {
+      $exception = TRUE;
+    }
+    $this->assertTrue($exception, t('breakpoint_breakpoint_config_name: An exception is thrown when an invalid name is entered.'));
+    $this->assertEqual((string) $breakpoint->id(), '', t('breakpoint_breakpoint_config_name: No id is set when an invalid sourceType is entered.'));
+
+    // Try a valid breakpoint.
+    $breakpoint->name = drupal_strtolower($this->randomName());
+    $breakpoint->mediaQuery = 'all';
+    $exception = FALSE;
+    try {
+      $breakpoint->save();
+    }
+    catch (Exception $e) {
+      $exception = TRUE;
+    }
+    $this->assertFalse($exception, t('breakpoint_breakpoint_config_name: No exception is thrown when a valid breakpoint is passed.'));
+    $this->assertEqual($breakpoint->id(), Breakpoint::SOURCE_TYPE_CUSTOM . '.custom_module.' . $breakpoint->name, t('breakpoint_breakpoint_config_name: A id is set when a valid breakpoint is passed.'));
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointCrudTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointCrudTest.php
new file mode 100644
index 0000000..54f443b
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointCrudTest.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Tests\BreakpointCrudTest.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\breakpoint\Tests\BreakpointTestBase;
+use Drupal\breakpoint\Breakpoint;
+
+/**
+ * Tests for breakpoint CRUD operations.
+ */
+class BreakpointCrudTest extends BreakpointTestBase {
+
+  /**
+   * Drupal\simpletest\WebTestBase\getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Breakpoint CRUD operations',
+      'description' => 'Test creation, loading, updating, deleting of breakpoints.',
+      'group' => 'Breakpoint',
+    );
+  }
+
+  /**
+   * Test CRUD operations for breakpoints.
+   */
+  public function testBreakpointCrud() {
+    // Add a breakpoint with minimum data only.
+    $values = array(
+      'label' => drupal_strtolower($this->randomName()),
+      'mediaQuery' => '(min-width: 600px)',
+    );
+
+    $breakpoint = new Breakpoint($values);
+    $breakpoint->save();
+
+    $this->verifyBreakpoint($breakpoint);
+
+    // Test breakpoint_breakpoint_load_all
+    $all_breakpoints = breakpoint_breakpoint_load_all();
+    $config_name = $breakpoint->getConfigName();
+    $this->assertTrue(isset($all_breakpoints[$config_name]), t('breakpoint_breakpoint_load_all: New breakpoint is present when loading all breakpoints.'));
+    $this->verifyBreakpoint($breakpoint, $all_breakpoints[$config_name]);
+
+    // Update the breakpoint.
+    $breakpoint->weight = 1;
+    $breakpoint->multipliers['2x'] = '2x';
+    $breakpoint->save();
+    $this->verifyBreakpoint($breakpoint);
+
+    // Disable the breakpoint.
+    $breakpoint->disable();
+    $this->verifyBreakpoint($breakpoint);
+
+    // Delete the breakpoint.
+    $breakpoint->delete();
+    $this->assertFalse(breakpoint_breakpoint_load($config_name), t('breakpoint_breakpoint_load: Loading a deleted breakpoint returns false.'), t('Breakpoints API'));
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php
new file mode 100644
index 0000000..68438dc
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Tests\BreakpointMediaQueryTest.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\simpletest\UnitTestBase;
+use Drupal\breakpoint\Breakpoint;
+use Exception;
+
+/**
+ * Tests for media queries in a breakpoint.
+ */
+class BreakpointMediaQueryTest extends UnitTestBase {
+
+  /**
+   * Drupal\simpletest\WebTestBase\getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Breakpoint media query tests',
+      'description' => 'Test validation of media queries.',
+      'group' => 'Breakpoint',
+    );
+  }
+
+  /**
+   * Test valid media queries.
+   */
+  public function testValidMediaQueries() {
+    $media_queries = array(
+      // Bartik breakpoints.
+      '(min-width: 0px)',
+      'all and (min-width: 560px) and (max-width:850px)',
+      'all and (min-width: 851px)',
+      // Seven breakpoints.
+      '(min-width: 0em)',
+      'screen and (min-width: 40em)',
+      // Stark breakpoints.
+      '(min-width: 0px)',
+      'all and (min-width: 480px) and (max-width: 959px)',
+      'all and (min-width: 960px)',
+      '(orientation)',
+      'all and (orientation)',
+      'not all and (orientation)',
+      'only all and (orientation)',
+      'screen and (width)',
+      'screen and (width: 0)',
+      'screen and (width: 0px)',
+      'screen and (width: 0em)',
+      'screen and (min-width: -0)',
+      'screen and (max-width: 0)',
+      'screen and (min-width)',
+      // Multiline and comments.
+      'screen and /* this is a comment */ (min-width)',
+      "screen\nand /* this is a comment */ (min-width)",
+      "screen\n\nand /* this is\n a comment */ (min-width)",
+    );
+
+    foreach ($media_queries as $media_query) {
+      try {
+        $this->assertTrue(Breakpoint::isValidMediaQuery($media_query), $media_query . ' is valid.');
+      }
+      catch (Exception $e) {
+        $this->assertTrue(FALSE, $media_query . ' is valid.');
+      }
+    }
+  }
+
+  /**
+   * Test invalid media queries.
+   */
+  public function testInvalidMediaQueries() {
+    $media_queries = array(
+      'not (orientation)',
+      'only (orientation)',
+      'all and not all',
+      'screen and (width: 0xx)',
+      'screen and (width: -8xx)',
+      'screen and (width: -xx)',
+      'screen and (width: xx)',
+      'screen and (width: px)',
+      'screen and (width: -8px)',
+      'screen and (width: -0.8px)',
+      'screen and (height: 0xx)',
+      'screen and (height: -8xx)',
+      'screen and (height: -xx)',
+      'screen and (height: xx)',
+      'screen and (height: px)',
+      'screen and (height: -8px)',
+      'screen and (height: -0.8px)',
+      'screen and (device-width: 0xx)',
+      'screen and (device-width: -8xx)',
+      'screen and (device-width: -xx)',
+      'screen and (device-width: xx)',
+      'screen and (device-width: px)',
+      'screen and (device-width: -8px)',
+      'screen and (device-width: -0.8px)',
+      'screen and (device-height: 0xx)',
+      'screen and (device-height: -8xx)',
+      'screen and (device-height: -xx)',
+      'screen and (device-height: xx)',
+      'screen and (device-height: px)',
+      'screen and (device-height: -8px)',
+      'screen and (device-height: -0.8px)',
+      'screen and (min-orientation)',
+      'screen and (max-orientation)',
+      'screen and (min-orientation: landscape)',
+      'screen and (max-orientation: landscape)',
+      'screen and (orientation: bogus)',
+      '(orientation: bogus)',
+    );
+
+    foreach ($media_queries as $media_query) {
+      try {
+        $this->assertFalse(Breakpoint::isValidMediaQuery($media_query), $media_query . ' is not valid.');
+      }
+      catch (Exception $e) {
+        $this->assertTrue(TRUE, $media_query . ' is not valid.');
+      }
+    }
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointSetCrudTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointSetCrudTest.php
new file mode 100644
index 0000000..ef6f6e8
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointSetCrudTest.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Tests\BreakpointSetCrudTest.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\breakpoint\Tests\BreakpointSetTestBase;
+use Drupal\breakpoint\BreakpointSet;
+use Drupal\breakpoint\Breakpoint;
+
+/**
+ * Tests for breakpoint set CRUD operations.
+ */
+class BreakpointSetCrudTest extends BreakpointSetTestBase {
+
+  /**
+   * Drupal\simpletest\WebTestBase\getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Breakpoint Set CRUD operations',
+      'description' => 'Test creation, loading, updating, deleting of breakpoint sets.',
+      'group' => 'Breakpoint',
+    );
+  }
+
+  /**
+   * Test CRUD operations for breakpoint sets.
+   */
+  public function testBreakpointSetCrud() {
+    // Add breakpoints.
+    $breakpoints = array();
+    for ($i = 0; $i <= 3; $i++) {
+      $width = ($i + 1) * 200;
+      $values = array(
+        'name' => drupal_strtolower($this->randomName()),
+        'weight' => $i,
+        'mediaQuery' => "(min-width: {$width}px)",
+      );
+      $breakpoint = new Breakpoint($values);
+      $breakpoint->save();
+      $breakpoints[$breakpoint->id()] = $breakpoint;
+    }
+    // Add a breakpoint set with minimum data only.
+    $label = $this->randomName();
+    $values = array(
+      'label' => $label,
+      'id' => drupal_strtolower($label),
+    );
+
+    $set = new BreakpointSet($values);
+    $set->save();
+    $this->verifyBreakpointSet($set);
+
+    // Update the breakpoint set.
+    $set->breakpoints = array_keys($breakpoints);
+    $set->save();
+    $this->verifyBreakpointSet($set);
+
+    // Duplicate the breakpoint set.
+    $new_set = new BreakpointSet();
+    $new_set->label = t('Clone of') . ' ' . $set->label();
+    $new_set->id = '';
+    $new_set->sourceType = Breakpoint::SOURCE_TYPE_CUSTOM;
+    $new_set->breakpoints = $set->breakpoints;
+    $duplicated_set = $set->createDuplicate();
+    $this->verifyBreakpointSet($duplicated_set, $new_set);
+
+    // Delete the breakpoint set.
+    $set->delete();
+    $this->assertFalse(breakpoint_breakpointset_load($set->id), t('breakpoint_breakpointset_load: Loading a deleted breakpoint set returns false.'), t('Breakpoints API'));
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointSetTestBase.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointSetTestBase.php
new file mode 100644
index 0000000..dc9dcf9
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointSetTestBase.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Tests\BreakpointSetTestBase.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\breakpoint\BreakpointSet;
+
+/**
+ * Base class for Breakpoint Set tests.
+ */
+abstract class BreakpointSetTestBase extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('breakpoint');
+
+  /**
+   * Drupal\simpletest\WebTestBase\setUp().
+   */
+  public function setUp() {
+    parent::setUp();
+  }
+
+  /**
+   * Verify that a breakpoint is properly stored.
+   */
+  public function verifyBreakpointSet(BreakpointSet $set, BreakpointSet $compare_set = NULL) {
+    $properties = array(
+      'label',
+      'id',
+      'breakpoints',
+      'overridden',
+      'sourceType',
+    );
+    $assert_set = t('Breakpoints API');
+
+    // Verify breakpoint_breakpointset_load().
+    $compare_set = is_null($compare_set) ? breakpoint_breakpointset_load($set->id) : $compare_set;
+
+    foreach ($properties as $property) {
+      $t_args = array(
+        '%set' => $set->label(),
+        '%property' => $property,
+      );
+      if (is_array($compare_set->{$property})) {
+        $this->assertEqual(array_keys($compare_set->{$property}), array_keys($set->{$property}), t('breakpoint_breakpointset_load: Proper %property for breakpoint set %set.', $t_args), $assert_set);
+      }
+      else {
+        $this->assertEqual($compare_set->{$property}, $set->{$property}, t('breakpoint_breakpointset_load: Proper %property . for breakpoint set %set.', $t_args), $assert_set);
+      }
+    }
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointTestBase.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointTestBase.php
new file mode 100644
index 0000000..72f8d91
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointTestBase.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Tests\BreakpointTestBase.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\breakpoint\Breakpoint;
+
+/**
+ * Base class for Breakpoint tests.
+ */
+abstract class BreakpointTestBase extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('breakpoint');
+
+  /**
+   * Drupal\simpletest\WebTestBase\setUp().
+   */
+  public function setUp() {
+    parent::setUp();
+  }
+
+  /**
+   * Verify that a breakpoint is properly stored.
+   */
+  public function verifyBreakpoint(Breakpoint $breakpoint, Breakpoint $compare_breakpoint = NULL) {
+    $properties = array(
+      'label',
+      'mediaQuery',
+      'source',
+      'sourceType',
+      'status',
+      'weight',
+      'multipliers',
+    );
+    $assert_group = t('Breakpoints API');
+
+    // Verify breakpoint_breakpoint_load().
+    $compare_breakpoint = is_null($compare_breakpoint) ? breakpoint_breakpoint_load($breakpoint->getConfigName()) : $compare_breakpoint;
+    foreach ($properties as $property) {
+      $t_args = array(
+        '%breakpoint' => $breakpoint->label(),
+        '%property' => $property,
+      );
+      $this->assertEqual($compare_breakpoint->{$property}, $breakpoint->{$property}, t('breakpoint_breakpoint_load: Proper %property for breakpoint %breakpoint.', $t_args), $assert_group);
+    }
+  }
+}
diff --git a/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
new file mode 100644
index 0000000..0ccad65
--- /dev/null
+++ b/core/modules/breakpoint/lib/Drupal/breakpoint/Tests/BreakpointThemeTest.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * @file
+ * Definition of Drupal\breakpoint\Tests\BreakpointsThemeTest.
+ */
+
+namespace Drupal\breakpoint\Tests;
+
+use Drupal\breakpoint\Tests\BreakpointSetTestBase;
+use Drupal\breakpoint\BreakpointSet;
+use Drupal\breakpoint\Breakpoint;
+
+/**
+ * Test breakpoints provided by themes.
+ */
+class BreakpointThemeTest extends BreakpointSetTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('breakpoint_theme_test');
+
+  /**
+   * Drupal\simpletest\WebTestBase\getInfo().
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'Breakpoint Theme functionality',
+      'description' => 'Thoroughly test the breakpoints provided by a theme.',
+      'group' => 'Breakpoint',
+    );
+  }
+
+  /**
+   * Drupal\simpletest\WebTestBase\setUp().
+   */
+  public function setUp() {
+    parent::setUp();
+    theme_enable(array('breakpoint_test_theme'));
+  }
+
+  /**
+   * Test the breakpoints provided by a theme.
+   */
+  public function testThemeBreakpoints() {
+    // Verify the breakpoint group for breakpoint_test_theme was created.
+    $breakpointset_obj = new BreakpointSet();
+    $breakpointset_obj->label = 'Breakpoint test theme';
+    $breakpointset_obj->id = 'breakpoint_test_theme';
+    $breakpointset_obj->sourceType = Breakpoint::SOURCE_TYPE_THEME;
+    $breakpointset_obj->breakpoints = array(
+      'theme.breakpoint_test_theme.mobile' => array(),
+      'theme.breakpoint_test_theme.narrow' => array(),
+      'theme.breakpoint_test_theme.wide' => array(),
+      'theme.breakpoint_test_theme.tv' => array(),
+    );
+    $breakpointset_obj->overridden = 0;
+
+    // Verify we can load this breakpoint defined by the theme.
+    $this->verifyBreakpointSet($breakpointset_obj);
+
+    // Override the breakpoints.
+    $overridden_set = clone $breakpointset_obj;
+    $breakpointset = breakpoint_breakpointset_load('breakpoint_test_theme');
+    $breakpointset = $breakpointset->override();
+
+    // Verify the group is overridden.
+    $overridden_set->breakpoints = array(
+      'custom.breakpoint_test_theme.mobile' => array(),
+      'custom.breakpoint_test_theme.narrow' => array(),
+      'custom.breakpoint_test_theme.wide' => array(),
+      'custom.breakpoint_test_theme.tv' => array(),
+    );
+    $overridden_set->overridden = 1;
+    $this->verifyBreakpointSet($overridden_set);
+
+    // Revert the breakpoint set.
+    $breakpointset = breakpoint_breakpointset_load('breakpoint_test_theme');
+    $breakpointset = $breakpointset->revert();
+
+    // Verify the breakpointset has its original values again when loaded.
+    $this->verifyBreakpointSet($breakpointset_obj);
+
+    // Disable the test theme and verify the breakpoint group is deleted.
+    theme_disable(array('breakpoint_test_theme'));
+    $this->assertFalse(breakpoint_breakpointset_load('breakpoint_test_theme'), t('breakpoint_breakpoint_group_load: Loading a deleted breakpoint group returns false.'), t('Breakpoints API'));
+  }
+}
diff --git a/core/modules/breakpoint/tests/breakpoint_theme_test.info b/core/modules/breakpoint/tests/breakpoint_theme_test.info
new file mode 100644
index 0000000..f934419
--- /dev/null
+++ b/core/modules/breakpoint/tests/breakpoint_theme_test.info
@@ -0,0 +1,5 @@
+name = Breakpoint theme test
+description = Test breakpoints provided by themes
+package = Other
+core = 8.x
+hidden = TRUE
diff --git a/core/modules/breakpoint/tests/breakpoint_theme_test.module b/core/modules/breakpoint/tests/breakpoint_theme_test.module
new file mode 100644
index 0000000..50b5ff0
--- /dev/null
+++ b/core/modules/breakpoint/tests/breakpoint_theme_test.module
@@ -0,0 +1,13 @@
+<?php
+/**
+ * @file
+ * Test breakpoint functionality for breakpoints provided by themes.
+ */
+
+/**
+ * Implements hook_system_theme_info().
+ */
+function breakpoint_theme_test_system_theme_info() {
+  $themes['breakpoint_test_theme'] = drupal_get_path('module', 'breakpoint_theme_test') . '/themes/breakpoint_test_theme/breakpoint_test_theme.info';
+  return $themes;
+}
diff --git a/core/modules/breakpoint/tests/themes/breakpoint_test_theme/breakpoint_test_theme.info b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/breakpoint_test_theme.info
new file mode 100644
index 0000000..b3ca39f
--- /dev/null
+++ b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/breakpoint_test_theme.info
@@ -0,0 +1,5 @@
+name = Breakpoint test theme
+description = Test theme for breakpoint.
+core = 8.x
+base theme = bartik
+hidden = FALSE
diff --git a/core/modules/breakpoint/tests/themes/breakpoint_test_theme/config/breakpoint_test_theme.breakpoints.yml b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/config/breakpoint_test_theme.breakpoints.yml
new file mode 100644
index 0000000..534fbf5
--- /dev/null
+++ b/core/modules/breakpoint/tests/themes/breakpoint_test_theme/config/breakpoint_test_theme.breakpoints.yml
@@ -0,0 +1,4 @@
+mobile: '(min-width: 0px)'
+narrow: '(min-width: 560px)'
+wide: '(min-width: 851px)'
+tv: 'only screen and (min-width: 3456px)'
