diff --git a/core/includes/common.inc b/core/includes/common.inc index 723d352..163a123 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -1874,6 +1874,7 @@ function drupal_pre_render_styles($elements) { $collection = &drupal_static('global_asset_collection', FALSE); + /** @var $collection \Drupal\Core\Asset\Collection\AssetCollectionInterface */ $collection->resolveLibraries(\Drupal::service('asset.library_repository')); $collection->ksort(); diff --git a/core/lib/Drupal/Core/Asset/AssetLibraryRepository.php b/core/lib/Drupal/Core/Asset/AssetLibraryRepository.php index 0744d3d..487d9e6 100644 --- a/core/lib/Drupal/Core/Asset/AssetLibraryRepository.php +++ b/core/lib/Drupal/Core/Asset/AssetLibraryRepository.php @@ -106,11 +106,14 @@ public function resolveDependencies(DependencyInterface $asset, $attach = TRUE) $dependencies[] = $library = $this->get($key); // Only bother attaching if operating on an asset. - if ($attach && $asset instanceof AssetInterface) { + if ($attach && $asset instanceof RelativePositionInterface) { foreach ($library as $libasset) { - if ($asset->getAssetType() === $libasset->getAssetType()) { - $asset->after($libasset); + if ($asset instanceof AssetInterface && + $asset->getAssetType() !== $libasset->getAssetType()) { + continue; } + + $asset->after($libasset); } } } diff --git a/core/lib/Drupal/Core/Asset/BaseAsset.php b/core/lib/Drupal/Core/Asset/BaseAsset.php index 0413a15..650417b 100644 --- a/core/lib/Drupal/Core/Asset/BaseAsset.php +++ b/core/lib/Drupal/Core/Asset/BaseAsset.php @@ -20,7 +20,7 @@ * The methods load() and getLastModified() are left undefined, although a * reusable doLoad() method is available to child classes. */ -abstract class BaseAsset extends AsseticAdapterAsset implements AssetInterface, DependencyInterface { +abstract class BaseAsset extends AsseticAdapterAsset implements AssetInterface, DependencyInterface, RelativePositionInterface { /** * @var AssetMetadataInterface @@ -67,27 +67,21 @@ public function isPreprocessable() { /** * {@inheritdoc} */ - public function hasDependencies() { - return !empty($this->dependencies); - } - - /** - * {@inheritdoc} - */ public function addDependency($key) { - if (!is_string($key)) { + if (!is_string($key) || substr_count($key, '/') !== 1) { throw new \InvalidArgumentException('Dependencies must be expressed as a string key identifying the depended-upon library.'); } // The library key is stored as the key for cheap deduping. $this->dependencies[$key] = TRUE; + return $this; } /** * {@inheritdoc} */ - public function clearDependencies() { - $this->dependencies = array(); + public function hasDependencies() { + return !empty($this->dependencies); } /** @@ -100,12 +94,9 @@ public function getDependencyInfo() { /** * {@inheritdoc} */ - public function before($asset) { - if (!($asset instanceof AssetInterface || is_string($asset))) { - throw new \InvalidArgumentException('Ordering information must be declared using either an asset string id or the full AssetInterface object.'); - } - - $this->successors[] = $asset; + public function clearDependencies() { + $this->dependencies = array(); + return $this; } /** @@ -117,6 +108,14 @@ public function after($asset) { } $this->predecessors[] = $asset; + return $this; + } + + /** + * {@inheritdoc} + */ + public function hasPredecessors() { + return !empty($this->predecessors); } /** @@ -129,21 +128,44 @@ public function getPredecessors() { /** * {@inheritdoc} */ - public function getSuccessors() { - return $this->successors; + public function clearPredecessors() { + $this->predecessors = array(); + return $this; } /** * {@inheritdoc} */ - public function clearSuccessors() { - $this->successors = array(); + public function before($asset) { + if (!($asset instanceof AssetInterface || is_string($asset))) { + throw new \InvalidArgumentException('Ordering information must be declared using either an asset string id or the full AssetInterface object.'); + } + + $this->successors[] = $asset; + return $this; } /** * {@inheritdoc} */ - public function clearPredecessors() { - $this->predecessors = array(); + public function hasSuccessors() { + return !empty($this->successors); } + + /** + * {@inheritdoc} + */ + public function getSuccessors() { + return $this->successors; + } + + /** + * {@inheritdoc} + */ + public function clearSuccessors() { + $this->successors = array(); + return $this; + } + } + diff --git a/core/lib/Drupal/Core/Asset/Collection/AssetCollection.php b/core/lib/Drupal/Core/Asset/Collection/AssetCollection.php index 91e34eb..52a9f69 100644 --- a/core/lib/Drupal/Core/Asset/Collection/AssetCollection.php +++ b/core/lib/Drupal/Core/Asset/Collection/AssetCollection.php @@ -14,7 +14,6 @@ use Drupal\Core\Asset\DependencyInterface; use Drupal\Core\Asset\Exception\FrozenObjectException; use Drupal\Core\Asset\Exception\UnsupportedAsseticBehaviorException; -use Drupal\Core\Asset\RelativePositionInterface; /** * A container for assets. @@ -90,6 +89,8 @@ public function replace($needle, AssetInterface $replacement, $graceful = FALSE) */ public function freeze() { $this->frozen = TRUE; + + return $this; } /** @@ -129,6 +130,8 @@ public function getJs() { public function uksort($callback) { $this->attemptWrite(__METHOD__); uksort($this->assetIdMap, $callback); + + return $this; } /** @@ -137,6 +140,8 @@ public function uksort($callback) { public function ksort() { $this->attemptWrite(__METHOD__); ksort($this->assetIdMap); + + return $this; } /** @@ -147,6 +152,8 @@ public function ksort() { public function reverse() { $this->attemptWrite(__METHOD__); $this->assetIdMap = array_reverse($this->assetIdMap); + + return $this; } /** @@ -156,6 +163,8 @@ public function addUnresolvedLibrary($key) { $this->attemptWrite(__METHOD__); // The library key is stored as the key for cheap deduping. $this->libraries[$key] = TRUE; + + return $this; } /** @@ -178,6 +187,8 @@ public function getUnresolvedLibraries() { public function clearUnresolvedLibraries() { $this->attemptWrite(__METHOD__); $this->libraries = array(); + + return $this; } /** @@ -211,6 +222,8 @@ public function resolveLibraries(AssetLibraryRepository $repository) { } } } + + return $this; } /** diff --git a/core/lib/Drupal/Core/Asset/Collection/AssetCollectionBasicInterface.php b/core/lib/Drupal/Core/Asset/Collection/AssetCollectionBasicInterface.php index 9ae38fb..b1394cb 100644 --- a/core/lib/Drupal/Core/Asset/Collection/AssetCollectionBasicInterface.php +++ b/core/lib/Drupal/Core/Asset/Collection/AssetCollectionBasicInterface.php @@ -33,9 +33,8 @@ * The asset to add. Note that, despite the type requirements, it must * conform to Drupal's AssetInterface. * - * @return bool - * TRUE if the asset was added successfully, FALSE if it was already present - * in the aggregate. + * @return AssetCollectionInterface + * The current asset collection. * * @throws UnsupportedAsseticBehaviorException * Thrown if a vanilla Assetic asset is provided. diff --git a/core/lib/Drupal/Core/Asset/Collection/AssetCollectionInterface.php b/core/lib/Drupal/Core/Asset/Collection/AssetCollectionInterface.php index 6649714..81d6f31 100644 --- a/core/lib/Drupal/Core/Asset/Collection/AssetCollectionInterface.php +++ b/core/lib/Drupal/Core/Asset/Collection/AssetCollectionInterface.php @@ -12,8 +12,6 @@ /** * Describes an asset collection. * - * TODO we need a few more methods here to deal with library resolution - * * @see \Drupal\Core\Asset\Collection\AssetCollectionBasicInterface */ interface AssetCollectionInterface extends AssetCollectionBasicInterface { @@ -31,7 +29,8 @@ * @param bool $freeze * Whether to freeze the provided collection after merging. Defaults to TRUE. * - * @return void + * @return AssetCollectionInterface + * The current asset collection. */ public function mergeCollection(AssetCollectionInterface $collection, $freeze = TRUE); @@ -43,7 +42,8 @@ public function mergeCollection(AssetCollectionInterface $collection, $freeze = * * TODO put this on the basic interface so aggregates have it, too? * - * @return void + * @return AssetCollectionInterface + * The current asset collection. */ public function freeze(); @@ -73,21 +73,24 @@ public function getJs(); * * @param $callback * - * @return void + * @return AssetCollectionInterface + * The current asset collection. */ public function uksort($callback); /** * Sorts contained assets via ksort() on their ids. * - * @return void + * @return AssetCollectionInterface + * The current asset collection. */ public function ksort(); /** * Reverses the sort order of the contained assets. * - * @return void + * @return AssetCollectionInterface + * The current asset collection. */ public function reverse(); @@ -102,7 +105,8 @@ public function reverse(); * slash-delimited, with the first part being the module owner and the * second part being the library name. * - * @return void + * @return AssetCollectionInterface + * The current asset collection. * * @see AssetCollectionInterface::resolveLibraries() */ @@ -127,7 +131,8 @@ public function getUnresolvedLibraries(); /** * Empties the collection of its unresolved library keys. * - * @return void + * @return AssetCollectionInterface + * The current asset collection. */ public function clearUnresolvedLibraries(); @@ -142,7 +147,8 @@ public function clearUnresolvedLibraries(); * The AssetLibraryRepository to use for resolving library keys into * AssetLibrary objects. * - * @return void + * @return AssetCollectionInterface + * The current asset collection. */ public function resolveLibraries(AssetLibraryRepository $repository); } diff --git a/core/lib/Drupal/Core/Asset/Collection/AssetLibrary.php b/core/lib/Drupal/Core/Asset/Collection/AssetLibrary.php index 6c6ad54..4e807bd 100644 --- a/core/lib/Drupal/Core/Asset/Collection/AssetLibrary.php +++ b/core/lib/Drupal/Core/Asset/Collection/AssetLibrary.php @@ -7,11 +7,19 @@ namespace Drupal\Core\Asset\Collection; +use Drupal\Core\Asset\AssetInterface; use Drupal\Core\Asset\DependencyInterface; use Drupal\Core\Asset\Collection\AssetCollection; use Drupal\Core\Asset\Exception\FrozenObjectException; +use Drupal\Core\Asset\RelativePositionInterface; -class AssetLibrary extends AssetCollection implements DependencyInterface { +/** + * An asset library is a named collection of assets. + * + * The primary role of an asset library is to be declared as a dependency by + * other assets (including assets declared by other libraries). + */ +class AssetLibrary extends AssetCollection implements DependencyInterface, RelativePositionInterface { /** * The asset library's title. @@ -123,29 +131,22 @@ public function getVersion() { /** * {@inheritdoc} */ - public function hasDependencies() { - return !empty($this->dependencies); - } - - /** - * {@inheritdoc} - */ public function addDependency($key) { $this->attemptWrite(__METHOD__); - if (!is_string($key)) { + if (!is_string($key) || substr_count($key, '/') !== 1) { throw new \InvalidArgumentException('Dependencies must be expressed as a string key identifying the depended-upon library.'); } // The library key is stored as the key for cheap deduping. $this->dependencies[$key] = TRUE; + return $this; } /** * {@inheritdoc} */ - public function clearDependencies() { - $this->attemptWrite(__METHOD__); - $this->dependencies = array(); + public function hasDependencies() { + return !empty($this->dependencies); } /** @@ -158,15 +159,30 @@ public function getDependencyInfo() { /** * {@inheritdoc} */ - public function before($asset) { - $this->successors[] = $asset; + public function clearDependencies() { + $this->attemptWrite(__METHOD__); + $this->dependencies = array(); + return $this; } /** * {@inheritdoc} */ public function after($asset) { + $this->attemptWrite(__METHOD__); + if (!($asset instanceof AssetInterface || is_string($asset))) { + throw new \InvalidArgumentException('Ordering information must be declared using either an asset string id or the full AssetInterface object.'); + } + $this->predecessors[] = $asset; + return $this; + } + + /** + * {@inheritdoc} + */ + public function hasPredecessors() { + return !empty($this->predecessors); } /** @@ -179,22 +195,46 @@ public function getPredecessors() { /** * {@inheritdoc} */ - public function getSuccessors() { - return $this->successors; + public function clearPredecessors() { + $this->attemptWrite(__METHOD__); + $this->predecessors = array(); + return $this; } /** * {@inheritdoc} */ - public function clearSuccessors() { - $this->successors = array(); + public function before($asset) { + $this->attemptWrite(__METHOD__); + if (!($asset instanceof AssetInterface || is_string($asset))) { + throw new \InvalidArgumentException('Ordering information must be declared using either an asset string id or the full AssetInterface object.'); + } + + $this->successors[] = $asset; + return $this; } /** * {@inheritdoc} */ - public function clearPredecessors() { - $this->predecessors = array(); + public function hasSuccessors() { + return !empty($this->successors); + } + + /** + * {@inheritdoc} + */ + public function getSuccessors() { + return $this->successors; + } + + /** + * {@inheritdoc} + */ + public function clearSuccessors() { + $this->attemptWrite(__METHOD__); + $this->successors = array(); + return $this; } /** diff --git a/core/lib/Drupal/Core/Asset/Collection/BasicAssetCollection.php b/core/lib/Drupal/Core/Asset/Collection/BasicAssetCollection.php index 2cd2f16..85ce488 100644 --- a/core/lib/Drupal/Core/Asset/Collection/BasicAssetCollection.php +++ b/core/lib/Drupal/Core/Asset/Collection/BasicAssetCollection.php @@ -68,18 +68,16 @@ public function add(AsseticAssetInterface $asset) { } $this->ensureCorrectType($asset); - if ($this->contains($asset) || $this->find($asset->id())) { - return FALSE; - } + if (!($this->contains($asset) || $this->find($asset->id()))) { + $this->assetStorage->attach($asset); + $this->assetIdMap[$asset->id()] = $asset; - $this->assetStorage->attach($asset); - $this->assetIdMap[$asset->id()] = $asset; - - if ($asset instanceof AssetCollectionBasicInterface) { - $this->nestedStorage->attach($asset); + if ($asset instanceof AssetCollectionBasicInterface) { + $this->nestedStorage->attach($asset); + } } - return TRUE; + return $this; } /** diff --git a/core/lib/Drupal/Core/Asset/DependencyInterface.php b/core/lib/Drupal/Core/Asset/DependencyInterface.php index cea6ceb..00488b3 100644 --- a/core/lib/Drupal/Core/Asset/DependencyInterface.php +++ b/core/lib/Drupal/Core/Asset/DependencyInterface.php @@ -8,17 +8,13 @@ /** * Describes assets that can declare dependencies on asset libraries. - * - * "Dependency" expands the concept of positioning expressed by the parent - * interface RelativePositionInterface by ensuring the presence of another - * another asset. */ -interface DependencyInterface extends RelativePositionInterface { +interface DependencyInterface { /** * Indicates whether this asset has one or more library dependencies. * - * @return boolean + * @return bool */ public function hasDependencies(); @@ -37,8 +33,9 @@ public function getDependencyInfo(); * The string identifying the library. It should be two-part composite key, * slash-delimited, with the first part being the module owner and the * second part being the library name. - - * @return void + * + * @return DependencyInterface + * The current DependencyInterface object. */ public function addDependency($key); @@ -47,8 +44,9 @@ public function addDependency($key); * * This does not affect ordering data. * - * @return void + * @return DependencyInterface + * The current DependencyInterface object. */ public function clearDependencies(); - } + diff --git a/core/lib/Drupal/Core/Asset/Factory/AssetCollectorInterface.php b/core/lib/Drupal/Core/Asset/Factory/AssetCollectorInterface.php index 0a59ec2..f171de1 100644 --- a/core/lib/Drupal/Core/Asset/Factory/AssetCollectorInterface.php +++ b/core/lib/Drupal/Core/Asset/Factory/AssetCollectorInterface.php @@ -72,6 +72,7 @@ public function add(AssetInterface $asset); * @see clearLastCss(). * * @return \Drupal\Core\Asset\AssetInterface + * The created AssetInterface object. * * @throws \InvalidArgumentException * Thrown if an invalid asset type or source type is passed. @@ -91,8 +92,8 @@ public function create($asset_type, $source_type, $data, $options = array(), $fi * end of such a contiguous series is reached, or by the asset creator * themselves if they want to avoid the creation of the ordering relationship. * - * @return AssetCollector - * The current AssetCollector instance, for easy chaining. + * @return AssetCollectorInterface + * The current asset collector. */ public function clearLastCss(); @@ -103,8 +104,10 @@ public function clearLastCss(); * all assets generated via its create() method to the collection. * * @param AssetCollectionInterface $collection + * The collection the collector should use internally. * - * @return void + * @return AssetCollectorInterface + * The current asset collector. * * @throws LockedObjectException * Thrown if the collector is locked when this method is called. @@ -114,7 +117,8 @@ public function setCollection(AssetCollectionInterface $collection); /** * Clears the internal collection for this collector. * - * @return void + * @return AssetCollectorInterface + * The current asset collector. * * @throws LockedObjectException * Thrown if the collector is locked when this method is called. @@ -138,7 +142,8 @@ public function hasCollection(); * @param mixed $key * The key used to lock the collector. * - * @return void + * @return AssetCollectorInterface + * The current asset collector. * * @throws LockedObjectException * Thrown if the collector is already locked. @@ -153,7 +158,8 @@ public function lock($key); * @param mixed $key * The key with which to unlock the collector. * - * @return void + * @return AssetCollectorInterface + * The current asset collector. * * @throws LockedObjectException * Thrown if the incorrect key is provided, or if the collector is not @@ -174,7 +180,8 @@ public function isLocked(); * @param MetadataFactoryInterface $factory * The factory to use. * - * @return void + * @return AssetCollectorInterface + * The current asset collector. * * @throws LockedObjectException * Thrown if the collector is locked when this method is called. diff --git a/core/lib/Drupal/Core/Asset/RelativePositionInterface.php b/core/lib/Drupal/Core/Asset/RelativePositionInterface.php index 66293d8..cd6c6e0 100644 --- a/core/lib/Drupal/Core/Asset/RelativePositionInterface.php +++ b/core/lib/Drupal/Core/Asset/RelativePositionInterface.php @@ -10,14 +10,27 @@ * Describes an asset or asset-like object that can declare dependencies. */ interface RelativePositionInterface { + /** - * Clears (removes) all ordering info declared by after() for this asset. + * Declare that an asset should, if present, precede this asset on output. * - * This does not affect dependency data. + * Either the string identifier for the other asset, or the asset object + * itself, should be provided. * - * @return void + * @param string|AssetInterface $asset + * The asset to precede the current asset. + * + * @return RelativePositionInterface + * The current RelativePositionInterface object. */ - public function clearPredecessors(); + public function after($asset); + + /** + * Indicates whether this asset has one or more asset predecessors. + * + * @return bool + */ + public function hasPredecessors(); /** * Returns ordering info declared by after(). @@ -29,6 +42,16 @@ public function clearPredecessors(); public function getPredecessors(); /** + * Clears all ordering info declared by after() for this asset. + * + * This does not affect dependency data. + * + * @return RelativePositionInterface + * The current RelativePositionInterface object. + */ + public function clearPredecessors(); + + /** * Declare that an asset should, if present, succeed this asset on output. * * Either the string identifier for the other asset, or the asset object @@ -37,11 +60,19 @@ public function getPredecessors(); * @param string|AssetInterface $asset * The asset to succeed the current asset. * - * @return void + * @return RelativePositionInterface + * The current RelativePositionInterface object. */ public function before($asset); /** + * Indicates whether this asset has one or more asset successors. + * + * @return bool + */ + public function hasSuccessors(); + + /** * Returns ordering info declared by before(). * * @return array @@ -55,20 +86,10 @@ public function getSuccessors(); * * This does not affect dependency data. * - * @return void + * @return RelativePositionInterface + * The current RelativePositionInterface object. */ public function clearSuccessors(); - /** - * Declare that an asset should, if present, precede this asset on output. - * - * Either the string identifier for the other asset, or the asset object - * itself, should be provided. - * - * @param string|AssetInterface $asset - * The asset to precede the current asset. - * - * @return void - */ - public function after($asset); -} \ No newline at end of file +} + diff --git a/core/tests/Drupal/Tests/Core/Asset/Aggregate/AssetAggregateTest.php b/core/tests/Drupal/Tests/Core/Asset/Aggregate/AssetAggregateTest.php index e6a90a7..326a9cc 100644 --- a/core/tests/Drupal/Tests/Core/Asset/Aggregate/AssetAggregateTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/Aggregate/AssetAggregateTest.php @@ -10,13 +10,14 @@ use Drupal\Core\Asset\Collection\AssetCollectionBasicInterface; use Drupal\Core\Asset\Exception\AssetTypeMismatchException; use Drupal\Core\Asset\Exception\UnsupportedAsseticBehaviorException; +use Drupal\Tests\Core\Asset\AssetUnitTest; use Drupal\Tests\Core\Asset\Collection\BasicAssetCollectionTest; /** * @coversDefaultClass \Drupal\Core\Asset\Aggregate\AssetAggregate * @group Asset */ -class AssetAggregateTest extends BasicAssetCollectionTest { +class AssetAggregateTest extends AssetUnitTest { public static function getInfo() { return array( @@ -81,7 +82,7 @@ public function testGetMetadata() { public function testAdd() { $aggregate = $this->getAggregate(); $asset = $this->createStubFileAsset(); - $this->assertTrue($aggregate->add($asset)); + $this->assertSame($aggregate, $aggregate->add($asset)); $this->assertAttributeContains($asset, 'assetStorage', $aggregate); $this->assertAttributeContains($asset, 'assetIdMap', $aggregate); diff --git a/core/tests/Drupal/Tests/Core/Asset/AssetLibraryRepositoryTest.php b/core/tests/Drupal/Tests/Core/Asset/AssetLibraryRepositoryTest.php index 44510f8..adfe81e 100644 --- a/core/tests/Drupal/Tests/Core/Asset/AssetLibraryRepositoryTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/AssetLibraryRepositoryTest.php @@ -186,6 +186,7 @@ public function testResolveDependencies() { $compatible_dep = $this->createStubFileAsset(); $incompatible_dep = $this->createStubFileAsset('js'); + $lib_dep = $this->createStubFileAsset(); $main_asset = $this->getMock('Drupal\\Core\\Asset\\FileAsset', array(), array(), '', FALSE); $main_asset->expects($this->exactly(2)) @@ -207,6 +208,8 @@ public function testResolveDependencies() { $library1->expects($this->once()) ->method('getDependencyInfo') ->will($this->returnValue(array('foo/baz', 'qux/bing'))); + $library1->expects($this->once()) + ->method('after')->with($lib_dep); $it = new \ArrayIterator(array($compatible_dep, $incompatible_dep)); @@ -215,9 +218,18 @@ public function testResolveDependencies() { ->will($this->returnValue($it)); $library2 = $this->getMock('Drupal\\Core\\Asset\\Collection\\AssetLibrary'); + $library2->expects($this->once()) + ->method('getIterator') + ->will($this->returnValue(new \ArrayIterator(array()))); + $library2->expects($this->never()) + ->method('hasDependencies'); + $library3 = $this->getMock('Drupal\\Core\\Asset\\Collection\\AssetLibrary'); + $library3->expects($this->once()) + ->method('getIterator') + ->will($this->returnValue(new \ArrayIterator(array($lib_dep)))); $library3->expects($this->never()) - ->method('getDependencyInfo') + ->method('hasDependencies') ->will($this->returnValue(array('qux/quark'))); $library4 = $this->getMock('Drupal\\Core\\Asset\\Collection\\AssetLibrary'); diff --git a/core/tests/Drupal/Tests/Core/Asset/BaseAssetTest.php b/core/tests/Drupal/Tests/Core/Asset/BaseAssetTest.php index 475d0e9..7a3125f 100644 --- a/core/tests/Drupal/Tests/Core/Asset/BaseAssetTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/BaseAssetTest.php @@ -9,7 +9,7 @@ use Drupal\Core\Asset\BaseAsset; /** - * + * @coversDefaultClass \Drupal\Core\Asset\BaseAsset * @group Asset */ class BaseAssetTest extends AssetUnitTest { @@ -63,19 +63,15 @@ public function testIsPreprocessable() { } /** - * Tests all dependency-related methods. + * @covers ::addDependency */ - public function testDependencies() { + public function testAddDependency() { $asset = $this->createBaseAsset(); - $asset->addDependency('foo/bar'); - $this->assertEquals(array('foo/bar'), $asset->getDependencyInfo()); - $this->assertTrue($asset->hasDependencies()); + $this->assertSame($asset, $asset->addDependency('foo/bar')); + $this->assertAttributeContains('foo/bar', 'dependencies', $asset); - $asset->clearDependencies(); - $this->assertEmpty($asset->getDependencyInfo()); - - $invalid = array(0, 1.1, fopen(__FILE__, 'r'), TRUE, array(), new \stdClass); + $invalid = array('foo', 'foo//bar', 0, 1.1, fopen(__FILE__, 'r'), TRUE, array(), new \stdClass); try { foreach ($invalid as $val) { @@ -85,39 +81,114 @@ public function testDependencies() { } catch (\InvalidArgumentException $e) {} } - public function testSuccessors() { + /** + * @depends testAddDependency + * @covers ::hasDependencies + */ + public function testHasDependencies() { $asset = $this->createBaseAsset(); - $dep = $this->createBaseAsset(); + $this->assertFalse($asset->hasDependencies()); - $asset->before('foo'); - $asset->before($dep); + $asset->addDependency('foo/bar'); + $this->assertTrue($asset->hasDependencies()); + } - $this->assertEquals(array('foo', $dep), $asset->getSuccessors()); + /** + * @depends testAddDependency + * @covers ::getDependencyInfo + */ + public function testGetDependencyInfo() { + $asset = $this->createBaseAsset(); + $this->assertEmpty($asset->getDependencyInfo()); - $asset->clearSuccessors(); - $this->assertEmpty($asset->getSuccessors()); + $asset->addDependency('foo/bar'); + $this->assertEquals(array('foo/bar'), $asset->getDependencyInfo()); + } + + /** + * @depends testAddDependency + * @depends testHasDependencies + * @covers ::clearDependencies + */ + public function testClearDependencies() { + $asset = $this->createBaseAsset(); + $asset->addDependency('foo/bar'); + + $this->assertSame($asset, $asset->clearDependencies()); + $this->assertFalse($asset->hasDependencies()); + } + + /** + * @covers ::after + */ + public function testAfter() { + $asset = $this->createBaseAsset(); + $dep = $this->createBaseAsset(); + + $this->assertSame($asset, $asset->after('foo')); + $this->assertSame($asset, $asset->after($dep)); + + $this->assertAttributeContains($dep, 'predecessors', $asset); $invalid = array(0, 1.1, fopen(__FILE__, 'r'), TRUE, array(), new \stdClass); try { foreach ($invalid as $val) { - $asset->before($val); + $asset->after($val); $this->fail('Was able to create an ordering relationship with an inappropriate value.'); } } catch (\InvalidArgumentException $e) {} } - public function testPredecessors() { + /** + * @depends testAfter + * @covers ::hasPredecessors + */ + public function testHasPredecessors() { $asset = $this->createBaseAsset(); - $dep = $this->createBaseAsset(); + $this->assertFalse($asset->hasPredecessors()); $asset->after('foo'); - $asset->after($dep); - $this->assertEquals(array('foo', $dep), $asset->getPredecessors()); + $this->assertTrue($asset->hasPredecessors()); + } - $asset->clearPredecessors(); + /** + * @depends testAfter + * @covers ::getPredecessors + */ + public function testGetPredecessors() { + $asset = $this->createBaseAsset(); $this->assertEmpty($asset->getPredecessors()); + $asset->after('foo'); + $this->assertEquals(array('foo'), $asset->getPredecessors()); + } + + /** + * @depends testAfter + * @depends testHasPredecessors + * @covers ::clearPredecessors + */ + public function testClearPredecessors() { + $asset = $this->createBaseAsset(); + $asset->after('foo'); + + $this->assertSame($asset, $asset->clearPredecessors()); + $this->assertFalse($asset->hasPredecessors()); + } + + /** + * @covers ::before + */ + public function testBefore() { + $asset = $this->createBaseAsset(); + $dep = $this->createBaseAsset(); + + $this->assertSame($asset, $asset->before('foo')); + $this->assertSame($asset, $asset->before($dep)); + + $this->assertAttributeContains($dep, 'successors', $asset); + $invalid = array(0, 1.1, fopen(__FILE__, 'r'), TRUE, array(), new \stdClass); try { @@ -128,6 +199,42 @@ public function testPredecessors() { } catch (\InvalidArgumentException $e) {} } + /** + * @depends testBefore + * @covers ::hasSuccessors + */ + public function testHasSuccessors() { + $asset = $this->createBaseAsset(); + $this->assertFalse($asset->hasSuccessors()); + + $asset->before('foo'); + $this->assertTrue($asset->hasSuccessors()); + } + + /** + * @depends testBefore + * @covers ::getSuccessors + */ + public function testGetSuccessors() { + $asset = $this->createBaseAsset(); + $this->assertEmpty($asset->getSuccessors()); + + $asset->before('foo'); + $this->assertEquals(array('foo'), $asset->getSuccessors()); + } + + /** + * @depends testBefore + * @covers ::clearSuccessors + */ + public function testClearSuccessors() { + $asset = $this->createBaseAsset(); + $asset->before('foo'); + + $this->assertSame($asset, $asset->clearSuccessors()); + $this->assertFalse($asset->hasSuccessors()); + } + public function testClone() { $mockmeta = $this->createStubAssetMetadata(); $asset = $this->getMockForAbstractClass('\\Drupal\\Core\\Asset\\BaseAsset', array($mockmeta)); diff --git a/core/tests/Drupal/Tests/Core/Asset/Collection/AssetCollectionTest.php b/core/tests/Drupal/Tests/Core/Asset/Collection/AssetCollectionTest.php index cad02c3..4c4357a 100644 --- a/core/tests/Drupal/Tests/Core/Asset/Collection/AssetCollectionTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/Collection/AssetCollectionTest.php @@ -4,18 +4,18 @@ * Contains Drupal\Tests\Core\Asset\AssetCollectionTest. */ - namespace Drupal\Tests\Core\Asset\Collection; use Drupal\Core\Asset\Collection\AssetCollection; use Drupal\Core\Asset\Collection\AssetCollectionBasicInterface; use Drupal\Core\Asset\Exception\FrozenObjectException; +use Drupal\Tests\Core\Asset\AssetUnitTest; /** * @coversDefaultClass \Drupal\Core\Asset\Collection\AssetCollection * @group Asset */ -class AssetCollectionTest extends BasicAssetCollectionTest { +class AssetCollectionTest extends AssetUnitTest { /** * @var AssetCollection @@ -50,37 +50,15 @@ public function testAdd() { $asset1 = $this->createStubFileAsset(); $asset2 = $this->createStubFileAsset(); - $this->assertTrue($this->collection->add($asset1)); - $this->assertTrue($this->collection->add($asset2)); + // test fluency + $this->assertSame($this->collection, $this->collection->add($asset1)); + $this->assertSame($this->collection, $this->collection->add($asset2)); $this->assertContains($asset1, $this->collection); $this->assertContains($asset2, $this->collection); } /** - * Tests that adding the same asset twice is disallowed. - * - * @depends testAdd - * @covers ::add - */ - public function testDoubleAdd() { - $asset = $this->createStubFileAsset(); - $this->assertTrue($this->collection->add($asset)); - - $this->assertTrue($this->collection->contains($asset)); - - // Test by object identity - $this->assertFalse($this->collection->add($asset)); - // Test by id - $asset2 = $this->getMock('Drupal\\Core\\Asset\\FileAsset', array(), array(), '', FALSE); - $asset2->expects($this->once()) - ->method('id') - ->will($this->returnValue($asset->id())); - - $this->assertFalse($this->collection->add($asset2)); - } - - /** * @depends testAdd * @covers ::contains */ @@ -185,6 +163,7 @@ public function testRemoveById() { /** * @expectedException \OutOfBoundsException + * @covers ::remove */ public function testRemoveNonexistentId() { $this->assertFalse($this->collection->remove('foo', TRUE)); @@ -193,6 +172,7 @@ public function testRemoveNonexistentId() { /** * @expectedException \OutOfBoundsException + * @covers ::remove */ public function testRemoveNonexistentAsset() { $stub = $this->createStubFileAsset(); @@ -210,7 +190,7 @@ public function testMergeCollection() { $stub2 = $this->createStubFileAsset(); $coll2->add($stub1); - $this->collection->mergeCollection($coll2); + $this->assertSame($this->collection, $this->collection->mergeCollection($coll2)); $this->assertContains($stub1, $this->collection); $this->assertTrue($coll2->isFrozen()); @@ -219,7 +199,7 @@ public function testMergeCollection() { $coll3->add($stub1); $coll3->add($stub2); // Ensure no duplicates, and don't freeze merged bag - $this->collection->mergeCollection($coll3, FALSE); + $this->assertSame($this->collection, $this->collection->mergeCollection($coll3, FALSE)); $contained = array( $stub1->id() => $stub1, @@ -232,6 +212,10 @@ public function testMergeCollection() { /** * Tests that all methods that should be disabled by freezing the collection * correctly trigger an exception. + * + * @covers ::freeze + * @covers ::isFrozen + * @covers ::attemptWrite */ public function testExceptionOnWriteWhenFrozen() { $stub = $this->createStubFileAsset(); @@ -248,6 +232,10 @@ public function testExceptionOnWriteWhenFrozen() { 'resolveLibraries' => array($this->getMock('Drupal\\Core\\Asset\\AssetLibraryRepository', array(), array(), '', FALSE)), ); + // No exception before freeze + list($method, $args) = each($write_protected); + call_user_func_array(array($this->collection, $method), $args); + $this->collection->freeze(); foreach ($write_protected as $method => $args) { try { @@ -262,7 +250,7 @@ public function testExceptionOnWriteWhenFrozen() { * @covers ::find * @expectedException OutOfBoundsException */ - public function testGetById() { + public function testFind() { $metamock = $this->createStubAssetMetadata(); $asset = $this->getMock('\\Drupal\\Core\\Asset\\FileAsset', array(), array($metamock, 'foo')); @@ -303,7 +291,7 @@ public function testUkSort() { return strnatcasecmp($a, $b); }; - $this->collection->uksort($dummysort); + $this->assertSame($this->collection, $this->collection->uksort($dummysort)); uksort($assets, $dummysort); $this->assertEquals($assets, $this->collection->all()); } @@ -327,7 +315,7 @@ public function testKsort() { $stub3->id() => $stub3, ); - $this->collection->ksort(); + $this->assertSame($this->collection, $this->collection->ksort()); ksort($assets); $this->assertEquals($assets, $this->collection->all()); } @@ -351,7 +339,7 @@ public function testReverse() { $stub1->id() => $stub1, ); - $this->collection->reverse(); + $this->assertSame($this->collection, $this->collection->reverse()); $this->assertEquals($assets, $this->collection->all()); } @@ -359,7 +347,7 @@ public function testReverse() { * @covers ::addUnresolvedLibrary */ public function testAddUnresolvedLibrary() { - $this->collection->addUnresolvedLibrary('foo/bar'); + $this->assertSame($this->collection, $this->collection->addUnresolvedLibrary('foo/bar')); $this->assertAttributeContains('foo/bar', 'libraries', $this->collection); } @@ -383,7 +371,7 @@ public function testHasUnresolvedLibraries() { */ public function testClearUnresolvedLibraries() { $this->collection->addUnresolvedLibrary('foo/bar'); - $this->collection->clearUnresolvedLibraries(); + $this->assertSame($this->collection, $this->collection->clearUnresolvedLibraries()); $this->assertFalse($this->collection->hasUnresolvedLibraries()); } @@ -505,7 +493,7 @@ public function testResolveLibrariesAgain() { ->will($this->returnValue(array())); $this->collection->add($coll_asset); - $this->collection->resolveLibraries($repository); + $this->assertSame($this->collection, $this->collection->resolveLibraries($repository)); $expected = array( $coll_asset->id() => $coll_asset, diff --git a/core/tests/Drupal/Tests/Core/Asset/Collection/AssetLibraryTest.php b/core/tests/Drupal/Tests/Core/Asset/Collection/AssetLibraryTest.php index d70ef5b..bf94ea3 100644 --- a/core/tests/Drupal/Tests/Core/Asset/Collection/AssetLibraryTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/Collection/AssetLibraryTest.php @@ -7,10 +7,11 @@ namespace Drupal\Tests\Core\Asset\Collection; use Drupal\Core\Asset\Collection\AssetLibrary; +use Drupal\Core\Asset\Exception\FrozenObjectException; use Drupal\Tests\Core\Asset\AssetUnitTest; /** - * + * @coversDefaultClass \Drupal\Core\Asset\Collection\AssetLibrary * @group Asset */ class AssetLibraryTest extends AssetUnitTest { @@ -27,54 +28,233 @@ public function getLibraryFixture() { $library = new AssetLibrary(); $library->setTitle('foo') ->setVersion('1.2.3') - ->setWebsite('http://foo.bar') - ->addDependency('foo/bar'); + ->setWebsite('http://foo.bar'); return $library; } + /** + * These simply don't merit individual tests. + * + * @covers ::setWebsite + * @covers ::getWebsite + * @covers ::setVersion + * @covers ::getVersion + * @covers ::setTitle + * @covers ::getTitle + */ + public function testMetadataProps() { + $library = $this->getLibraryFixture(); + + $this->assertEquals('foo', $library->getTitle()); + $this->assertEquals('1.2.3', $library->getVersion()); + $this->assertEquals('http://foo.bar', $library->getWebsite()); + } + + /** + * @covers ::addDependency + */ public function testAddDependency() { $library = $this->getLibraryFixture(); - $library->addDependency('baz/bing'); - $this->assertEquals($library->getDependencyInfo(), array('foo/bar', 'baz/bing'), 'Dependencies added to library successfully.'); + + $this->assertSame($library, $library->addDependency('foo/bar')); + $this->assertAttributeContains('foo/bar', 'dependencies', $library); + + $invalid = array('foo', 'foo//bar', 0, 1.1, fopen(__FILE__, 'r'), TRUE, array(), new \stdClass); + + try { + foreach ($invalid as $val) { + $library->addDependency($val, $val); + $this->fail('Was able to create an ordering relationship with an inappropriate value.'); + } + } catch (\InvalidArgumentException $e) {} + } + + /** + * @depends testAddDependency + * @covers ::hasDependencies + */ + public function testHasDependencies() { + $library = $this->getLibraryFixture(); + $this->assertFalse($library->hasDependencies()); + + $library->addDependency('foo/bar'); + $this->assertTrue($library->hasDependencies()); + } + + /** + * @depends testAddDependency + * @covers ::getDependencyInfo + */ + public function testGetDependencyInfo() { + $library = $this->getLibraryFixture(); + $this->assertEmpty($library->getDependencyInfo()); + + $library->addDependency('foo/bar'); + $this->assertEquals(array('foo/bar'), $library->getDependencyInfo()); } + /** + * @depends testAddDependency + * @depends testHasDependencies + * @covers ::clearDependencies + */ public function testClearDependencies() { $library = $this->getLibraryFixture(); - $library->clearDependencies(); - $this->assertEmpty($library->getDependencyInfo(), 'Dependencies recorded in the library were cleared correctly.'); + $library->addDependency('foo/bar'); + + $this->assertSame($library, $library->clearDependencies()); + $this->assertFalse($library->hasDependencies()); } - public function testFrozenNonwriteability() { + /** + * @covers ::after + */ + public function testAfter() { $library = $this->getLibraryFixture(); - $library->freeze(); - try { - $library->setTitle('bar'); - $this->fail('No exception thrown when attempting to set a new title on a frozen library.'); - } - catch (\LogicException $e) {} + $dep = $this->createStubFileAsset(); - try { - $library->setVersion('2.3.4'); - $this->fail('No exception thrown when attempting to set a new version on a frozen library.'); - } - catch (\LogicException $e) {} + $this->assertSame($library, $library->after('foo')); + $this->assertSame($library, $library->after($dep)); - try { - $library->setWebsite('http://bar.baz'); - $this->fail('No exception thrown when attempting to set a new website on a frozen library.'); - } - catch (\LogicException $e) {} + $this->assertAttributeContains($dep, 'predecessors', $library); + + $invalid = array(0, 1.1, fopen(__FILE__, 'r'), TRUE, array(), new \stdClass); try { - $library->addDependency('bing', 'bang'); - $this->fail('No exception thrown when attempting to add a new dependency on a frozen library.'); - } - catch (\LogicException $e) {} + foreach ($invalid as $val) { + $library->after($val); + $this->fail('Was able to create an ordering relationship with an inappropriate value.'); + } + } catch (\InvalidArgumentException $e) {} + } + + /** + * @depends testAfter + * @covers ::hasPredecessors + */ + public function testHasPredecessors() { + $library = $this->getLibraryFixture(); + $this->assertFalse($library->hasPredecessors()); + + $library->after('foo'); + $this->assertTrue($library->hasPredecessors()); + } + + /** + * @depends testAfter + * @covers ::getPredecessors + */ + public function testGetPredecessors() { + $library = $this->getLibraryFixture(); + $this->assertEmpty($library->getPredecessors()); + + $library->after('foo'); + $this->assertEquals(array('foo'), $library->getPredecessors()); + } + + /** + * @depends testAfter + * @depends testHasPredecessors + * @covers ::clearPredecessors + */ + public function testClearPredecessors() { + $library = $this->getLibraryFixture(); + $library->after('foo'); + + $this->assertSame($library, $library->clearPredecessors()); + $this->assertFalse($library->hasPredecessors()); + } + + /** + * @covers ::before + */ + public function testBefore() { + $library = $this->getLibraryFixture(); + $dep = $this->createStubFileAsset(); + + $this->assertSame($library, $library->before('foo')); + $this->assertSame($library, $library->before($dep)); + + $this->assertAttributeContains($dep, 'successors', $library); + + $invalid = array(0, 1.1, fopen(__FILE__, 'r'), TRUE, array(), new \stdClass); try { - $library->clearDependencies(); - $this->fail('No exception thrown when attempting to clear dependencies from a frozen library.'); + foreach ($invalid as $val) { + $library->after($val); + $this->fail('Was able to create an ordering relationship with an inappropriate value.'); + } + } catch (\InvalidArgumentException $e) {} + } + + /** + * @depends testBefore + * @covers ::hasSuccessors + */ + public function testHasSuccessors() { + $library = $this->getLibraryFixture(); + $this->assertFalse($library->hasSuccessors()); + + $library->before('foo'); + $this->assertTrue($library->hasSuccessors()); + } + + /** + * @depends testBefore + * @covers ::getSuccessors + */ + public function testGetSuccessors() { + $library = $this->getLibraryFixture(); + $this->assertEmpty($library->getSuccessors()); + + $library->before('foo'); + $this->assertEquals(array('foo'), $library->getSuccessors()); + } + + /** + * @depends testBefore + * @covers ::clearSuccessors + */ + public function testClearSuccessors() { + $library = $this->getLibraryFixture(); + $library->before('foo'); + + $this->assertSame($library, $library->clearSuccessors()); + $this->assertFalse($library->hasSuccessors()); + } + + /** + * Tests that all methods that should be disabled by freezing the collection + * correctly trigger an exception. + * + * @covers ::freeze + * @covers ::isFrozen + * @covers ::attemptWrite + */ + public function testExceptionOnWriteWhenFrozen() { + $library = new AssetLibrary(); + $write_protected = array( + 'setTitle' => array('foo'), + 'setVersion' => array('foo'), + 'setWebsite' => array('foo'), + 'addDependency' => array('foo/bar'), + 'clearDependencies' => array(function() {}), + 'after' => array('foo'), + 'clearPredecessors' => array(), + 'before' => array('foo'), + 'clearSuccessors' => array(), + ); + + // No exception before freeze + list($method, $args) = each($write_protected); + call_user_func_array(array($library, $method), $args); + + $library->freeze(); + foreach ($write_protected as $method => $args) { + try { + call_user_func_array(array($library, $method), $args); + $this->fail(sprintf('Was able to run write method "%s" on frozen AssetLibrary', $method)); + } catch (FrozenObjectException $e) {} } - catch (\LogicException $e) {} } } diff --git a/core/tests/Drupal/Tests/Core/Asset/Collection/BasicAssetCollectionTest.php b/core/tests/Drupal/Tests/Core/Asset/Collection/BasicAssetCollectionTest.php index fc89f8a..71345ba 100644 --- a/core/tests/Drupal/Tests/Core/Asset/Collection/BasicAssetCollectionTest.php +++ b/core/tests/Drupal/Tests/Core/Asset/Collection/BasicAssetCollectionTest.php @@ -38,6 +38,10 @@ public function getBasicCollection() { /** * Method to return the appropriate collection type for the current test. * + * If demonstrating adherence to Liskov is desired, this test class can be + * extended and this method swapped out to provide the correct + * AssetCollectionBasicInterface object for testing. + * * @return AssetCollectionBasicInterface */ public function getCollection() { @@ -73,7 +77,7 @@ public function getThreeLeafBasicCollection() { public function testAdd() { $collection = $this->getCollection(); $asset = $this->createStubFileAsset(); - $this->assertTrue($collection->add($asset)); + $this->assertSame($collection, $collection->add($asset)); $this->assertAttributeContains($asset, 'assetStorage', $collection); $this->assertAttributeContains($asset, 'assetIdMap', $collection); @@ -88,20 +92,6 @@ public function testAdd() { } /** - * @depends testAdd - * @depends testEach - * @covers ::__construct - */ - public function testCreateWithAssets() { - $asset1 = $this->createStubFileAsset(); - $asset2 = $this->createStubFileAsset(); - $collection = $this->getMockForAbstractClass('\\Drupal\\Core\\Asset\\Collection\\BasicAssetCollection', array(array($asset1, $asset2))); - - $this->assertContains($asset1, $collection); - $this->assertContains($asset2, $collection); - } - - /** * @expectedException \Drupal\Core\Asset\Exception\UnsupportedAsseticBehaviorException * @covers ::add */ @@ -128,6 +118,20 @@ public function testEach() { /** * @depends testAdd + * @depends testEach + * @covers ::__construct + */ + public function testCreateWithAssets() { + $asset1 = $this->createStubFileAsset(); + $asset2 = $this->createStubFileAsset(); + $collection = $this->getMockForAbstractClass('\\Drupal\\Core\\Asset\\Collection\\BasicAssetCollection', array(array($asset1, $asset2))); + + $this->assertContains($asset1, $collection); + $this->assertContains($asset2, $collection); + } + + /** + * @depends testAdd * @covers ::eachLeaf * @covers \Drupal\Core\Asset\Collection\Iterator\RecursiveBasicCollectionIterator */ @@ -142,25 +146,6 @@ public function testEachLeaf() { } /** - * Tests that adding the same asset twice is disallowed. - * - * @depends testAdd - * @covers ::add - */ - public function testDoubleAdd() { - $collection = $this->getCollection(); - $asset = $this->createStubFileAsset(); - $this->assertTrue($collection->add($asset)); - - // Test by object identity - $this->assertFalse($collection->add($asset)); - // Test by id - $asset2 = $this->createStubFileAsset('css', $asset->id()); - - $this->assertFalse($collection->add($asset2)); - } - - /** * @depends testAdd * @covers ::contains */ @@ -185,7 +170,7 @@ public function testContains() { * @covers ::find * @expectedException \OutOfBoundsException */ - public function testGetById() { + public function testFind() { $collection = $this->getCollection(); $asset = $this->createStubFileAsset(); @@ -259,6 +244,58 @@ public function testRemove() { } /** + * @depends testAdd + * @depends testRemove + * @covers ::count + */ + public function testCount() { + $collection = $this->getCollection(); + $this->assertCount(0, $collection); + + $collection->add($this->getAggregate()); + $this->assertCount(0, $collection); + + $aggregate = $this->getAggregate(); + $asset = $this->createStubFileAsset(); + $aggregate->add($asset); + $collection->add($aggregate); + $this->assertCount(1, $collection); + + $collection->remove($aggregate); + $this->assertCount(0, $collection); + + $collection->add($asset); + $this->assertCount(1, $collection); + + $collection->remove($asset); + $this->assertCount(0, $collection); + } + + /** + * Tests that adding the same asset twice results in just one asset. + * + * @depends testAdd + * @depends testCount + * @covers ::add + */ + public function testDoubleAdd() { + $collection = $this->getCollection(); + $asset = $this->createStubFileAsset(); + + $collection->add($asset); + + // Test by object identity + $collection->add($asset); + $this->assertCount(1, $collection); + + // Test by id + $asset2 = $this->createStubFileAsset('css', $asset->id()); + + $collection->add($asset2); + $this->assertCount(1, $collection); + } + + /** * @depends testEach * @covers ::remove * @covers ::doRemove @@ -396,34 +433,6 @@ public function testIsEmpty() { } /** - * @depends testAdd - * @depends testRemove - * @covers ::count - */ - public function testCount() { - $collection = $this->getCollection(); - $this->assertCount(0, $collection); - - $collection->add($this->getAggregate()); - $this->assertCount(0, $collection); - - $aggregate = $this->getAggregate(); - $asset = $this->createStubFileAsset(); - $aggregate->add($asset); - $collection->add($aggregate); - $this->assertCount(1, $collection); - - $collection->remove($aggregate); - $this->assertCount(0, $collection); - - $collection->add($asset); - $this->assertCount(1, $collection); - - $collection->remove($asset); - $this->assertCount(0, $collection); - } - - /** * @covers ::remove */ public function testRemoveInvalidNeedle() {