xero_sync-8.x-1.x-dev/tests/src/Unit/ItemFinderTest.php
tests/src/Unit/ItemFinderTest.php
<?php
namespace Drupal\Tests\xero_sync\Unit;
use Drupal\Tests\UnitTestCase;
use Drupal\entity_test\Entity\EntityTest;
use Drupal\xero_sync\Plugin\XeroSync\ItemFinder\ItemFinderInterface;
use Drupal\xero\TypedData\XeroComplexItemInterface;
/**
* @coversDefaultClass \Drupal\xero_sync\XeroSyncItemFinder
* @group xero_sync
*/
class ItemFinderTest extends UnitTestCase {
/**
* The item finder.
*
* @var \Drupal\xero_sync\XeroSyncItemFinder
*/
protected $itemFinder;
/**
* The Xero Sync entity handler.
*
* @var \Drupal\xero_sync\XeroSyncEntityHandlerInterface
*/
protected $entityHandler;
/**
* The discovered plugin definitions.
*
* @var array
*/
protected $definitions;
/**
* The entity to find items for.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
protected $entity;
/**
* {@inheritdoc}
*/
public function setUp(): void {
parent::setUp();
$this->entity = $this->createMock(EntityTest::class);
$this->entity->expects($this->any())
->method('id')
->willReturn('test_id');
$this->entity->expects($this->any())
->method('getEntityTypeId')
->willReturn('entity_test');
$this->definitions = [
'test1' => [
'id' => 'test1',
'entity_types' => ['entity_test'],
'create' => TRUE,
'priority' => 0,
],
'test2' => [
'id' => 'test2',
'entity_types' => ['entity_test', 'user'],
'create' => FALSE,
'priority' => 60,
],
'test3' => [
'id' => 'test3',
'entity_types' => ['entity_test'],
'create' => FALSE,
'priority' => 50,
],
'test4' => [
'id' => 'test4',
'entity_types' => [],
'create' => FALSE,
'priority' => 100,
],
'test5' => [
'id' => 'test5',
'entity_types' => ['user'],
'create' => FALSE,
],
];
$this->item = $this->createMock(XeroComplexItemInterface::class);
}
/**
* Test what plugins definitions match when creation is allowed.
*/
public function testGetMatchingDefinitionsCreateTrue() {
$itemFinder = new TestItemFinder($this->definitions, []);
$matches = $itemFinder->getMatchingDefinitions($this->entity, TRUE);
$matchedIds = array_keys($matches);
$this->assertEquals(['test4', 'test2', 'test3', 'test1'], $matchedIds);
}
/**
* Test what plugins definitions match when creation is not allowed.
*/
public function testGetMatchingDefinitionsCreateFalse() {
$itemFinder = new TestItemFinder($this->definitions, []);
$matches = $itemFinder->getMatchingDefinitions($this->entity, FALSE);
$matchedIds = array_keys($matches);
$this->assertEquals(['test4', 'test2', 'test3'], $matchedIds);
}
/**
* Test the first plugin succeeding.
*/
public function testGetItemFromDefinitionsFirst() {
$plugins = [
'test1' => $this->getMockPlugin($this->item),
];
$itemFinder = new TestItemFinder($this->definitions, $plugins);
$item = $itemFinder->getItemFromDefinitions($this->definitions, $this->entity);
$this->assertSame($item, $this->item);
}
/**
* Test the first plugin failing and the second succeeding.
*/
public function testGetItemFromDefinitionsSecond() {
$plugins = [
'test1' => $this->getMockPlugin(NULL),
'test2' => $this->getMockPlugin($this->item),
];
$itemFinder = new TestItemFinder($this->definitions, $plugins);
$item = $itemFinder->getItemFromDefinitions($this->definitions, $this->entity);
$this->assertSame($item, $this->item);
}
/**
* Test what happens when no plugin succeeds in finding an item.
*/
public function testGetItemFromDefinitionsNone() {
$plugins = [
'test1' => $this->getMockPlugin(NULL),
'test2' => $this->getMockPlugin(NULL),
'test3' => $this->getMockPlugin(NULL),
'test4' => $this->getMockPlugin(NULL),
'test5' => $this->getMockPlugin(NULL),
];
$itemFinder = new TestItemFinder($this->definitions, $plugins);
$item = $itemFinder->getItemFromDefinitions($this->definitions, $this->entity);
$this->assertSame($item, NULL);
}
/**
* Test what happens when item creation is allowed and necessary.
*/
public function testGetItemCreate() {
$plugins = [
'test4' => $this->getMockPlugin(NULL),
'test2' => $this->getMockPlugin(NULL),
'test3' => $this->getMockPlugin(NULL),
'test1' => $this->getMockPlugin($this->item),
];
$itemFinder = new TestItemFinder($this->definitions, $plugins);
// If we're not allowed to create, then test1 is not used so no item found.
$item = $itemFinder->getItem($this->entity, FALSE);
$this->assertNull($item);
// If we're allowed to create, then test1 is used despite the cached null.
$item2 = $itemFinder->getItem($this->entity, TRUE);
$this->assertSame($item2, $this->item);
}
/**
* Test what happens when the first plugin fails but second succeeds.
*/
public function testGetItemSecond() {
$plugins = [
'test4' => $this->getMockPlugin(NULL),
'test2' => $this->getMockPlugin($this->item),
];
$itemFinder = new TestItemFinder($this->definitions, $plugins);
$item = $itemFinder->getItem($this->entity);
$this->assertSame($item, $this->item);
}
/**
* Test what happens when there is a cached result available.
*/
public function testGetItemCached() {
$plugins = [
'test4' => $this->getMockPlugin($this->item, $this->once()),
];
$itemFinder = new TestItemFinder($this->definitions, $plugins);
$item = $itemFinder->getItem($this->entity);
$this->assertSame($item, $this->item);
// Calling again should be OK even though
// the mock plugin from ::getMockPlugin only expects to be called once
// because itemFinder users a static cache.
$item2 = $itemFinder->getItem($this->entity);
$this->assertSame($item2, $this->item);
}
/**
* Test caching for unsuccessful plugins.
*/
public function testGetItemCacheNull() {
$plugins = [
'test4' => $this->getMockPlugin(NULL, $this->once()),
'test2' => $this->getMockPlugin(NULL, $this->once()),
'test3' => $this->getMockPlugin(NULL, $this->once()),
];
$itemFinder = new TestItemFinder($this->definitions, $plugins);
$item = $itemFinder->getItem($this->entity);
$this->assertNull($item);
// Calling again should be OK even though
// the mock plugin from ::getMockPlugin only expects to be called once
// because itemFinder users a static cache.
$item = $itemFinder->getItem($this->entity);
$this->assertNull($item);
}
/**
* Test the getItemFromCache method.
*
* @param string $type
* The Xero item's type.
* @param string $id
* The Xero item's guid.
* @param bool $create
* Whether creating the item is allowed.
* @param mixed $expected
* What to expect the plugin to return.
* @param array $items
* Available Xero items.
*
* @dataProvider providerGetItemFromCache
*/
public function testGetItemFromCache($type, $id, $create, $expected, array $items) {
$cache = [
'test_type' => [
'entity_1' => [
'item' => $items[0],
'create' => TRUE,
],
'entity_2' => [
'item' => $items[1],
'create' => FALSE,
],
'entity_3' => [
'item' => NULL,
'create' => FALSE,
],
'entity_4' => [
'item' => NULL,
'create' => TRUE,
],
],
];
$itemFinder = new TestItemFinder([], [], $cache);
$actual = $itemFinder->getItemFromCache($type, $id, $create);
$this->assertSame($expected, $actual);
}
/**
* Data provider for testGetItemFromCache().
*
* @return array
* An array of scenarios.
*/
public function providerGetItemFromCache() {
$items = [
$this->createMock(XeroComplexItemInterface::class),
$this->createMock(XeroComplexItemInterface::class),
];
return [
'Missing type' => [
'type' => 'different_type',
'id' => 'entity_1',
'create' => FALSE,
'expected' => NULL,
'items' => $items,
],
'Missing id' => [
'type' => 'test_type',
'id' => 'different_id',
'create' => FALSE,
'expected' => NULL,
'items' => $items,
],
'Create, and create not yet tried' => [
'type' => 'test_type',
'id' => 'entity_3',
'create' => TRUE,
'expected' => NULL,
'items' => $items,
],
'No create, and create not yet tried' => [
'type' => 'test_type',
'id' => 'entity_3',
'create' => FALSE,
'expected' => FALSE,
'items' => $items,
],
'Create, and create tried' => [
'type' => 'test_type',
'id' => 'entity_4',
'create' => TRUE,
'expected' => FALSE,
'items' => $items,
],
'No create, and create tried' => [
'type' => 'test_type',
'id' => 'entity_4',
'create' => FALSE,
'expected' => FALSE,
'items' => $items,
],
'Create, and cache hit with create' => [
'type' => 'test_type',
'id' => 'entity_1',
'create' => TRUE,
'expected' => $items[0],
'items' => $items,
],
'No create, and cache hit with create' => [
'type' => 'test_type',
'id' => 'entity_1',
'create' => FALSE,
'expected' => $items[0],
'items' => $items,
],
'Create, and cache hit without create' => [
'type' => 'test_type',
'id' => 'entity_2',
'create' => TRUE,
'expected' => $items[1],
'items' => $items,
],
'No create, and cache hit without create' => [
'type' => 'test_type',
'id' => 'entity_2',
'create' => FALSE,
'expected' => $items[1],
'items' => $items,
],
];
}
/**
* Get a mock item finder plugin.
*
* @param \Drupal\xero\TypedData\XeroComplexItemInterface|null $return
* The result to return from the plugin's getItem() method.
* @param mixed $expects
* The argument to pass along to the mock's expect() method.
*
* @return \PHPUnit_Framework_MockObject_MockObject
* A mock item finder plugin.
*/
protected function getMockPlugin($return, $expects = NULL) {
if (!$expects) {
$expects = $this->any();
}
$plugin = $this->createMock(ItemFinderInterface::class);
$plugin->expects($expects)
->method('getItem')
->willReturn($return);
return $plugin;
}
}
