319 lines
9.5 KiB
PHP
319 lines
9.5 KiB
PHP
|
<?php
|
||
|
|
||
|
/*
|
||
|
* This file is part of the Assetic package, an OpenSky project.
|
||
|
*
|
||
|
* (c) 2010-2012 OpenSky Project Inc
|
||
|
*
|
||
|
* For the full copyright and license information, please view the LICENSE
|
||
|
* file that was distributed with this source code.
|
||
|
*/
|
||
|
|
||
|
namespace Assetic\Test\Asset;
|
||
|
|
||
|
use Assetic\Asset\StringAsset;
|
||
|
use Assetic\Asset\AssetCollection;
|
||
|
use Assetic\Filter\CallablesFilter;
|
||
|
|
||
|
class AssetCollectionTest extends \PHPUnit_Framework_TestCase
|
||
|
{
|
||
|
public function testInterface()
|
||
|
{
|
||
|
$coll = new AssetCollection();
|
||
|
$this->assertInstanceOf('Assetic\\Asset\\AssetInterface', $coll, 'AssetCollection implements AssetInterface');
|
||
|
}
|
||
|
|
||
|
public function testLoadFilter()
|
||
|
{
|
||
|
$filter = $this->getMock('Assetic\\Filter\\FilterInterface');
|
||
|
$filter->expects($this->once())->method('filterLoad');
|
||
|
|
||
|
$coll = new AssetCollection(array(new StringAsset('')), array($filter));
|
||
|
$coll->load();
|
||
|
}
|
||
|
|
||
|
public function testDumpFilter()
|
||
|
{
|
||
|
$filter = $this->getMock('Assetic\\Filter\\FilterInterface');
|
||
|
$filter->expects($this->once())->method('filterDump');
|
||
|
|
||
|
$coll = new AssetCollection(array(new StringAsset('')), array($filter));
|
||
|
$coll->dump();
|
||
|
}
|
||
|
|
||
|
public function testNestedCollectionLoad()
|
||
|
{
|
||
|
$content = 'foobar';
|
||
|
|
||
|
$count = 0;
|
||
|
$matches = array();
|
||
|
$filter = new CallablesFilter(function($asset) use ($content, & $matches, & $count)
|
||
|
{
|
||
|
++$count;
|
||
|
if ($content == $asset->getContent()) {
|
||
|
$matches[] = $asset;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$innerColl = new AssetCollection(array(new StringAsset($content)));
|
||
|
$outerColl = new AssetCollection(array($innerColl), array($filter));
|
||
|
$outerColl->load();
|
||
|
|
||
|
$this->assertEquals(1, count($matches), '->load() applies filters to leaves');
|
||
|
$this->assertEquals(1, $count, '->load() applies filters to leaves only');
|
||
|
}
|
||
|
|
||
|
public function testMixedIteration()
|
||
|
{
|
||
|
$asset = new StringAsset('asset');
|
||
|
$nestedAsset = new StringAsset('nested');
|
||
|
$innerColl = new AssetCollection(array($nestedAsset));
|
||
|
|
||
|
$contents = array();
|
||
|
$filter = new CallablesFilter(function($asset) use(& $contents)
|
||
|
{
|
||
|
$contents[] = $asset->getContent();
|
||
|
});
|
||
|
|
||
|
$coll = new AssetCollection(array($asset, $innerColl), array($filter));
|
||
|
$coll->load();
|
||
|
|
||
|
$this->assertEquals(array('asset', 'nested'), $contents, '->load() iterates over multiple levels');
|
||
|
}
|
||
|
|
||
|
public function testLoadDedupBySourceUrl()
|
||
|
{
|
||
|
$asset1 = new StringAsset('asset', array(), '/some/dir', 'foo.bar');
|
||
|
$asset2 = new StringAsset('asset', array(), '/some/dir', 'foo.bar');
|
||
|
|
||
|
$coll = new AssetCollection(array($asset1, $asset2));
|
||
|
$coll->load();
|
||
|
|
||
|
$this->assertEquals('asset', $coll->getContent(), '->load() detects duplicate assets based on source URL');
|
||
|
}
|
||
|
|
||
|
public function testLoadDedupByStrictEquality()
|
||
|
{
|
||
|
$asset = new StringAsset('foo');
|
||
|
|
||
|
$coll = new AssetCollection(array($asset, $asset));
|
||
|
$coll->load();
|
||
|
|
||
|
$this->assertEquals('foo', $coll->getContent(), '->load() detects duplicate assets based on strict equality');
|
||
|
}
|
||
|
|
||
|
public function testDumpDedupBySourceUrl()
|
||
|
{
|
||
|
$asset1 = new StringAsset('asset', array(), '/some/dir', 'foo.bar');
|
||
|
$asset2 = new StringAsset('asset', array(), '/some/dir', 'foo.bar');
|
||
|
|
||
|
$coll = new AssetCollection(array($asset1, $asset2));
|
||
|
$coll->load();
|
||
|
|
||
|
$this->assertEquals('asset', $coll->dump(), '->dump() detects duplicate assets based on source URL');
|
||
|
}
|
||
|
|
||
|
public function testDumpDedupByStrictEquality()
|
||
|
{
|
||
|
$asset = new StringAsset('foo');
|
||
|
|
||
|
$coll = new AssetCollection(array($asset, $asset));
|
||
|
$coll->load();
|
||
|
|
||
|
$this->assertEquals('foo', $coll->dump(), '->dump() detects duplicate assets based on strict equality');
|
||
|
}
|
||
|
|
||
|
public function testIterationFilters()
|
||
|
{
|
||
|
$count = 0;
|
||
|
$filter = new CallablesFilter(function() use(&$count) { ++$count; });
|
||
|
|
||
|
$coll = new AssetCollection();
|
||
|
$coll->add(new StringAsset(''));
|
||
|
$coll->ensureFilter($filter);
|
||
|
|
||
|
foreach ($coll as $asset) {
|
||
|
$asset->dump();
|
||
|
}
|
||
|
|
||
|
$this->assertEquals(1, $count, 'collection filters are called when child assets are iterated over');
|
||
|
}
|
||
|
|
||
|
public function testSetContent()
|
||
|
{
|
||
|
$coll = new AssetCollection();
|
||
|
$coll->setContent('asdf');
|
||
|
|
||
|
$this->assertEquals('asdf', $coll->getContent(), '->setContent() sets the content');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @dataProvider getTimestampsAndExpected
|
||
|
*/
|
||
|
public function testGetLastModified($timestamps, $expected)
|
||
|
{
|
||
|
$asset = $this->getMock('Assetic\\Asset\\AssetInterface');
|
||
|
|
||
|
for ($i = 0; $i < count($timestamps); $i++) {
|
||
|
$asset->expects($this->at($i))
|
||
|
->method('getLastModified')
|
||
|
->will($this->returnValue($timestamps[$i]));
|
||
|
}
|
||
|
|
||
|
$coll = new AssetCollection(array_fill(0, count($timestamps), $asset));
|
||
|
|
||
|
$this->assertEquals($expected, $coll->getLastModified(), '->getLastModifed() returns the highest last modified');
|
||
|
}
|
||
|
|
||
|
public function getTimestampsAndExpected()
|
||
|
{
|
||
|
return array(
|
||
|
array(array(1, 2, 3), 3),
|
||
|
array(array(5, 4, 3), 5),
|
||
|
array(array(3, 8, 5), 8),
|
||
|
array(array(3, 8, null), 8),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
public function testRecursiveIteration()
|
||
|
{
|
||
|
$asset1 = $this->getMock('Assetic\\Asset\\AssetInterface');
|
||
|
$asset2 = $this->getMock('Assetic\\Asset\\AssetInterface');
|
||
|
$asset3 = $this->getMock('Assetic\\Asset\\AssetInterface');
|
||
|
$asset4 = $this->getMock('Assetic\\Asset\\AssetInterface');
|
||
|
|
||
|
$coll3 = new AssetCollection(array($asset1, $asset2));
|
||
|
$coll2 = new AssetCollection(array($asset3, $coll3));
|
||
|
$coll1 = new AssetCollection(array($asset4, $coll2));
|
||
|
|
||
|
$i = 0;
|
||
|
foreach ($coll1 as $a) {
|
||
|
$i++;
|
||
|
}
|
||
|
|
||
|
$this->assertEquals(4, $i, 'iteration with a recursive iterator is recursive');
|
||
|
}
|
||
|
|
||
|
public function testRecursiveDeduplication()
|
||
|
{
|
||
|
$asset = $this->getMock('Assetic\\Asset\\AssetInterface');
|
||
|
|
||
|
$coll3 = new AssetCollection(array($asset, $asset));
|
||
|
$coll2 = new AssetCollection(array($asset, $coll3));
|
||
|
$coll1 = new AssetCollection(array($asset, $coll2));
|
||
|
|
||
|
$i = 0;
|
||
|
foreach ($coll1 as $a) {
|
||
|
$i++;
|
||
|
}
|
||
|
|
||
|
$this->assertEquals(1, $i, 'deduplication is performed recursively');
|
||
|
}
|
||
|
|
||
|
public function testIteration()
|
||
|
{
|
||
|
$asset1 = new StringAsset('asset1', array(), '/some/dir', 'foo.css');
|
||
|
$asset2 = new StringAsset('asset2', array(), '/some/dir', 'foo.css');
|
||
|
$asset3 = new StringAsset('asset3', array(), '/some/dir', 'bar.css');
|
||
|
|
||
|
$coll = new AssetCollection(array($asset1, $asset2, $asset3));
|
||
|
|
||
|
$count = 0;
|
||
|
foreach ($coll as $a) {
|
||
|
++$count;
|
||
|
}
|
||
|
|
||
|
$this->assertEquals(2, $count, 'iterator filters duplicates based on url');
|
||
|
}
|
||
|
|
||
|
public function testBasenameCollision()
|
||
|
{
|
||
|
$asset1 = new StringAsset('asset1', array(), '/some/dir', 'foo/foo.css');
|
||
|
$asset2 = new StringAsset('asset2', array(), '/some/dir', 'bar/foo.css');
|
||
|
|
||
|
$coll = new AssetCollection(array($asset1, $asset2));
|
||
|
|
||
|
$urls = array();
|
||
|
foreach ($coll as $leaf) {
|
||
|
$urls[] = $leaf->getTargetPath();
|
||
|
}
|
||
|
|
||
|
$this->assertEquals(2, count(array_unique($urls)), 'iterator prevents basename collisions');
|
||
|
}
|
||
|
|
||
|
public function testEmptyMtime()
|
||
|
{
|
||
|
$coll = new AssetCollection();
|
||
|
$this->assertNull($coll->getLastModified(), '->getLastModified() returns null on empty collection');
|
||
|
}
|
||
|
|
||
|
public function testLeafManipulation()
|
||
|
{
|
||
|
$coll = new AssetCollection(array(new StringAsset('asdf')));
|
||
|
|
||
|
foreach ($coll as $leaf) {
|
||
|
$leaf->setTargetPath('asdf');
|
||
|
}
|
||
|
|
||
|
foreach ($coll as $leaf) {
|
||
|
$this->assertEquals('asdf', $leaf->getTargetPath(), 'leaf changes persist between iterations');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function testRemoveLeaf()
|
||
|
{
|
||
|
$coll = new AssetCollection(array(
|
||
|
$leaf = new StringAsset('asdf'),
|
||
|
));
|
||
|
|
||
|
$this->assertTrue($coll->removeLeaf($leaf));
|
||
|
}
|
||
|
|
||
|
public function testRemoveRecursiveLeaf()
|
||
|
{
|
||
|
$coll = new AssetCollection(array(
|
||
|
new AssetCollection(array(
|
||
|
$leaf = new StringAsset('asdf'),
|
||
|
))
|
||
|
));
|
||
|
|
||
|
$this->assertTrue($coll->removeLeaf($leaf));
|
||
|
}
|
||
|
|
||
|
public function testRemoveInvalidLeaf()
|
||
|
{
|
||
|
$this->setExpectedException('InvalidArgumentException');
|
||
|
|
||
|
$coll = new AssetCollection();
|
||
|
$coll->removeLeaf(new StringAsset('asdf'));
|
||
|
}
|
||
|
|
||
|
public function testReplaceLeaf()
|
||
|
{
|
||
|
$coll = new AssetCollection(array(
|
||
|
$leaf = new StringAsset('asdf'),
|
||
|
));
|
||
|
|
||
|
$this->assertTrue($coll->replaceLeaf($leaf, new StringAsset('foo')));
|
||
|
}
|
||
|
|
||
|
public function testReplaceRecursiveLeaf()
|
||
|
{
|
||
|
$coll = new AssetCollection(array(
|
||
|
new AssetCollection(array(
|
||
|
$leaf = new StringAsset('asdf'),
|
||
|
)),
|
||
|
));
|
||
|
|
||
|
$this->assertTrue($coll->replaceLeaf($leaf, new StringAsset('foo')));
|
||
|
}
|
||
|
|
||
|
public function testReplaceInvalidLeaf()
|
||
|
{
|
||
|
$this->setExpectedException('InvalidArgumentException');
|
||
|
|
||
|
$coll = new AssetCollection();
|
||
|
$coll->replaceLeaf(new StringAsset('foo'), new StringAsset('bar'));
|
||
|
}
|
||
|
}
|