wp-optimize
/
vendor
/
kriswallsmith
/
assetic
/
tests
/
Assetic
/
Test
/
Asset
/
AssetCollectionTest.php
AssetCollectionTest.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.5, at vendor/kriswallsmith/assetic/tests/Assetic/Test/Asset/AssetCollectionTest.php
| 1 | <?php |
| 2 | |
| 3 | /* |
| 4 | * This file is part of the Assetic package, an OpenSky project. |
| 5 | * |
| 6 | * (c) 2010-2014 OpenSky Project Inc |
| 7 | * |
| 8 | * For the full copyright and license information, please view the LICENSE |
| 9 | * file that was distributed with this source code. |
| 10 | */ |
| 11 | |
| 12 | namespace Assetic\Test\Asset; |
| 13 | |
| 14 | use Assetic\Asset\StringAsset; |
| 15 | use Assetic\Asset\FileAsset; |
| 16 | use Assetic\Asset\AssetCollection; |
| 17 | use Assetic\Filter\CallablesFilter; |
| 18 | |
| 19 | class AssetCollectionTest extends \PHPUnit_Framework_TestCase |
| 20 | { |
| 21 | public function testInterface() |
| 22 | { |
| 23 | $coll = new AssetCollection(); |
| 24 | $this->assertInstanceOf('Assetic\\Asset\\AssetInterface', $coll, 'AssetCollection implements AssetInterface'); |
| 25 | } |
| 26 | |
| 27 | public function testLoadFilter() |
| 28 | { |
| 29 | $filter = $this->getMockBuilder('Assetic\\Filter\\FilterInterface')->getMock(); |
| 30 | $filter->expects($this->once())->method('filterLoad'); |
| 31 | |
| 32 | $coll = new AssetCollection(array(new StringAsset('')), array($filter)); |
| 33 | $coll->load(); |
| 34 | } |
| 35 | |
| 36 | public function testDumpFilter() |
| 37 | { |
| 38 | $filter = $this->getMockBuilder('Assetic\\Filter\\FilterInterface')->getMock(); |
| 39 | $filter->expects($this->once())->method('filterDump'); |
| 40 | |
| 41 | $coll = new AssetCollection(array(new StringAsset('')), array($filter)); |
| 42 | $coll->dump(); |
| 43 | } |
| 44 | |
| 45 | public function testNestedCollectionLoad() |
| 46 | { |
| 47 | $content = 'foobar'; |
| 48 | |
| 49 | $count = 0; |
| 50 | $matches = array(); |
| 51 | $filter = new CallablesFilter(function ($asset) use ($content, &$matches, &$count) { |
| 52 | ++$count; |
| 53 | if ($content == $asset->getContent()) { |
| 54 | $matches[] = $asset; |
| 55 | } |
| 56 | }); |
| 57 | |
| 58 | $innerColl = new AssetCollection(array(new StringAsset($content))); |
| 59 | $outerColl = new AssetCollection(array($innerColl), array($filter)); |
| 60 | $outerColl->load(); |
| 61 | |
| 62 | $this->assertEquals(1, count($matches), '->load() applies filters to leaves'); |
| 63 | $this->assertEquals(1, $count, '->load() applies filters to leaves only'); |
| 64 | } |
| 65 | |
| 66 | public function testMixedIteration() |
| 67 | { |
| 68 | $asset = new StringAsset('asset'); |
| 69 | $nestedAsset = new StringAsset('nested'); |
| 70 | $innerColl = new AssetCollection(array($nestedAsset)); |
| 71 | |
| 72 | $contents = array(); |
| 73 | $filter = new CallablesFilter(function ($asset) use (&$contents) { |
| 74 | $contents[] = $asset->getContent(); |
| 75 | }); |
| 76 | |
| 77 | $coll = new AssetCollection(array($asset, $innerColl), array($filter)); |
| 78 | $coll->load(); |
| 79 | |
| 80 | $this->assertEquals(array('asset', 'nested'), $contents, '->load() iterates over multiple levels'); |
| 81 | } |
| 82 | |
| 83 | public function testLoadDedupBySourceUrl() |
| 84 | { |
| 85 | $asset1 = new StringAsset('asset', array(), '/some/dir', 'foo.bar'); |
| 86 | $asset2 = new StringAsset('asset', array(), '/some/dir', 'foo.bar'); |
| 87 | |
| 88 | $coll = new AssetCollection(array($asset1, $asset2)); |
| 89 | $coll->load(); |
| 90 | |
| 91 | $this->assertEquals('asset', $coll->getContent(), '->load() detects duplicate assets based on source URL'); |
| 92 | } |
| 93 | |
| 94 | public function testLoadDedupByStrictEquality() |
| 95 | { |
| 96 | $asset = new StringAsset('foo'); |
| 97 | |
| 98 | $coll = new AssetCollection(array($asset, $asset)); |
| 99 | $coll->load(); |
| 100 | |
| 101 | $this->assertEquals('foo', $coll->getContent(), '->load() detects duplicate assets based on strict equality'); |
| 102 | } |
| 103 | |
| 104 | public function testDumpDedupBySourceUrl() |
| 105 | { |
| 106 | $asset1 = new StringAsset('asset', array(), '/some/dir', 'foo.bar'); |
| 107 | $asset2 = new StringAsset('asset', array(), '/some/dir', 'foo.bar'); |
| 108 | |
| 109 | $coll = new AssetCollection(array($asset1, $asset2)); |
| 110 | $coll->load(); |
| 111 | |
| 112 | $this->assertEquals('asset', $coll->dump(), '->dump() detects duplicate assets based on source URL'); |
| 113 | } |
| 114 | |
| 115 | public function testDumpDedupByStrictEquality() |
| 116 | { |
| 117 | $asset = new StringAsset('foo'); |
| 118 | |
| 119 | $coll = new AssetCollection(array($asset, $asset)); |
| 120 | $coll->load(); |
| 121 | |
| 122 | $this->assertEquals('foo', $coll->dump(), '->dump() detects duplicate assets based on strict equality'); |
| 123 | } |
| 124 | |
| 125 | public function testIterationFilters() |
| 126 | { |
| 127 | $count = 0; |
| 128 | $filter = new CallablesFilter(function () use (&$count) { ++$count; }); |
| 129 | |
| 130 | $coll = new AssetCollection(); |
| 131 | $coll->add(new StringAsset('')); |
| 132 | $coll->ensureFilter($filter); |
| 133 | |
| 134 | foreach ($coll as $asset) { |
| 135 | $asset->dump(); |
| 136 | } |
| 137 | |
| 138 | $this->assertEquals(1, $count, 'collection filters are called when child assets are iterated over'); |
| 139 | } |
| 140 | |
| 141 | public function testSetContent() |
| 142 | { |
| 143 | $coll = new AssetCollection(); |
| 144 | $coll->setContent('asdf'); |
| 145 | |
| 146 | $this->assertEquals('asdf', $coll->getContent(), '->setContent() sets the content'); |
| 147 | } |
| 148 | |
| 149 | /** |
| 150 | * @dataProvider getTimestampsAndExpected |
| 151 | */ |
| 152 | public function testGetLastModified($timestamps, $expected) |
| 153 | { |
| 154 | $assets = array(); |
| 155 | |
| 156 | for ($i = 0; $i < count($timestamps); $i++) { |
| 157 | $asset = $this->getMockBuilder('Assetic\\Asset\\AssetInterface')->getMock(); |
| 158 | $asset->expects($this->once()) |
| 159 | ->method('getLastModified') |
| 160 | ->will($this->returnValue($timestamps[$i])); |
| 161 | $assets[$i] = $asset; |
| 162 | } |
| 163 | |
| 164 | $coll = new AssetCollection($assets); |
| 165 | |
| 166 | $this->assertEquals($expected, $coll->getLastModified(), '->getLastModifed() returns the highest last modified'); |
| 167 | } |
| 168 | |
| 169 | public function testGetLastModifiedWithValues() |
| 170 | { |
| 171 | $vars = array('locale'); |
| 172 | $asset = new FileAsset(__DIR__.'/../Fixture/messages.{locale}.js', array(), null, null, $vars); |
| 173 | |
| 174 | $coll = new AssetCollection(array($asset), array(), null, $vars); |
| 175 | $coll->setValues(array('locale' => 'en')); |
| 176 | try { |
| 177 | $coll->getLastModified(); |
| 178 | } catch (\InvalidArgumentException $e) { |
| 179 | $this->fail("->getLastModified() shouldn't fail for assets with vars"); |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | public function getTimestampsAndExpected() |
| 184 | { |
| 185 | return array( |
| 186 | array(array(1, 2, 3), 3), |
| 187 | array(array(5, 4, 3), 5), |
| 188 | array(array(3, 8, 5), 8), |
| 189 | array(array(3, 8, null), 8), |
| 190 | ); |
| 191 | } |
| 192 | |
| 193 | public function testRecursiveIteration() |
| 194 | { |
| 195 | $asset1 = $this->getMockBuilder('Assetic\\Asset\\AssetInterface')->getMock(); |
| 196 | $asset2 = $this->getMockBuilder('Assetic\\Asset\\AssetInterface')->getMock(); |
| 197 | $asset3 = $this->getMockBuilder('Assetic\\Asset\\AssetInterface')->getMock(); |
| 198 | $asset4 = $this->getMockBuilder('Assetic\\Asset\\AssetInterface')->getMock(); |
| 199 | |
| 200 | $coll3 = new AssetCollection(array($asset1, $asset2)); |
| 201 | $coll2 = new AssetCollection(array($asset3, $coll3)); |
| 202 | $coll1 = new AssetCollection(array($asset4, $coll2)); |
| 203 | |
| 204 | $i = 0; |
| 205 | foreach ($coll1 as $a) { |
| 206 | $i++; |
| 207 | } |
| 208 | |
| 209 | $this->assertEquals(4, $i, 'iteration with a recursive iterator is recursive'); |
| 210 | } |
| 211 | |
| 212 | public function testRecursiveDeduplication() |
| 213 | { |
| 214 | $asset = $this->getMockBuilder('Assetic\\Asset\\AssetInterface')->getMock(); |
| 215 | |
| 216 | $coll3 = new AssetCollection(array($asset, $asset)); |
| 217 | $coll2 = new AssetCollection(array($asset, $coll3)); |
| 218 | $coll1 = new AssetCollection(array($asset, $coll2)); |
| 219 | |
| 220 | $i = 0; |
| 221 | foreach ($coll1 as $a) { |
| 222 | $i++; |
| 223 | } |
| 224 | |
| 225 | $this->assertEquals(1, $i, 'deduplication is performed recursively'); |
| 226 | } |
| 227 | |
| 228 | public function testIteration() |
| 229 | { |
| 230 | $asset1 = new StringAsset('asset1', array(), '/some/dir', 'foo.css'); |
| 231 | $asset2 = new StringAsset('asset2', array(), '/some/dir', 'foo.css'); |
| 232 | $asset3 = new StringAsset('asset3', array(), '/some/dir', 'bar.css'); |
| 233 | |
| 234 | $coll = new AssetCollection(array($asset1, $asset2, $asset3)); |
| 235 | |
| 236 | $count = 0; |
| 237 | foreach ($coll as $a) { |
| 238 | ++$count; |
| 239 | } |
| 240 | |
| 241 | $this->assertEquals(2, $count, 'iterator filters duplicates based on url'); |
| 242 | } |
| 243 | |
| 244 | public function testBasenameCollision() |
| 245 | { |
| 246 | $asset1 = new StringAsset('asset1', array(), '/some/dir', 'foo/foo.css'); |
| 247 | $asset2 = new StringAsset('asset2', array(), '/some/dir', 'bar/foo.css'); |
| 248 | |
| 249 | $coll = new AssetCollection(array($asset1, $asset2)); |
| 250 | |
| 251 | $urls = array(); |
| 252 | foreach ($coll as $leaf) { |
| 253 | $urls[] = $leaf->getTargetPath(); |
| 254 | } |
| 255 | |
| 256 | $this->assertEquals(2, count(array_unique($urls)), 'iterator prevents basename collisions'); |
| 257 | } |
| 258 | |
| 259 | public function testTargetNameGeneration() |
| 260 | { |
| 261 | $path = '/testing/dir.ectory/path/file.ext'; |
| 262 | |
| 263 | $coll = new AssetCollection(array(new StringAsset('asset1'), new StringAsset('asset2'))); |
| 264 | $coll->setTargetPath($path); |
| 265 | |
| 266 | foreach ($coll as $asset) { |
| 267 | $this->assertEquals(dirname($path), dirname($asset->getTargetPath())); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | public function testEmptyMtime() |
| 272 | { |
| 273 | $coll = new AssetCollection(); |
| 274 | $this->assertNull($coll->getLastModified(), '->getLastModified() returns null on empty collection'); |
| 275 | } |
| 276 | |
| 277 | public function testLeafManipulation() |
| 278 | { |
| 279 | $coll = new AssetCollection(array(new StringAsset('asdf'))); |
| 280 | |
| 281 | foreach ($coll as $leaf) { |
| 282 | $leaf->setTargetPath('asdf'); |
| 283 | } |
| 284 | |
| 285 | foreach ($coll as $leaf) { |
| 286 | $this->assertEquals('asdf', $leaf->getTargetPath(), 'leaf changes persist between iterations'); |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | public function testRemoveLeaf() |
| 291 | { |
| 292 | $coll = new AssetCollection(array( |
| 293 | $leaf = new StringAsset('asdf'), |
| 294 | )); |
| 295 | |
| 296 | $this->assertTrue($coll->removeLeaf($leaf)); |
| 297 | } |
| 298 | |
| 299 | public function testRemoveRecursiveLeaf() |
| 300 | { |
| 301 | $coll = new AssetCollection(array( |
| 302 | new AssetCollection(array( |
| 303 | $leaf = new StringAsset('asdf'), |
| 304 | )), |
| 305 | )); |
| 306 | |
| 307 | $this->assertTrue($coll->removeLeaf($leaf)); |
| 308 | } |
| 309 | |
| 310 | public function testRemoveInvalidLeaf() |
| 311 | { |
| 312 | $this->setExpectedException('InvalidArgumentException'); |
| 313 | |
| 314 | $coll = new AssetCollection(); |
| 315 | $coll->removeLeaf(new StringAsset('asdf')); |
| 316 | } |
| 317 | |
| 318 | public function testReplaceLeaf() |
| 319 | { |
| 320 | $coll = new AssetCollection(array( |
| 321 | $leaf = new StringAsset('asdf'), |
| 322 | )); |
| 323 | |
| 324 | $this->assertTrue($coll->replaceLeaf($leaf, new StringAsset('foo'))); |
| 325 | } |
| 326 | |
| 327 | public function testReplaceRecursiveLeaf() |
| 328 | { |
| 329 | $coll = new AssetCollection(array( |
| 330 | new AssetCollection(array( |
| 331 | $leaf = new StringAsset('asdf'), |
| 332 | )), |
| 333 | )); |
| 334 | |
| 335 | $this->assertTrue($coll->replaceLeaf($leaf, new StringAsset('foo'))); |
| 336 | } |
| 337 | |
| 338 | public function testReplaceInvalidLeaf() |
| 339 | { |
| 340 | $this->setExpectedException('InvalidArgumentException'); |
| 341 | |
| 342 | $coll = new AssetCollection(); |
| 343 | $coll->replaceLeaf(new StringAsset('foo'), new StringAsset('bar')); |
| 344 | } |
| 345 | |
| 346 | public function testClone() |
| 347 | { |
| 348 | $coll1 = new AssetCollection(); |
| 349 | $coll1->ensureFilter(new CallablesFilter()); |
| 350 | |
| 351 | $coll2 = clone $coll1; |
| 352 | $coll2->ensureFilter(new CallablesFilter()); |
| 353 | |
| 354 | $this->assertCount(1, $coll1->getFilters()); |
| 355 | $this->assertCount(2, $coll2->getFilters()); |
| 356 | } |
| 357 | |
| 358 | public function testNewFilterOnCloneDoesNotPropagateToPrototype() |
| 359 | { |
| 360 | $coll1 = new AssetCollection(); |
| 361 | $coll1->add(new StringAsset("")); |
| 362 | |
| 363 | $coll2 = clone $coll1; |
| 364 | $coll2->ensureFilter(new CallablesFilter()); |
| 365 | |
| 366 | // Internally, this will set up the "clones" for collection #2 with one filter |
| 367 | foreach ($coll2 as $asset) { |
| 368 | } |
| 369 | |
| 370 | // The clones on collection #1 must not be affected |
| 371 | foreach ($coll1 as $asset) { |
| 372 | $this->assertCount(0, $asset->getFilters()); |
| 373 | } |
| 374 | } |
| 375 | |
| 376 | public function testClearingFiltersWorksAfterCollectionHasBeenIterated() |
| 377 | { |
| 378 | $coll = new AssetCollection(); |
| 379 | $coll->add(new StringAsset("")); |
| 380 | $coll->ensureFilter(new CallablesFilter()); |
| 381 | |
| 382 | /* This iteration is necessary to internally prime the collection's |
| 383 | "clones" with one filter. */ |
| 384 | foreach ($coll as $asset) { |
| 385 | $this->assertCount(1, $asset->getFilters()); |
| 386 | } |
| 387 | |
| 388 | $coll->clearFilters(); |
| 389 | |
| 390 | foreach ($coll as $asset) { |
| 391 | $this->assertCount(0, $asset->getFilters()); |
| 392 | } |
| 393 | } |
| 394 | } |
| 395 |