From 9531faf8783a6345528b5ab724288c78b6b480a5 Mon Sep 17 00:00:00 2001 From: 1stthomas Date: Thu, 10 Mar 2022 23:49:24 +0100 Subject: [PATCH] #30 fix repository by readding classes and fixing tests --- src/Models/AbstractLoadableModel.php | 32 +++ src/Models/AbstractTransLoadableModel.php | 52 ++++ src/Models/Loadable.php | 36 +++ src/Models/TransLoadable.php | 37 +++ tests/Unit/ContainerLwTest_1.php | 170 +++++++++++++ tests/Unit/DummyTest.php | 18 ++ tests/Unit/EnumTest.php | 41 +++ tests/Unit/Lists/AbstractItemListTest.php | 226 +++++++++++++++++ tests/Unit/Lists/HashListTest.php | 237 ++++++++++++++++++ tests/Unit/Lists/ItemListTest.php | 88 +++++++ .../Traits/CanAddByPropertyNameTest.php | 7 +- 11 files changed, 938 insertions(+), 6 deletions(-) create mode 100644 src/Models/AbstractLoadableModel.php create mode 100644 src/Models/AbstractTransLoadableModel.php create mode 100644 src/Models/Loadable.php create mode 100644 src/Models/TransLoadable.php create mode 100644 tests/Unit/ContainerLwTest_1.php create mode 100644 tests/Unit/DummyTest.php create mode 100644 tests/Unit/EnumTest.php create mode 100644 tests/Unit/Lists/AbstractItemListTest.php create mode 100644 tests/Unit/Lists/HashListTest.php create mode 100644 tests/Unit/Lists/ItemListTest.php diff --git a/src/Models/AbstractLoadableModel.php b/src/Models/AbstractLoadableModel.php new file mode 100644 index 0000000..3a0d322 --- /dev/null +++ b/src/Models/AbstractLoadableModel.php @@ -0,0 +1,32 @@ +load($data); + } + + public function load(array $data) + { + foreach ($data as $name => $value) { + $this->addByPropertyName($name, $value); + } + } + +} diff --git a/src/Models/AbstractTransLoadableModel.php b/src/Models/AbstractTransLoadableModel.php new file mode 100644 index 0000000..50a6b03 --- /dev/null +++ b/src/Models/AbstractTransLoadableModel.php @@ -0,0 +1,52 @@ +setTransformations($transformations); + + $this->load($data); + } + + public function getTransformations() + { + return $this->transformations; + } + + public function load(array $data) + { + $transformations = $this->getTransformations(); + + foreach ($data as $name => $value) { + if (array_key_exists($name, $transformations)) { + $name = $transformations[$name]; + } + + $this->addByPropertyName($name, $value); + } + } + + public function setTransformations(array $transformations) + { + $this->transformations = $transformations; + } + +} diff --git a/src/Models/Loadable.php b/src/Models/Loadable.php new file mode 100644 index 0000000..59fe823 --- /dev/null +++ b/src/Models/Loadable.php @@ -0,0 +1,36 @@ +getMockBuilder($className) + ->setMethods(['bind']) + ->disableOriginalConstructor() + ->getMock(); + + $reflectedClass = new \ReflectionClass($className); + $propBindings = $reflectedClass->getProperty('bindings'); + $propBindings->setAccessible(true); + $propInstances = $reflectedClass->getProperty('instances'); + $propInstances->setAccessible(true); + + $this->assertNull($propBindings->getValue($mock)); + $this->assertNull($propInstances->getValue($mock)); + + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($mock); + + $this->assertIsArray($propBindings->getValue($mock)); + $this->assertEmpty($propBindings->getValue($mock)); + $this->assertIsArray($propInstances->getValue($mock)); + $this->assertEmpty($propInstances->getValue($mock)); + } + public function testGetInstance() + { + $this->assertInstanceOf(ContainerLw::class, ContainerLw::getInstance()); + } + public function testGetInstanceSingleton() + { + $this->assertSame(ContainerLw::getInstance(), ContainerLw::getInstance()); + } + public function testBind() + { + $className = ContainerLw::class; + + $mock = $this->getMockBuilder($className) + ->setMethods(['bound']) + ->disableOriginalConstructor() + ->getMock(); + + $reflectedClass = new \ReflectionClass($className); + $prop = $reflectedClass->getProperty('bindings'); + $prop->setAccessible(true); + $prop->setValue($mock, []); + + $mock->bind('ht7/test'); + + $this->assertArrayHasKey('ht7/test', $prop->getValue($mock)); + $this->assertNull($prop->getValue($mock)['ht7/test']); + + $mock->bind('ht7/test/exception', \InvalidArgumentException::class); + + $this->assertArrayHasKey('ht7/test/exception', $prop->getValue($mock)); + $this->assertEquals(\InvalidArgumentException::class, $prop->getValue($mock)['ht7/test/exception']); + } + public function testBond() + { + $className = ContainerLw::class; + + $bindings = ['ht7/test' => null]; + + $mock = $this->getMockBuilder($className) + ->setMethods(['getBindings']) + ->disableOriginalConstructor() + ->getMock(); + $mock->expects($this->exactly(3)) + ->method('getBindings') + ->willReturn($bindings); + + $this->assertIsBool($mock->bound('ht7/test')); + $this->assertTrue($mock->bound('ht7/test')); + $this->assertFalse($mock->bound('ht7/test1')); + } +// public function testGet() +// { +// $className = ContainerLw::class; +// +// $bindings = ['ht7/test' => 'expected binding']; +// +// $mock = $this->getMockBuilder($className) +// ->setMethods(['getBindings']) +// ->disableOriginalConstructor() +// ->getMock(); +// $mock->expects($this->exactly(1)) +// ->method('getBindings') +// ->willReturn($bindings); +// +// $this->assertEquals($bindings['ht7/test'], $mock->get('ht7/test')); +// } + + public function testGet() + { + $className = ContainerLw::class; + + $bindings = ['ht7/test' => 'expected binding']; + + $mock = $this->getMockBuilder($className) + ->setMethods(['resolve']) + ->disableOriginalConstructor() + ->getMock(); + $mock->expects($this->exactly(1)) + ->method('resolve') + ->willReturn($bindings['ht7/test']); + + $this->assertEquals($bindings['ht7/test'], $mock->get('ht7/test')); + } +// public function testGetExceptionContainer() +// { +// $className = ContainerLw::class; +// +// $excBinding = [ +// 'ht7/exc' => function() { +// throw new \Exception(); +// } +// ]; +// $errBinding = ['exc/container/psr/container' => ContainerResolvingException::class]; +// +// $mock = $this->getMockBuilder($className) +// ->setMethods(['has', 'getBindings']) +// ->disableOriginalConstructor() +// ->getMock(); +// $mock->expects($this->exactly(1)) +// ->method('has') +// ->willReturn(true); +// $mock->expects($this->exactly(2)) +// ->method('getBindings') +//// ->will($this->returnCallback(function() { +// ->willReturnOnConsecutiveCalls($excBinding, $errBinding); +//// ->willReturnOnConsecutiveCalls($excBinding, $errBinding); +//// ->willReturn($excBinding, $errBinding); +//// ->will($this->returnValueMap([$bindings,])); +//// ->willReturn($bindings); +// +// $this->expectException(ContainerResolvingException::class); +// +// $mock->get('ht7/exc'); +// } + + public function testGetExceptionEntryNotFound() + { + $className = ContainerLw::class; + + $mock = $this->getMockBuilder($className) + ->setMethods(['getBindings']) + ->disableOriginalConstructor() + ->getMock(); + $mock->expects($this->exactly(2)) + ->method('getBindings') + ->willReturn([], ['exc/container/psr/notfound' => EntryNotFoundException::class]); + + $this->expectException(EntryNotFoundException::class); + + $mock->get('ht7/not_found'); + } +// public function testGetBindings +} diff --git a/tests/Unit/DummyTest.php b/tests/Unit/DummyTest.php new file mode 100644 index 0000000..3cb1156 --- /dev/null +++ b/tests/Unit/DummyTest.php @@ -0,0 +1,18 @@ +assertTrue($dummy->getDummy()); + } + +} diff --git a/tests/Unit/EnumTest.php b/tests/Unit/EnumTest.php new file mode 100644 index 0000000..0768943 --- /dev/null +++ b/tests/Unit/EnumTest.php @@ -0,0 +1,41 @@ +object = new EnumImplementation(); + } + /** + * Test to get a defined constant by comparing the expected value. An undefined + * constant will throw an exception. This case is tested by this method too. + */ + public function testGetConstant() + { + $this->assertEquals('test 1', EnumImplementation::getConstant('TEST_1')); + + $this->expectException(UndefinedConstantException::class); + + EnumImplementation::getConstant('test_11111'); + } + /** + * Test setting an undefined property on the enum, which should throw an + * exception. + * This functionallity is implemented by a trait. + */ + public function testSet() + { + $this->expectException(InvalidArgumentException::class); + + $this->object->test = 'Should throw an exception.'; + } +} diff --git a/tests/Unit/Lists/AbstractItemListTest.php b/tests/Unit/Lists/AbstractItemListTest.php new file mode 100644 index 0000000..e8d7009 --- /dev/null +++ b/tests/Unit/Lists/AbstractItemListTest.php @@ -0,0 +1,226 @@ +getMockForAbstractClass($className, [], '', true, true, true, ['load']); + + $stub->expects($this->once()) + ->method('load') + ->with($this->equalTo($items)); + + $reflectedClass = new \ReflectionClass($className); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($stub, $items); + } + public function testCount() + { + $className = AbstractItemList::class; + $items = [1, 2, 3, 4, 5]; + + $stub = $this->getMockForAbstractClass($className, [], '', true, true, true, ['getAll']); + + $stub->expects($this->once()) + ->method('getAll') + ->willReturn($items); + + $this->assertCount(5, $stub); + } + public function testGet() + { + $className = AbstractItemList::class; + $items = [1, 2, 3, 4, 5]; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + foreach ($items as $key => $value) { + $this->assertEquals($value, $stub->get($key)); + } + } + public function testGetAll() + { + $className = AbstractItemList::class; + $items = [1, 2, 3, 4, 5]; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $this->assertEquals($items, $stub->getAll()); + } + public function testGetIterator() + { + $className = AbstractItemList::class; + + $items = [ + 'test_1' => 'test 1', + 'test_2' => 'test 2', + 'test_3' => 'test 3', + ]; + + $stub = $this->getMockBuilder($className) + ->setMethods(['getAll']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $stub->expects($this->once()) + ->method('getAll') + ->willReturn($items); + + $it = $stub->getIterator(); + + $this->assertInstanceOf(SimpleIndexIterator::class, $it); + + $reflectedClass = new \ReflectionClass(SimpleIndexIterator::class); + $property = $reflectedClass->getProperty('array'); + $property->setAccessible(true); + + $this->assertEquals($items, $property->getValue($it)); + } + public function testGetNext() + { + $className = AbstractItemList::class; + + $items = [1, 20, 300, 4000, 50000]; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $this->assertEquals(50000, $stub->getNext(3)); + + $this->assertEquals(null, $stub->getNext(4)); + } + public function testGetPrevious() + { + $className = AbstractItemList::class; + + $items = [1, 20, 300, 4000, 50000]; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $this->assertEquals(300, $stub->getPrevious(3)); + + $this->assertEquals(null, $stub->getPrevious(0)); + } + public function testHas() + { + $className = AbstractItemList::class; + $items = [1, 2, 0, 3, 4, 5]; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $this->assertTrue($stub->has(0)); + $this->assertTrue($stub->has(2)); + $this->assertTrue($stub->has(5)); + $this->assertFalse($stub->has(6)); + $this->assertFalse($stub->has(10)); + } + public function testHasByValue() + { + $className = AbstractItemList::class; + $items = [1, 2, 0, 3, 4, 5]; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $this->assertTrue($stub->hasByValue(0)); + $this->assertTrue($stub->hasByValue(2)); + $this->assertTrue($stub->hasByValue(5)); + $this->assertFalse($stub->hasByValue(6)); + $this->assertFalse($stub->hasByValue(10)); + } + public function testLoad() + { + $className = AbstractItemList::class; + $items = [1, 2, 0, 3, 4, 5]; + + $stub = $this->getMockForAbstractClass($className); + + $stub->expects($this->exactly(6)) + ->method('add') + ->withConsecutive( + [$this->equalTo(1)], + [$this->equalTo(2)], + [$this->equalTo(0)], + [$this->equalTo(3)], + [$this->equalTo(4)], + [$this->equalTo(5)] + ); + + $stub->load($items); + } + public function testRemove() + { + $className = AbstractItemList::class; + $items = [1, 2, 0, 3, 3, 4, 5]; + $itemsNew = [ + 0 => 1, + 1 => 2, + 2 => 0, + 3 => 3, + 5 => 4, + 6 => 5 + ]; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $stub->remove(4); + + $this->assertEquals($itemsNew, $property->getValue($stub)); + } + public function testHandleInvalidIndex() + { + $className = AbstractItemList::class; + + $stub = $this->getMockForAbstractClass($className); + + $reflectedClass = new \ReflectionClass($className); + $method = $reflectedClass->getMethod('handleInvalidIndex'); + $method->setAccessible(true); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessageMatches('/Invalid index(.)+invalid_index/'); + + $method->invoke($stub, 'invalid_index'); + } +} diff --git a/tests/Unit/Lists/HashListTest.php b/tests/Unit/Lists/HashListTest.php new file mode 100644 index 0000000..ef6c549 --- /dev/null +++ b/tests/Unit/Lists/HashListTest.php @@ -0,0 +1,237 @@ +getMockBuilder($className) + ->setMethods(['load']) + ->disableOriginalConstructor() + ->getMock(); + + $mock->expects($this->once()) + ->method('load') + ->with($this->equalTo($items)); + + $reflectedClass = new \ReflectionClass($className); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($mock, $items); + } + + public function testAdd() + { + $mock = $this->createMock(HashListItemImplementation::class); + + $mock->expects($this->once()) + ->method('getHash') + ->willReturn('key1'); + + $stub = $this->getMockBuilder(HashList::class) + ->setMethods(['load']) + ->disableOriginalConstructor() + ->getMock(); + + $stub->add($mock); + + $reflectedClass = new \ReflectionClass(HashList::class); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + + $this->assertArrayHasKey('key1', $property->getValue($stub)); + + $mock2 = $this->createMock(HashListItemImplementation::class); + + $mock2->expects($this->once()) + ->method('getHash') + ->willReturn('key2'); + + $stub->add($mock2); + + $this->assertArrayHasKey('key2', $property->getValue($stub)); + } + + public function testaddWithExpection() + { + $mock = $this->getMockBuilder(HashList::class) + ->setMethods(['load']) + ->disableOriginalConstructor() + ->getMock(); + + $this->expectException(\InvalidArgumentException::class); + + $mock->add('123 yeah!'); + } + + public function testGetIterator() + { + $className = HashList::class; + + $items = [ + 'test_1' => 'test 1', + 'test_2' => 'test 2', + 'test_3' => 'test 3', + ]; + + $stub = $this->getMockBuilder($className) + ->setMethods(['getAll']) + ->disableOriginalConstructor() + ->getMock(); + $stub->expects($this->once()) + ->method('getAll') + ->willReturn($items); + + $it = $stub->getIterator(); + + $this->assertInstanceOf(SimpleAssocIterator::class, $it); + + $reflectedClass = new \ReflectionClass(SimpleAssocIterator::class); + $property = $reflectedClass->getProperty('array'); + $property->setAccessible(true); + + $this->assertEquals($items, $property->getValue($it)); + } + + public function testGetNext() + { + $className = HashList::class; + + $items = [ + 'test_1' => 'test 1', + 'test_2' => 'test 2', + 'test_3' => 'test 3', + ]; + $indexInvalid = 'test_4'; + + $stub = $this->getMockBuilder($className) + ->setMethods(['handleInvalidIndex']) + ->disableOriginalConstructor() + ->getMock(); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $this->assertEquals('test 3', $stub->getNext('test_2')); + + $this->assertEquals(null, $stub->getNext('test_3')); + + $stub->expects($this->once()) + ->method('handleInvalidIndex') + ->with($indexInvalid); + + $stub->getNext('test_4'); + } + + public function testGetPrevious() + { + $className = HashList::class; + + $items = [ + 'test_1' => 'test 1', + 'test_2' => 'test 2', + 'test_3' => 'test 3', + ]; + $indexInvalid = 'test_4'; + + $stub = $this->getMockBuilder($className) + ->setMethods(['handleInvalidIndex']) + ->disableOriginalConstructor() + ->getMock(); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $property->setValue($stub, $items); + + $this->assertEquals('test 1', $stub->getPrevious('test_2')); + + $this->assertEquals(null, $stub->getPrevious('test_1')); + + $stub->expects($this->once()) + ->method('handleInvalidIndex') + ->with($indexInvalid); + + $stub->getPrevious($indexInvalid); + } + + public function testMerge() + { + $className = HashList::class; + $items1 = [ + 'item1' => 'val11', + 'item2' => 'val12', + 'item3' => 'val13', + 'item4' => 'val14', + 'item5' => 'val15', + 'item6' => 'val16', + 'item7' => 'val17', + ]; + $items2 = [ + 'item1' => 'val21', + 'item12' => 'val22', + 'item3' => 'val23', + 'item4' => 'val24', + 'item5' => 'val25', + 'item16' => 'val26', + 'item7' => 'val27', + ]; + $expected = [ + 'item1' => 'val11', + 'item12' => 'val22', + 'item3' => 'val13', + 'item4' => 'val14', + 'item5' => 'val15', + 'item16' => 'val26', + 'item7' => 'val17', + 'item2' => 'val12', + 'item6' => 'val16' + ]; + + $mock1 = $this->getMockBuilder($className) + ->setMethods(['getAll']) + ->disableOriginalConstructor() + ->getMock(); + $mock1->expects($this->once()) + ->method('getAll') + ->willReturn($items1); + + $mock2 = $this->getMockBuilder($className) + ->setMethods(['getAll']) + ->disableOriginalConstructor() + ->getMock(); + $mock2->expects($this->once()) + ->method('getAll') + ->willReturn($items2); + + $mock1->merge($mock2); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $actual = $property->getValue($mock1); + + $this->assertSame($expected, $actual); + } + +} diff --git a/tests/Unit/Lists/ItemListTest.php b/tests/Unit/Lists/ItemListTest.php new file mode 100644 index 0000000..f226e63 --- /dev/null +++ b/tests/Unit/Lists/ItemListTest.php @@ -0,0 +1,88 @@ +getMockBuilder($className) + ->setMethods(['load']) + ->disableOriginalConstructor() + ->getMock(); + + $mock->expects($this->once()) + ->method('load') + ->with($this->equalTo($items)); + + $reflectedClass = new \ReflectionClass($className); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($mock, $items); + } + + public function testAdd() + { + // see: https://www.webtipblog.com/unit-testing-private-methods-and-properties-with-phpunit/ + $className = ItemList::class; + + $mock = $this->getMockBuilder($className) + ->setMethods(['load']) + ->getMock(); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + + $this->assertEquals([], $property->getValue($mock)); + + $mock->add('test text'); + + $this->assertEquals(['test text'], $property->getValue($mock)); + + $mock->add(123); + + $this->assertEquals(['test text', 123], $property->getValue($mock)); + } + + public function testMerge() + { + $className = ItemList::class; + $items1 = [1, 2, 3]; + $items2 = [1, 2, 4, 3]; + $expected = [1, 2, 3, 1, 2, 4, 3]; + + $mock1 = $this->getMockBuilder($className) + ->setMethods(['getAll']) + ->disableOriginalConstructor() + ->getMock(); + $mock1->expects($this->once()) + ->method('getAll') + ->willReturn($items1); + + $mock2 = $this->getMockBuilder($className) + ->setMethods(['getAll']) + ->disableOriginalConstructor() + ->getMock(); + $mock2->expects($this->once()) + ->method('getAll') + ->willReturn($items2); + + $mock1->merge($mock2); + + $reflectedClass = new \ReflectionClass($className); + $property = $reflectedClass->getProperty('items'); + $property->setAccessible(true); + $actual = $property->getValue($mock1); + + $this->assertSame($expected, $actual); + } + +} diff --git a/tests/Unit/Utility/Traits/CanAddByPropertyNameTest.php b/tests/Unit/Utility/Traits/CanAddByPropertyNameTest.php index aea4dc2..c329331 100644 --- a/tests/Unit/Utility/Traits/CanAddByPropertyNameTest.php +++ b/tests/Unit/Utility/Traits/CanAddByPropertyNameTest.php @@ -11,7 +11,6 @@ */ class CanAddByPropertyNameTest extends TestCase { - public function testAddByPropertyName() { $items = [ @@ -23,7 +22,6 @@ public function testAddByPropertyName() { use CanAddByPropertyName; - protected $testOne; protected $testTwo; @@ -31,7 +29,6 @@ public function setTestProperty1($test1) { return $this->testOne = $test1; } - public function setTestProperty2($test2) { $this->testTwo = $test2; @@ -53,15 +50,13 @@ public function setTestProperty2($test2) $this->assertEquals($items['testProperty1'], $testProperty1->getValue($mock)); $this->assertEquals($items['testProperty2'], $testProperty2->getValue($mock)); } - public function testAddByPropertyNameWithException() { $mock = $this->getMockForTrait(CanAddByPropertyName::class); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessageRegExp('/(U|u)nkown property(.)+unknownProperty/'); + $this->expectExceptionMessageMatches('/(U|u)nkown property(.)+unknownProperty/'); $mock->addByPropertyName('unknownProperty', 'value'); } - }