first commit

This commit is contained in:
2024-07-15 12:33:27 +02:00
commit ce50ae282b
22084 changed files with 2623791 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
name: Breakpoint
type: module
description: 'Manages breakpoints and breakpoint groups for responsive designs.'
package: Core
# version: VERSION
# Information added by Drupal.org packaging script on 2024-07-04
version: '10.3.1'
project: 'drupal'
datestamp: 1720094222

View File

@@ -0,0 +1,51 @@
<?php
/**
* @file
* Manage breakpoints and breakpoint groups for responsive designs.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function breakpoint_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.breakpoint':
$output = '';
$output .= '<h2>' . t('About') . '</h2>';
$output .= '<p>' . t('The Breakpoint module keeps track of the height, width, and resolution breakpoints where a responsive design needs to change in order to respond to different devices being used to view the site. This module does not have a user interface. For more information, see the <a href=":docs">online documentation for the Breakpoint module</a>.', [':docs' => 'https://www.drupal.org/documentation/modules/breakpoint']) . '</p>';
$output .= '<h4>' . t('Terminology') . '</h4>';
$output .= '<dl>';
$output .= '<dt>' . t('Breakpoint') . '</dt>';
$output .= '<dd>' . t('A breakpoint separates the height or width of viewports (screens, printers, and other media output types) into steps. For instance, a width breakpoint of 40em creates two steps: one for widths up to 40em and one for widths above 40em. Breakpoints can be used to define when layouts should shift from one form to another, when images should be resized, and other changes that need to respond to changes in viewport height or width.') . '</dd>';
$output .= '<dt>' . t('Media query') . '</dt>';
$output .= '<dd>' . t('<a href=":w3">Media queries</a> are a formal way to encode breakpoints. For instance, a width breakpoint at 40em would be written as the media query "(min-width: 40em)". Breakpoints are really just media queries with some additional meta-data, such as a name and multiplier information.', [':w3' => 'http://www.w3.org/TR/css3-mediaqueries/']) . '</dd>';
$output .= '<dt>' . t('Resolution multiplier') . '</dt>';
$output .= '<dd>' . t('Resolution multipliers are a measure of the viewport\'s device resolution, defined to be the ratio between the physical pixel size of the active device and the <a href="http://en.wikipedia.org/wiki/Device_independent_pixel">device-independent pixel</a> size. The Breakpoint module defines multipliers of 1, 1.5, and 2; when defining breakpoints, modules and themes can define which multipliers apply to each breakpoint.') . '</dd>';
$output .= '<dt>' . t('Breakpoint group') . '</dt>';
$output .= '<dd>' . t('Breakpoints can be organized into groups. Modules and themes should use groups to separate out breakpoints that are meant to be used for different purposes, such as breakpoints for layouts or breakpoints for image sizing.') . '</dd>';
$output .= '</dl>';
$output .= '<h2>' . t('Uses') . '</h2>';
$output .= '<dl>';
$output .= '<dt>' . t('Defining breakpoints and breakpoint groups') . '</dt>';
$output .= '<dd>' . t('Modules and themes can use the API provided by the Breakpoint module to define breakpoints and breakpoint groups, and to assign resolution multipliers to breakpoints.') . '</dd>';
$output .= '</dl>';
return $output;
}
}
/**
* Implements hook_themes_installed().
*/
function breakpoint_themes_installed($theme_list) {
\Drupal::service('breakpoint.manager')->clearCachedDefinitions();
}
/**
* Implements hook_themes_uninstalled().
*/
function breakpoint_themes_uninstalled($theme_list) {
\Drupal::service('breakpoint.manager')->clearCachedDefinitions();
}

View File

@@ -0,0 +1,7 @@
services:
breakpoint.manager:
class: Drupal\breakpoint\BreakpointManager
arguments: ['@module_handler', '@theme_handler', '@cache.discovery', '@string_translation', '@extension.list.module']
tags:
- { name: plugin_manager_cache_clear }
Drupal\breakpoint\BreakpointManagerInterface: '@breakpoint.manager'

View File

@@ -0,0 +1,21 @@
---
label: 'Managing height, width, and resolution breakpoints'
related:
- core.appearance
---
<h2>{% trans %}What are breakpoints?{% endtrans %}</h2>
<p>{% trans %}Breakpoints are the point at which your site's content will respond to provide the user with the best possible layout to consume the information. A breakpoint separates the height or width of viewports (screens, printers, and other media output types) into steps. For instance, a width breakpoint of 40em creates two steps: one for widths up to 40em and one for widths above 40em. Breakpoints can be used to define when layouts should shift from one form to another, when images should be resized, and other changes that need to respond to changes in viewport height or width.{% endtrans %}</p>
<h2>{% trans %}What are media queries?{% endtrans %}</h2>
<p>{% trans %}Media queries are a formal way to encode breakpoints. For instance, a width breakpoint at 40em would be written as the media query "(min-width: 40em)". Breakpoints are really just media queries with some additional meta-data, such as a name and multiplier information.{% endtrans %}</p>
<h2>{% trans %}What are resolution multipliers?{% endtrans %}</h2>
<p>{% trans %}Resolution multipliers are a measure of the viewport's device resolution, defined to be the ratio between the physical pixel size of the active device and the <a href="http://en.wikipedia.org/wiki/Device_independent_pixel">device-independent pixel</a> size. The Breakpoint module defines multipliers of 1, 1.5, and 2; when defining breakpoints, modules and themes can define which multipliers apply to each breakpoint.{% endtrans %}</p>
<h2>{% trans %}What is a breakpoint group?{% endtrans %}</h2>
<p>{% trans %}Breakpoints can be organized into groups. Modules and themes should use groups to separate out breakpoints that are meant to be used for different purposes, such as breakpoints for layouts or breakpoints for image sizing.{% endtrans %}</p>
<h2>{% trans %}Managing breakpoints and breakpoint groups overview{% endtrans %}</h2>
<p>{% trans %}The <em>Breakpoint</em> module allows you to define breakpoints and breakpoint groups in YAML files. Modules and themes can use the API provided by the <em>Breakpoint</em> module to define breakpoints and breakpoint groups, and to assign resolution multipliers to breakpoints.{% endtrans %}
</p>
<h2>{% trans %}Additional resources{% endtrans %}</h2>
<ul>
<li><a href="https://www.drupal.org/documentation/modules/breakpoint">{% trans %}Working with breakpoints in Drupal{% endtrans %}</a></li>
<li><a href="http://www.w3.org/TR/css3-mediaqueries/">{% trans %}W3C standards for media queries{% endtrans %}</a></li>
</ul>

View File

@@ -0,0 +1,57 @@
<?php
namespace Drupal\breakpoint;
use Drupal\Core\Plugin\PluginBase;
/**
* Default object used for breakpoint plugins.
*
* @see \Drupal\breakpoint\BreakpointManager
* @see plugin_api
*/
class Breakpoint extends PluginBase implements BreakpointInterface {
/**
* {@inheritdoc}
*/
public function getLabel() {
return $this->t($this->pluginDefinition['label'], [], ['context' => 'breakpoint']);
}
/**
* {@inheritdoc}
*/
public function getWeight() {
return (int) $this->pluginDefinition['weight'];
}
/**
* {@inheritdoc}
*/
public function getMediaQuery() {
return $this->pluginDefinition['mediaQuery'];
}
/**
* {@inheritdoc}
*/
public function getMultipliers() {
return $this->pluginDefinition['multipliers'];
}
/**
* {@inheritdoc}
*/
public function getProvider() {
return $this->pluginDefinition['provider'];
}
/**
* {@inheritdoc}
*/
public function getGroup() {
return $this->pluginDefinition['group'];
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace Drupal\breakpoint;
/**
* Interface for Breakpoint plugins.
*/
interface BreakpointInterface {
/**
* Returns the translated label.
*
* @return string
* The translated label.
*/
public function getLabel();
/**
* Returns the weight.
*
* @return int
* The weight.
*/
public function getWeight();
/**
* Returns the media query.
*
* @return string
* The media query.
*/
public function getMediaQuery();
/**
* Returns the multipliers.
*
* @return array
* The multipliers.
*/
public function getMultipliers();
/**
* Returns the provider.
*
* @return string
* The provider.
*/
public function getProvider();
/**
* Returns the breakpoint group.
*
* @return string
* The breakpoint group.
*/
public function getGroup();
}

View File

@@ -0,0 +1,267 @@
<?php
namespace Drupal\breakpoint;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleExtensionList;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
use Drupal\Core\Plugin\Discovery\YamlDiscovery;
use Drupal\Core\Plugin\Factory\ContainerFactory;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
/**
* Defines a breakpoint plugin manager to deal with breakpoints.
*
* Extension can define breakpoints in an EXTENSION_NAME.breakpoints.yml file
* contained in the extension's base directory. Each breakpoint has the
* following structure:
* @code
* MACHINE_NAME:
* label: STRING
* mediaQuery: STRING
* weight: INTEGER
* multipliers:
* - STRING
* @endcode
* For example:
* @code
* olivero.lg:
* label: Large
* mediaQuery: 'all and (min-width: 1000px)'
* weight: 2
* multipliers:
* - 1x
* @endcode
* Optionally a breakpoint can provide a group key. By default an extensions
* breakpoints will be placed in a group labelled with the extension name.
*
* @see \Drupal\breakpoint\Breakpoint
* @see \Drupal\breakpoint\BreakpointInterface
* @see plugin_api
*/
class BreakpointManager extends DefaultPluginManager implements BreakpointManagerInterface {
use StringTranslationTrait;
/**
* {@inheritdoc}
*/
protected $defaults = [
// Human readable label for breakpoint.
'label' => '',
// The media query for the breakpoint.
'mediaQuery' => '',
// Weight used for ordering breakpoints.
'weight' => 0,
// Breakpoint multipliers.
'multipliers' => [],
// The breakpoint group.
'group' => '',
// Default class for breakpoint implementations.
'class' => 'Drupal\breakpoint\Breakpoint',
// The plugin id. Set by the plugin system based on the top-level YAML key.
'id' => '',
];
/**
* The theme handler.
*
* @var \Drupal\Core\Extension\ThemeHandlerInterface
*/
protected $themeHandler;
/**
* Static cache of breakpoints keyed by group.
*
* @var array
*/
protected $breakpointsByGroup;
/**
* The plugin instances.
*
* @var array
*/
protected $instances = [];
/**
* Constructs a new BreakpointManager instance.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
* The theme handler.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
* The cache backend.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
* @param \Drupal\Core\Extension\ModuleExtensionList|null $module_extension_list
* The module extension list.
*/
public function __construct(ModuleHandlerInterface $module_handler, ThemeHandlerInterface $theme_handler, CacheBackendInterface $cache_backend, TranslationInterface $string_translation, ?ModuleExtensionList $module_extension_list = NULL) {
$this->factory = new ContainerFactory($this);
$this->moduleHandler = $module_handler;
$this->themeHandler = $theme_handler;
if ($module_extension_list === NULL) {
@trigger_error('Calling ' . __METHOD__ . '() without the $module_extension_list argument is deprecated in drupal:10.3.0 and will be required in drupal:12.0.0. See https://www.drupal.org/node/3310017', E_USER_DEPRECATED);
$module_extension_list = \Drupal::service('extension.list.module');
}
$this->moduleExtensionList = $module_extension_list;
$this->setStringTranslation($string_translation);
$this->alterInfo('breakpoints');
$this->setCacheBackend($cache_backend, 'breakpoints', ['breakpoints']);
}
/**
* {@inheritdoc}
*/
protected function getDiscovery() {
if (!isset($this->discovery)) {
$this->discovery = new YamlDiscovery('breakpoints', $this->moduleHandler->getModuleDirectories() + $this->themeHandler->getThemeDirectories());
$this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
}
return $this->discovery;
}
/**
* {@inheritdoc}
*/
public function processDefinition(&$definition, $plugin_id) {
parent::processDefinition($definition, $plugin_id);
// Allow custom groups and therefore more than one group per extension.
if (empty($definition['group'])) {
$definition['group'] = $definition['provider'];
}
// Ensure a 1x multiplier exists.
if (!in_array('1x', $definition['multipliers'])) {
$definition['multipliers'][] = '1x';
}
// Ensure that multipliers are sorted numerically so 1x, 1.5x and 2x
// come out in that order instead of 1.5x, 1x, 2x.
sort($definition['multipliers'], SORT_NUMERIC);
}
/**
* {@inheritdoc}
*/
protected function providerExists($provider) {
return $this->moduleHandler->moduleExists($provider) || $this->themeHandler->themeExists($provider);
}
/**
* {@inheritdoc}
*/
public function getBreakpointsByGroup($group) {
if (!isset($this->breakpointsByGroup[$group])) {
if ($cache = $this->cacheBackend->get($this->cacheKey . ':' . $group)) {
$this->breakpointsByGroup[$group] = $cache->data;
}
else {
$breakpoints = [];
foreach ($this->getDefinitions() as $plugin_id => $plugin_definition) {
if ($plugin_definition['group'] == $group) {
$breakpoints[$plugin_id] = $plugin_definition;
}
}
uasort($breakpoints, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);
$this->cacheBackend->set($this->cacheKey . ':' . $group, $breakpoints, Cache::PERMANENT, ['breakpoints']);
$this->breakpointsByGroup[$group] = $breakpoints;
}
}
$instances = [];
foreach ($this->breakpointsByGroup[$group] as $plugin_id => $definition) {
if (!isset($this->instances[$plugin_id])) {
$this->instances[$plugin_id] = $this->createInstance($plugin_id);
}
$instances[$plugin_id] = $this->instances[$plugin_id];
}
return $instances;
}
/**
* {@inheritdoc}
*/
public function getGroups() {
// Use a double colon so as to not clash with the cache for each group.
if ($cache = $this->cacheBackend->get($this->cacheKey . '::groups')) {
$groups = $cache->data;
}
else {
$groups = [];
foreach ($this->getDefinitions() as $plugin_definition) {
if (!isset($groups[$plugin_definition['group']])) {
$groups[$plugin_definition['group']] = $plugin_definition['group'];
}
}
$this->cacheBackend->set($this->cacheKey . '::groups', $groups, Cache::PERMANENT, ['breakpoints']);
}
// Get the labels. This is not cacheable due to translation.
$group_labels = [];
foreach ($groups as $group) {
$group_labels[$group] = $this->getGroupLabel($group);
}
asort($group_labels);
return $group_labels;
}
/**
* {@inheritdoc}
*/
public function getGroupProviders($group) {
$providers = [];
$breakpoints = $this->getBreakpointsByGroup($group);
foreach ($breakpoints as $breakpoint) {
$provider = $breakpoint->getProvider();
$extension = FALSE;
if ($this->moduleHandler->moduleExists($provider)) {
$extension = $this->moduleHandler->getModule($provider);
}
elseif ($this->themeHandler->themeExists($provider)) {
$extension = $this->themeHandler->getTheme($provider);
}
if ($extension) {
$providers[$extension->getName()] = $extension->getType();
}
}
return $providers;
}
/**
* {@inheritdoc}
*/
public function clearCachedDefinitions() {
parent::clearCachedDefinitions();
$this->breakpointsByGroup = NULL;
$this->instances = [];
}
/**
* Gets the label for a breakpoint group.
*
* @param string $group
* The breakpoint group.
*
* @return string
* The label.
*/
protected function getGroupLabel($group) {
// Extension names are not translatable.
if ($this->moduleHandler->moduleExists($group)) {
$label = $this->moduleExtensionList->getName($group);
}
elseif ($this->themeHandler->themeExists($group)) {
$label = $this->themeHandler->getName($group);
}
else {
// Custom group label that should be translatable.
$label = $this->t($group, [], ['context' => 'breakpoint']);
}
return $label;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Drupal\breakpoint;
/**
* Defines an interface for breakpoint managers.
*/
interface BreakpointManagerInterface {
/**
* Gets breakpoints for the specified group.
*
* @param string $group
* The breakpoint group to retrieve.
*
* @return \Drupal\breakpoint\BreakpointInterface[]
* Array of breakpoint plugins keyed by machine name.
*/
public function getBreakpointsByGroup($group);
/**
* Gets all the existing breakpoint groups.
*
* @return array
* Array of breakpoint group labels. Keyed by group name.
*/
public function getGroups();
/**
* Gets all the providers for the specified breakpoint group.
*
* @param string $group
* The breakpoint group to retrieve.
*
* @return array
* An array keyed by provider name with values of provider type (module or
* theme).
*/
public function getGroupProviders($group);
}

View File

@@ -0,0 +1,21 @@
breakpoint_module_test.mobile:
label: mobile
mediaQuery: '(min-width: 0px)'
weight: 0
# Don't include multipliers. A 1x multiplier this will be enforced by default.
breakpoint_module_test.standard:
label: standard
mediaQuery: '(min-width: 560px)'
weight: 1
# Don't include a 1x multiplier this will be enforced by default.
multipliers:
- 2x
# Test providing a breakpoint for group matching the group provided by
# breakpoint_test_theme.
breakpoint_module_test.breakpoint_theme_test.group2.tv:
label: tv
mediaQuery: '(min-width: 6000px)'
weight: 2
multipliers:
- 1x
group: breakpoint_theme_test.group2

View File

@@ -0,0 +1,10 @@
name: 'Breakpoint test module'
type: module
description: 'Test module for breakpoint.'
package: Testing
# version: VERSION
# Information added by Drupal.org packaging script on 2024-07-04
version: '10.3.1'
project: 'drupal'
datestamp: 1720094222

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\breakpoint\Functional;
use Drupal\Tests\system\Functional\Module\GenericModuleTestBase;
/**
* Generic module test for breakpoint.
*
* @group breakpoint
*/
class GenericTest extends GenericModuleTestBase {}

View File

@@ -0,0 +1,210 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\breakpoint\Kernel;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests discovery of breakpoints provided by themes and modules.
*
* @group breakpoint
*/
class BreakpointDiscoveryTest extends KernelTestBase {
/**
* Modules to install.
*
* @var array
*/
protected static $modules = [
'system',
'breakpoint',
'breakpoint_module_test',
];
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
\Drupal::service('theme_installer')->install(['breakpoint_theme_test']);
}
/**
* Tests the breakpoint group created for a theme.
*/
public function testThemeBreakpoints(): void {
// Verify the breakpoint group for breakpoint_theme_test was created.
$expected_breakpoints = [
'breakpoint_theme_test.mobile' => [
'label' => 'mobile',
'mediaQuery' => '(min-width: 0px)',
'weight' => 0,
'multipliers' => [
'1x',
],
'provider' => 'breakpoint_theme_test',
'id' => 'breakpoint_theme_test.mobile',
'group' => 'breakpoint_theme_test',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
'breakpoint_theme_test.narrow' => [
'label' => 'narrow',
'mediaQuery' => '(min-width: 560px)',
'weight' => 1,
'multipliers' => [
'1x',
],
'provider' => 'breakpoint_theme_test',
'id' => 'breakpoint_theme_test.narrow',
'group' => 'breakpoint_theme_test',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
'breakpoint_theme_test.wide' => [
'label' => 'wide',
'mediaQuery' => '(min-width: 851px)',
'weight' => 2,
'multipliers' => [
'1x',
],
'provider' => 'breakpoint_theme_test',
'id' => 'breakpoint_theme_test.wide',
'group' => 'breakpoint_theme_test',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
'breakpoint_theme_test.tv' => [
'label' => 'tv',
'mediaQuery' => 'only screen and (min-width: 1220px)',
'weight' => 3,
'multipliers' => [
'1x',
],
'provider' => 'breakpoint_theme_test',
'id' => 'breakpoint_theme_test.tv',
'group' => 'breakpoint_theme_test',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
];
$breakpoints = \Drupal::service('breakpoint.manager')->getBreakpointsByGroup('breakpoint_theme_test');
foreach ($expected_breakpoints as $id => $expected_breakpoint) {
$this->assertEquals($expected_breakpoint, $breakpoints[$id]->getPluginDefinition());
}
// Test that the order is as expected.
$this->assertSame(array_keys($expected_breakpoints), array_keys($breakpoints));
}
/**
* Tests the custom breakpoint group provided by a theme and a module.
*/
public function testCustomBreakpointGroups(): void {
// Verify the breakpoint group for breakpoint_theme_test.group2 was created.
$expected_breakpoints = [
'breakpoint_theme_test.group2.narrow' => [
'label' => 'narrow',
'mediaQuery' => '(min-width: 560px)',
'weight' => 0,
'multipliers' => [
'1x',
'2x',
],
'provider' => 'breakpoint_theme_test',
'id' => 'breakpoint_theme_test.group2.narrow',
'group' => 'breakpoint_theme_test.group2',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
'breakpoint_theme_test.group2.wide' => [
'label' => 'wide',
'mediaQuery' => '(min-width: 851px)',
'weight' => 1,
'multipliers' => [
'1x',
'2x',
],
'provider' => 'breakpoint_theme_test',
'id' => 'breakpoint_theme_test.group2.wide',
'group' => 'breakpoint_theme_test.group2',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
'breakpoint_module_test.breakpoint_theme_test.group2.tv' => [
'label' => 'tv',
'mediaQuery' => '(min-width: 6000px)',
'weight' => 2,
'multipliers' => [
'1x',
],
'provider' => 'breakpoint_module_test',
'id' => 'breakpoint_module_test.breakpoint_theme_test.group2.tv',
'group' => 'breakpoint_theme_test.group2',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
];
$breakpoints = \Drupal::service('breakpoint.manager')->getBreakpointsByGroup('breakpoint_theme_test.group2');
foreach ($expected_breakpoints as $id => $expected_breakpoint) {
$this->assertEquals($expected_breakpoint, $breakpoints[$id]->getPluginDefinition());
}
}
/**
* Tests the breakpoint group created for a module.
*/
public function testModuleBreakpoints(): void {
$expected_breakpoints = [
'breakpoint_module_test.mobile' => [
'label' => 'mobile',
'mediaQuery' => '(min-width: 0px)',
'weight' => 0,
'multipliers' => [
'1x',
],
'provider' => 'breakpoint_module_test',
'id' => 'breakpoint_module_test.mobile',
'group' => 'breakpoint_module_test',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
'breakpoint_module_test.standard' => [
'label' => 'standard',
'mediaQuery' => '(min-width: 560px)',
'weight' => 1,
'multipliers' => [
'1x',
'2x',
],
'provider' => 'breakpoint_module_test',
'id' => 'breakpoint_module_test.standard',
'group' => 'breakpoint_module_test',
'class' => 'Drupal\\breakpoint\\Breakpoint',
],
];
$breakpoints = \Drupal::service('breakpoint.manager')->getBreakpointsByGroup('breakpoint_module_test');
$this->assertEquals(array_keys($expected_breakpoints), array_keys($breakpoints));
}
/**
* Tests the collection of breakpoint groups.
*/
public function testBreakpointGroups(): void {
$expected = [
'olivero' => 'Olivero',
'breakpoint_module_test' => 'Breakpoint test module',
'breakpoint_theme_test' => 'Breakpoint test theme',
'breakpoint_theme_test.group2' => 'breakpoint_theme_test.group2',
];
$breakpoint_groups = \Drupal::service('breakpoint.manager')->getGroups();
// Ensure the order is as expected. Should be sorted by label.
$this->assertEquals($expected, $breakpoint_groups);
$expected = [
'breakpoint_theme_test' => 'theme',
'breakpoint_module_test' => 'module',
];
$breakpoint_group_providers = \Drupal::service('breakpoint.manager')->getGroupProviders('breakpoint_theme_test.group2');
$this->assertEquals($expected, $breakpoint_group_providers);
}
}

View File

@@ -0,0 +1,119 @@
<?php
declare(strict_types=1);
namespace Drupal\Tests\breakpoint\Unit;
use Drupal\breakpoint\Breakpoint;
use Drupal\Tests\UnitTestCase;
use Drupal\Core\StringTranslation\TranslatableMarkup;
/**
* @coversDefaultClass \Drupal\breakpoint\Breakpoint
* @group Breakpoint
*/
class BreakpointTest extends UnitTestCase {
/**
* The used plugin ID.
*
* @var string
*/
protected $pluginId = 'breakpoint';
/**
* The used plugin definition.
*
* @var array
*/
protected $pluginDefinition = [
'id' => 'breakpoint',
];
/**
* The breakpoint under test.
*
* @var \Drupal\breakpoint\Breakpoint
*/
protected $breakpoint;
/**
* The mocked translator.
*
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit\Framework\MockObject\MockObject
*/
protected $stringTranslation;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->stringTranslation = $this->createMock('Drupal\Core\StringTranslation\TranslationInterface');
}
/**
* Sets up the breakpoint defaults.
*/
protected function setupBreakpoint() {
$this->breakpoint = new Breakpoint([], $this->pluginId, $this->pluginDefinition);
$this->breakpoint->setStringTranslation($this->stringTranslation);
}
/**
* @covers ::getLabel
*/
public function testGetLabel(): void {
$this->pluginDefinition['label'] = 'Test label';
$this->setupBreakpoint();
$this->assertEquals(new TranslatableMarkup('Test label', [], ['context' => 'breakpoint'], $this->stringTranslation), $this->breakpoint->getLabel());
}
/**
* @covers ::getWeight
*/
public function testGetWeight(): void {
$this->pluginDefinition['weight'] = '4';
$this->setupBreakpoint();
// Assert that the type returned in an integer.
$this->assertSame(4, $this->breakpoint->getWeight());
}
/**
* @covers ::getMediaQuery
*/
public function testGetMediaQuery(): void {
$this->pluginDefinition['mediaQuery'] = 'only screen and (min-width: 1220px)';
$this->setupBreakpoint();
$this->assertEquals('only screen and (min-width: 1220px)', $this->breakpoint->getMediaQuery());
}
/**
* @covers ::getMultipliers
*/
public function testGetMultipliers(): void {
$this->pluginDefinition['multipliers'] = ['1x', '2x'];
$this->setupBreakpoint();
$this->assertSame(['1x', '2x'], $this->breakpoint->getMultipliers());
}
/**
* @covers ::getProvider
*/
public function testGetProvider(): void {
$this->pluginDefinition['provider'] = 'Breakpoint';
$this->setupBreakpoint();
$this->assertEquals('Breakpoint', $this->breakpoint->getProvider());
}
/**
* @covers ::getGroup
*/
public function testGetGroup(): void {
$this->pluginDefinition['group'] = 'Breakpoint';
$this->setupBreakpoint();
$this->assertEquals('Breakpoint', $this->breakpoint->getGroup());
}
}

View File

@@ -0,0 +1,41 @@
breakpoint_theme_test.mobile:
label: mobile
mediaQuery: '(min-width: 0px)'
weight: 0
multipliers:
- 1x
breakpoint_theme_test.narrow:
label: narrow
mediaQuery: '(min-width: 560px)'
weight: 1
multipliers:
- 1x
# Out of order breakpoint to test sorting.
breakpoint_theme_test.tv:
label: tv
mediaQuery: 'only screen and (min-width: 1220px)'
weight: 3
multipliers:
- 1x
breakpoint_theme_test.wide:
label: wide
mediaQuery: '(min-width: 851px)'
weight: 2
multipliers:
- 1x
breakpoint_theme_test.group2.narrow:
label: narrow
mediaQuery: '(min-width: 560px)'
weight: 0
multipliers:
- 1x
- 2x
group: breakpoint_theme_test.group2
breakpoint_theme_test.group2.wide:
label: wide
mediaQuery: '(min-width: 851px)'
weight: 1
multipliers:
- 1x
- 2x
group: breakpoint_theme_test.group2

View File

@@ -0,0 +1,10 @@
name: 'Breakpoint test theme'
type: theme
description: 'Test theme for breakpoint.'
# version: VERSION
base theme: olivero
# Information added by Drupal.org packaging script on 2024-07-04
version: '10.3.1'
project: 'drupal'
datestamp: 1720094222