1<?php 2 3namespace Drupal\Tests\Core\Asset; 4 5use Drupal\Core\Asset\LibraryDependencyResolver; 6use Drupal\Tests\UnitTestCase; 7 8/** 9 * @coversDefaultClass \Drupal\Core\Asset\LibraryDependencyResolver 10 * @group Asset 11 */ 12class LibraryDependencyResolverTest extends UnitTestCase { 13 14 /** 15 * The tested library dependency resolver. 16 * 17 * @var \Drupal\Core\Asset\LibraryDependencyResolver 18 */ 19 protected $libraryDependencyResolver; 20 21 /** 22 * The mocked library discovery service. 23 * 24 * @var \Drupal\Core\Asset\LibraryDiscoveryInterface|\PHPUnit\Framework\MockObject\MockObject 25 */ 26 protected $libraryDiscovery; 27 28 /** 29 * The mocked module handler. 30 * 31 * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit\Framework\MockObject\MockObject 32 */ 33 protected $moduleHandler; 34 35 /** 36 * Test library data. 37 * 38 * @var array 39 */ 40 protected $libraryData = [ 41 'no_deps_a' => ['js' => [], 'css' => []], 42 'no_deps_b' => ['js' => [], 'css' => []], 43 'no_deps_c' => ['js' => [], 'css' => []], 44 'deps_a' => ['js' => [], 'css' => [], 'dependencies' => ['test/no_deps_a']], 45 'deps_b' => ['js' => [], 'css' => [], 'dependencies' => ['test/no_deps_a', 'test/no_deps_b']], 46 'deps_c' => ['js' => [], 'css' => [], 'dependencies' => ['test/no_deps_b', 'test/no_deps_a']], 47 'nested_deps_a' => ['js' => [], 'css' => [], 'dependencies' => ['test/deps_a']], 48 'nested_deps_b' => ['js' => [], 'css' => [], 'dependencies' => ['test/nested_deps_a']], 49 'nested_deps_c' => ['js' => [], 'css' => [], 'dependencies' => ['test/nested_deps_b']], 50 ]; 51 52 /** 53 * {@inheritdoc} 54 */ 55 protected function setUp() { 56 $this->libraryDiscovery = $this->getMockBuilder('Drupal\Core\Asset\LibraryDiscovery') 57 ->disableOriginalConstructor() 58 ->setMethods(['getLibrariesByExtension']) 59 ->getMock(); 60 $this->libraryDiscovery->expects($this->any()) 61 ->method('getLibrariesByExtension') 62 ->with('test') 63 ->will($this->returnValue($this->libraryData)); 64 $this->libraryDependencyResolver = new LibraryDependencyResolver($this->libraryDiscovery); 65 } 66 67 /** 68 * Provides test data for ::testGetLibrariesWithDependencies(). 69 */ 70 public function providerTestGetLibrariesWithDependencies() { 71 return [ 72 // Empty list of libraries. 73 [[], []], 74 // Without dependencies. 75 [['test/no_deps_a'], ['test/no_deps_a']], 76 [['test/no_deps_a', 'test/no_deps_b'], ['test/no_deps_a', 'test/no_deps_b']], 77 [['test/no_deps_b', 'test/no_deps_a'], ['test/no_deps_b', 'test/no_deps_a']], 78 // Single-level (direct) dependencies. 79 [['test/deps_a'], ['test/no_deps_a', 'test/deps_a']], 80 [['test/deps_b'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_b']], 81 [['test/deps_c'], ['test/no_deps_b', 'test/no_deps_a', 'test/deps_c']], 82 [['test/deps_a', 'test/deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/no_deps_b', 'test/deps_b']], 83 [['test/deps_a', 'test/deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/no_deps_b', 'test/deps_c']], 84 [['test/deps_a', 'test/deps_b', 'test/deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/no_deps_b', 'test/deps_b', 'test/deps_c']], 85 [['test/deps_b', 'test/deps_a'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_b', 'test/deps_a']], 86 [['test/deps_b', 'test/deps_c'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_b', 'test/deps_c']], 87 [['test/deps_c', 'test/deps_b'], ['test/no_deps_b', 'test/no_deps_a', 'test/deps_c', 'test/deps_b']], 88 // Multi-level (indirect) dependencies. 89 [['test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a']], 90 [['test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']], 91 [['test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 92 [['test/nested_deps_a', 'test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']], 93 [['test/nested_deps_b', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']], 94 [['test/nested_deps_a', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 95 [['test/nested_deps_b', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 96 [['test/nested_deps_c', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 97 [['test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 98 [['test/nested_deps_a', 'test/nested_deps_c', 'test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 99 [['test/nested_deps_b', 'test/nested_deps_a', 'test/nested_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 100 [['test/nested_deps_b', 'test/nested_deps_c', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 101 [['test/nested_deps_c', 'test/nested_deps_a', 'test/nested_deps_b'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 102 [['test/nested_deps_c', 'test/nested_deps_b', 'test/nested_deps_a'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c']], 103 // Complex dependencies, combining the above, with many intersections. 104 [['test/deps_c', 'test/nested_deps_b'], ['test/no_deps_b', 'test/no_deps_a', 'test/deps_c', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']], 105 [['test/no_deps_a', 'test/deps_c', 'test/nested_deps_b'], ['test/no_deps_a', 'test/no_deps_b', 'test/deps_c', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b']], 106 [['test/nested_deps_b', 'test/deps_c', 'test/no_deps_c'], ['test/no_deps_a', 'test/deps_a', 'test/nested_deps_a', 'test/nested_deps_b', 'test/no_deps_b', 'test/deps_c', 'test/no_deps_c']], 107 ]; 108 } 109 110 /** 111 * @covers ::getLibrariesWithDependencies 112 * 113 * @dataProvider providerTestGetLibrariesWithDependencies 114 */ 115 public function testGetLibrariesWithDependencies(array $libraries, array $expected) { 116 $this->assertEquals($expected, $this->libraryDependencyResolver->getLibrariesWithDependencies($libraries)); 117 } 118 119 /** 120 * Provides test data for ::testGetMinimalRepresentativeSubset(). 121 */ 122 public function providerTestGetMinimalRepresentativeSubset() { 123 return [ 124 // Empty list of libraries. 125 [[], []], 126 // Without dependencies. 127 [['test/no_deps_a'], ['test/no_deps_a']], 128 [['test/no_deps_a', 'test/no_deps_b'], ['test/no_deps_a', 'test/no_deps_b']], 129 [['test/no_deps_b', 'test/no_deps_a'], ['test/no_deps_b', 'test/no_deps_a']], 130 // Single-level (direct) dependencies. 131 [['test/deps_a'], ['test/deps_a']], 132 [['test/deps_b'], ['test/deps_b']], 133 [['test/deps_c'], ['test/deps_c']], 134 [['test/deps_a', 'test/deps_b'], ['test/deps_a', 'test/deps_b']], 135 [['test/deps_a', 'test/deps_c'], ['test/deps_a', 'test/deps_c']], 136 [['test/deps_a', 'test/deps_b', 'test/deps_c'], ['test/deps_a', 'test/deps_b', 'test/deps_c']], 137 [['test/deps_b', 'test/deps_a'], ['test/deps_b', 'test/deps_a']], 138 [['test/deps_b', 'test/deps_c'], ['test/deps_b', 'test/deps_c']], 139 [['test/deps_c', 'test/deps_b'], ['test/deps_c', 'test/deps_b']], 140 // Multi-level (indirect) dependencies. 141 [['test/nested_deps_a'], ['test/nested_deps_a']], 142 [['test/nested_deps_b'], ['test/nested_deps_b']], 143 [['test/nested_deps_c'], ['test/nested_deps_c']], 144 [['test/nested_deps_a', 'test/nested_deps_b'], ['test/nested_deps_b']], 145 [['test/nested_deps_b', 'test/nested_deps_a'], ['test/nested_deps_b']], 146 [['test/nested_deps_a', 'test/nested_deps_c'], ['test/nested_deps_c']], 147 [['test/nested_deps_b', 'test/nested_deps_c'], ['test/nested_deps_c']], 148 [['test/nested_deps_c', 'test/nested_deps_a'], ['test/nested_deps_c']], 149 [['test/nested_deps_a', 'test/nested_deps_b', 'test/nested_deps_c'], ['test/nested_deps_c']], 150 [['test/nested_deps_a', 'test/nested_deps_c', 'test/nested_deps_b'], ['test/nested_deps_c']], 151 [['test/nested_deps_b', 'test/nested_deps_a', 'test/nested_deps_c'], ['test/nested_deps_c']], 152 [['test/nested_deps_b', 'test/nested_deps_c', 'test/nested_deps_a'], ['test/nested_deps_c']], 153 [['test/nested_deps_c', 'test/nested_deps_a', 'test/nested_deps_b'], ['test/nested_deps_c']], 154 [['test/nested_deps_c', 'test/nested_deps_b', 'test/nested_deps_a'], ['test/nested_deps_c']], 155 // Complex dependencies, combining the above, with many intersections. 156 [['test/deps_c', 'test/nested_deps_b'], ['test/deps_c', 'test/nested_deps_b']], 157 [['test/no_deps_a', 'test/deps_c', 'test/nested_deps_b'], ['test/deps_c', 'test/nested_deps_b']], 158 [['test/nested_deps_b', 'test/deps_c', 'test/no_deps_c'], ['test/nested_deps_b', 'test/deps_c', 'test/no_deps_c']], 159 ]; 160 } 161 162 /** 163 * @covers ::getMinimalRepresentativeSubset 164 * 165 * @dataProvider providerTestGetMinimalRepresentativeSubset 166 */ 167 public function testGetMinimalRepresentativeSubset(array $libraries, array $expected) { 168 $this->assertEquals($expected, $this->libraryDependencyResolver->getMinimalRepresentativeSubset($libraries)); 169 } 170 171 /** 172 * @covers ::getMinimalRepresentativeSubset 173 */ 174 public function testGetMinimalRepresentativeSubsetInvalidInput() { 175 $this->expectException(\AssertionError::class); 176 $this->expectExceptionMessage('$libraries can\'t contain duplicate items.'); 177 $this->libraryDependencyResolver->getMinimalRepresentativeSubset(['test/no_deps_a', 'test/no_deps_a']); 178 } 179 180} 181